mirror of
https://github.com/bitwarden/server
synced 2025-12-31 15:43:16 +00:00
Merge branch 'master' into flexible-collections/deprecate-custom-collection-perm
# Conflicts: # src/Api/AdminConsole/Controllers/OrganizationUsersController.cs # src/Api/Vault/AuthorizationHandlers/Collections/CollectionAuthorizationHandler.cs # test/Api.Test/Vault/AuthorizationHandlers/CollectionAuthorizationHandlerTests.cs
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
using Bit.Core.Auth.Models.Api.Request.Accounts;
|
||||
using Bit.IntegrationTestCommon.Factories;
|
||||
using IdentityServer4.AccessTokenValidation;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
@@ -27,12 +27,12 @@ public class ApiApplicationFactory : WebApplicationFactoryBase<Startup>
|
||||
builder.ConfigureTestServices(services =>
|
||||
{
|
||||
// Remove scheduled background jobs to prevent errors in parallel test execution
|
||||
var jobService = services.First(sd => sd.ServiceType == typeof(Microsoft.Extensions.Hosting.IHostedService) && sd.ImplementationType == typeof(Bit.Api.Jobs.JobsHostedService));
|
||||
var jobService = services.First(sd => sd.ServiceType == typeof(IHostedService) && sd.ImplementationType == typeof(Jobs.JobsHostedService));
|
||||
services.Remove(jobService);
|
||||
|
||||
services.PostConfigure<IdentityServerAuthenticationOptions>(IdentityServerAuthenticationDefaults.AuthenticationScheme, options =>
|
||||
services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
|
||||
{
|
||||
options.JwtBackChannelHandler = _identityApplicationFactory.Server.CreateHandler();
|
||||
options.BackchannelHttpHandler = _identityApplicationFactory.Server.CreateHandler();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -364,6 +364,24 @@
|
||||
"Microsoft.Win32.Registry": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "4HVjzx1F8v5J+U7oa8RGAQGj2QzmzNSu87r18Sh+dlh10uyZZL8teAaT/FaVLDObnfItGdPFvN8mwpF/HkI3Xw==",
|
||||
"dependencies": {
|
||||
"Duende.IdentityServer.Storage": "6.0.4",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "s5gAjfbpr2IMgI+fU2Nx+2AZdzstmbt9gpo13iX7GwvqSeSaBVqj9ZskAN0R2KF1OemPdZuGnfaTcevdXMUrrw==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "6.0.0",
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Fare": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
@@ -408,49 +426,8 @@
|
||||
},
|
||||
"IdentityModel": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==",
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "11.0.2",
|
||||
"System.Text.Encodings.Web": "4.7.0"
|
||||
}
|
||||
},
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0",
|
||||
"IdentityServer4.Storage": "4.1.2",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0",
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0",
|
||||
"Newtonsoft.Json": "12.0.2"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.AccessTokenValidation": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.1",
|
||||
"contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==",
|
||||
"dependencies": {
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0"
|
||||
}
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "eVHCR7a6m/dm5RFcBzE3qs/Jg5j9R5Rjpu8aTOv9e4AFvaQtBXb5ah7kmwU+YwA0ufRwz4wf1hnIvsD2hSnI4g=="
|
||||
},
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": {
|
||||
"type": "Transitive",
|
||||
@@ -551,10 +528,10 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "cJxdro36spFzk/K2OFCddM6vZ+yoj6ug8mTFRH3Gdv1Pul/buSuCtfb/FSCp31UmS5S4C1315dU7wX3ErLFuDg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0"
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Cryptography.Internal": {
|
||||
@@ -587,8 +564,8 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.32",
|
||||
"contentHash": "MPL4iVyiaRxnOUY5VATHjvhDWaAEFb77KFiUxVRklv3Z3v+STofUr1UG/aCt1O9cgN7FVTDaC5A7U+zsLub8Xg=="
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "Z/UU4NEBm5UgNufJmw+j5baW26ytCOIZ0G7sZocPaOzsUeBon1bkM3lSMNZQG2GmDjAIVP2XMSODf2jzSGbibw=="
|
||||
},
|
||||
"Microsoft.AspNetCore.Mvc.Testing": {
|
||||
"type": "Transitive",
|
||||
@@ -3154,25 +3131,25 @@
|
||||
"AspNetCore.HealthChecks.SqlServer": "[6.0.2, )",
|
||||
"AspNetCore.HealthChecks.Uris": "[6.0.3, )",
|
||||
"Azure.Messaging.EventGrid": "[4.10.0, )",
|
||||
"Commercial.Core": "[2023.10.2, )",
|
||||
"Commercial.Infrastructure.EntityFramework": "[2023.10.2, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"SharedWeb": "[2023.10.2, )",
|
||||
"Commercial.Core": "[2023.10.3, )",
|
||||
"Commercial.Infrastructure.EntityFramework": "[2023.10.3, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"SharedWeb": "[2023.10.3, )",
|
||||
"Swashbuckle.AspNetCore": "[6.5.0, )"
|
||||
}
|
||||
},
|
||||
"commercial.core": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )"
|
||||
"Core": "[2023.10.3, )"
|
||||
}
|
||||
},
|
||||
"commercial.infrastructure.entityframework": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.2, )"
|
||||
"Core": "[2023.10.3, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.3, )"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
@@ -3180,7 +3157,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "[4.17.0, )",
|
||||
"AutoFixture.Xunit2": "[4.17.0, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )",
|
||||
"Microsoft.NET.Test.Sdk": "[17.1.0, )",
|
||||
"NSubstitute": "[4.3.0, )",
|
||||
@@ -3202,10 +3179,9 @@
|
||||
"BitPay.Light": "[1.0.1907, )",
|
||||
"Braintree": "[5.19.0, )",
|
||||
"DnsClient": "[1.7.0, )",
|
||||
"Duende.IdentityServer": "[6.0.4, )",
|
||||
"Fido2.AspNet": "[3.0.1, )",
|
||||
"Handlebars.Net": "[2.1.2, )",
|
||||
"IdentityServer4": "[4.1.2, )",
|
||||
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
|
||||
"LaunchDarkly.ServerSdk": "[8.0.0, )",
|
||||
"MailKit": "[4.2.0, )",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
|
||||
@@ -3233,15 +3209,15 @@
|
||||
"identity": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"SharedWeb": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"SharedWeb": "[2023.10.3, )",
|
||||
"Swashbuckle.AspNetCore.SwaggerGen": "[6.5.0, )"
|
||||
}
|
||||
},
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Dapper": "[2.0.123, )"
|
||||
}
|
||||
},
|
||||
@@ -3249,7 +3225,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
|
||||
@@ -3261,8 +3237,8 @@
|
||||
"integrationtestcommon": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Common": "[2023.10.2, )",
|
||||
"Identity": "[2023.10.2, )",
|
||||
"Common": "[2023.10.3, )",
|
||||
"Identity": "[2023.10.3, )",
|
||||
"Microsoft.AspNetCore.Mvc.Testing": "[6.0.5, )",
|
||||
"Microsoft.Extensions.Configuration": "[6.0.1, )"
|
||||
}
|
||||
@@ -3270,9 +3246,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"Infrastructure.Dapper": "[2023.10.2, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.2, )"
|
||||
"Core": "[2023.10.3, )",
|
||||
"Infrastructure.Dapper": "[2023.10.3, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.3, )"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using Bit.Api.AdminConsole.Controllers;
|
||||
using Bit.Api.AdminConsole.Models.Request.Organizations;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
@@ -82,7 +85,7 @@ public class OrganizationUsersControllerTests
|
||||
};
|
||||
sutProvider.GetDependency<IUserService>().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user);
|
||||
sutProvider.GetDependency<IPolicyRepository>().GetByOrganizationIdTypeAsync(orgId,
|
||||
Core.Enums.PolicyType.ResetPassword).Returns(policy);
|
||||
PolicyType.ResetPassword).Returns(policy);
|
||||
|
||||
await sutProvider.Sut.Accept(orgId, orgUserId, model);
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using Bit.Api.Auth.Controllers;
|
||||
using Bit.Api.Auth.Models.Request.Accounts;
|
||||
using Bit.Api.Auth.Models.Request.Webauthn;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Services;
|
||||
using Bit.Core.Auth.Models.Business.Tokenables;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Tokens;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Bit.Api.Auth.Models.Request.Accounts;
|
||||
using Bit.Api.Controllers;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.AdminConsole.Services;
|
||||
using Bit.Core.Auth.Models.Api.Request.Accounts;
|
||||
using Bit.Core.Auth.Services;
|
||||
using Bit.Core.Auth.UserFeatures.UserKey;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using System.Security.Claims;
|
||||
using System.Text.Json;
|
||||
using Bit.Api.AdminConsole.Controllers;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
|
||||
@@ -21,481 +21,6 @@ namespace Bit.Api.Test.Vault.AuthorizationHandlers;
|
||||
[FeatureServiceCustomize(FeatureFlagKeys.FlexibleCollections)]
|
||||
public class BulkCollectionAuthorizationHandlerTests
|
||||
{
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(OrganizationUserType.User, false, false)]
|
||||
[BitAutoData(OrganizationUserType.Admin, false, true)]
|
||||
[BitAutoData(OrganizationUserType.Owner, false, true)]
|
||||
[BitAutoData(OrganizationUserType.Custom, true, true)]
|
||||
public async Task CanCreateAsync_Success(
|
||||
OrganizationUserType userType, bool createNewCollection, bool limitCollectionCreateDelete,
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = userType;
|
||||
organization.Permissions = new Permissions
|
||||
{
|
||||
CreateNewCollections = createNewCollection
|
||||
};
|
||||
organization.LimitCollectionCreationDeletion = limitCollectionCreateDelete;
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.Create },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task CanCreateAsync_WhenProviderUser_Success(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<CollectionDetails> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = OrganizationUserType.User;
|
||||
organization.Permissions = new Permissions
|
||||
{
|
||||
CreateNewCollections = false
|
||||
};
|
||||
organization.LimitCollectionCreationDeletion = true;
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.Create },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<ICurrentContext>().ProviderUserForOrgAsync(organization.Id).Returns(true);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(OrganizationUserType.User)]
|
||||
[BitAutoData(OrganizationUserType.Custom)]
|
||||
public async Task CanCreateAsync_WhenMissingCreateCollectionPermission_Failure(
|
||||
OrganizationUserType userType,
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = userType;
|
||||
organization.Permissions = new Permissions
|
||||
{
|
||||
CreateNewCollections = false
|
||||
};
|
||||
organization.LimitCollectionCreationDeletion = true;
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.Create },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.False(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(OrganizationUserType.Admin)]
|
||||
[BitAutoData(OrganizationUserType.Owner)]
|
||||
public async Task CanReadAsync_WhenAdminOrOwner_Success(
|
||||
OrganizationUserType userType,
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<CollectionDetails> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = userType;
|
||||
organization.Permissions = new Permissions();
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.Read },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task CanReadAsync_WhenProviderUser_Success(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<CollectionDetails> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = OrganizationUserType.User;
|
||||
organization.Permissions = new Permissions();
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.Read },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<ICurrentContext>().ProviderUserForOrgAsync(organization.Id).Returns(true);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(true, false)]
|
||||
[BitAutoData(false, true)]
|
||||
public async Task CanReadAsync_WhenCustomUserWithRequiredPermissions_Success(
|
||||
bool editAnyCollection, bool deleteAnyCollection,
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<CollectionDetails> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = OrganizationUserType.Custom;
|
||||
organization.Permissions = new Permissions
|
||||
{
|
||||
EditAnyCollection = editAnyCollection,
|
||||
DeleteAnyCollection = deleteAnyCollection
|
||||
};
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.Read },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task CanReadAsync_WhenUserAssigned_Success(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<CollectionDetails> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = OrganizationUserType.User;
|
||||
organization.Permissions = new Permissions();
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.Read },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<ICollectionRepository>().GetManyByUserIdAsync(actingUserId).Returns(collections);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(OrganizationUserType.User)]
|
||||
[BitAutoData(OrganizationUserType.Custom)]
|
||||
public async Task CanReadAsync_WhenMissingAccess_Failure(
|
||||
OrganizationUserType userType,
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<CollectionDetails> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = userType;
|
||||
organization.Permissions = new Permissions
|
||||
{
|
||||
EditAnyCollection = false,
|
||||
DeleteAnyCollection = false
|
||||
};
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.Read },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.False(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(OrganizationUserType.Admin)]
|
||||
[BitAutoData(OrganizationUserType.Owner)]
|
||||
public async Task CanReadAccessAsync_WhenAdminOrOwner_Success(
|
||||
OrganizationUserType userType,
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<CollectionDetails> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = userType;
|
||||
organization.Permissions = new Permissions();
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.ReadAccess },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task CanReadAccessAsync_WhenProviderUser_Success(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<CollectionDetails> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = OrganizationUserType.User;
|
||||
organization.Permissions = new Permissions();
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.ReadAccess },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<ICurrentContext>().ProviderUserForOrgAsync(organization.Id).Returns(true);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(true, false)]
|
||||
[BitAutoData(false, true)]
|
||||
public async Task CanReadAccessAsync_WhenCustomUserWithRequiredPermissions_Success(
|
||||
bool editAnyCollection, bool deleteAnyCollection,
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<CollectionDetails> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = OrganizationUserType.Custom;
|
||||
organization.Permissions = new Permissions
|
||||
{
|
||||
EditAnyCollection = editAnyCollection,
|
||||
DeleteAnyCollection = deleteAnyCollection
|
||||
};
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.ReadAccess },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task CanReadAccessAsync_WhenUserAssigned_Success(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<CollectionDetails> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = OrganizationUserType.User;
|
||||
organization.Permissions = new Permissions();
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.ReadAccess },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<ICollectionRepository>().GetManyByUserIdAsync(actingUserId).Returns(collections);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(OrganizationUserType.User)]
|
||||
[BitAutoData(OrganizationUserType.Custom)]
|
||||
public async Task CanReadAccessAsync_WhenMissingAccess_Failure(
|
||||
OrganizationUserType userType,
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<CollectionDetails> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = userType;
|
||||
organization.Permissions = new Permissions
|
||||
{
|
||||
EditAnyCollection = false,
|
||||
DeleteAnyCollection = false
|
||||
};
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.ReadAccess },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.False(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(OrganizationUserType.User, false, true)]
|
||||
[BitAutoData(OrganizationUserType.Admin, false, false)]
|
||||
[BitAutoData(OrganizationUserType.Owner, false, false)]
|
||||
[BitAutoData(OrganizationUserType.Custom, true, false)]
|
||||
[BitAutoData(OrganizationUserType.Owner, true, true)]
|
||||
public async Task CanUpdateAsync_Success(
|
||||
OrganizationUserType userType, bool editAnyCollection, bool manageCollections,
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
ICollection<CollectionDetails> collectionDetails,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
foreach (var collectionDetail in collectionDetails)
|
||||
{
|
||||
collectionDetail.Manage = manageCollections;
|
||||
}
|
||||
|
||||
organization.Type = userType;
|
||||
organization.Permissions = new Permissions
|
||||
{
|
||||
EditAnyCollection = editAnyCollection
|
||||
};
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.Update },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<ICollectionRepository>().GetManyByUserIdAsync(actingUserId).Returns(collectionDetails);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task CanUpdateAsync_WhenProviderUser_Success(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = OrganizationUserType.User;
|
||||
organization.Permissions = new Permissions();
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.Update },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<ICurrentContext>().ProviderUserForOrgAsync(organization.Id).Returns(true);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task CanUpdateAsync_WhenMissingManageCollectionPermission_Failure(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
ICollection<CollectionDetails> collectionDetails,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
foreach (var collectionDetail in collectionDetails)
|
||||
{
|
||||
collectionDetail.Manage = true;
|
||||
}
|
||||
// Simulate one collection missing the manage permission
|
||||
collectionDetails.First().Manage = false;
|
||||
|
||||
// Ensure the user is not an owner/admin and does not have edit any collection permission
|
||||
organization.Type = OrganizationUserType.User;
|
||||
organization.Permissions = new Permissions
|
||||
{
|
||||
EditAnyCollection = false
|
||||
};
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.Update },
|
||||
new ClaimsPrincipal(),
|
||||
collections
|
||||
);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(Arg.Any<Guid>()).Returns(organization);
|
||||
sutProvider.GetDependency<ICollectionRepository>().GetManyByUserIdAsync(actingUserId).Returns(collectionDetails);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
Assert.False(context.HasSucceeded);
|
||||
sutProvider.GetDependency<ICurrentContext>().ReceivedWithAnyArgs().GetOrganization(default);
|
||||
await sutProvider.GetDependency<ICollectionRepository>().ReceivedWithAnyArgs()
|
||||
.GetManyByUserIdAsync(default);
|
||||
}
|
||||
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(OrganizationUserType.User, false, true)]
|
||||
[BitAutoData(OrganizationUserType.Admin, false, false)]
|
||||
@@ -516,10 +41,7 @@ public class BulkCollectionAuthorizationHandlerTests
|
||||
}
|
||||
|
||||
organization.Type = userType;
|
||||
organization.Permissions = new Permissions
|
||||
{
|
||||
EditAnyCollection = editAnyCollection
|
||||
};
|
||||
organization.Permissions.EditAnyCollection = editAnyCollection;
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.ModifyAccess },
|
||||
@@ -535,71 +57,36 @@ public class BulkCollectionAuthorizationHandlerTests
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task CanManageCollectionAccessAsync_WhenProviderUser_Success(
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(OrganizationUserType.User, false, false)]
|
||||
[BitAutoData(OrganizationUserType.Admin, false, true)]
|
||||
[BitAutoData(OrganizationUserType.Owner, false, true)]
|
||||
[BitAutoData(OrganizationUserType.Custom, true, true)]
|
||||
public async Task CanCreateAsync_Success(
|
||||
OrganizationUserType userType, bool createNewCollection, bool limitCollectionCreateDelete,
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = OrganizationUserType.User;
|
||||
organization.Permissions = new Permissions();
|
||||
organization.Type = userType;
|
||||
organization.Permissions.CreateNewCollections = createNewCollection;
|
||||
organization.LimitCollectionCreationDeletion = limitCollectionCreateDelete;
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.ModifyAccess },
|
||||
new[] { CollectionOperations.Create },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<ICurrentContext>().ProviderUserForOrgAsync(organization.Id).Returns(true);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task CanManageCollectionAccessAsync_WhenMissingManageCollectionPermission_Failure(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
ICollection<CollectionDetails> collectionDetails,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
foreach (var collectionDetail in collectionDetails)
|
||||
{
|
||||
collectionDetail.Manage = true;
|
||||
}
|
||||
// Simulate one collection missing the manage permission
|
||||
collectionDetails.First().Manage = false;
|
||||
|
||||
// Ensure the user is not an owner/admin and does not have edit any collection permission
|
||||
organization.Type = OrganizationUserType.User;
|
||||
organization.Permissions = new Permissions
|
||||
{
|
||||
EditAnyCollection = false
|
||||
};
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.ModifyAccess },
|
||||
new ClaimsPrincipal(),
|
||||
collections
|
||||
);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(Arg.Any<Guid>()).Returns(organization);
|
||||
sutProvider.GetDependency<ICollectionRepository>().GetManyByUserIdAsync(actingUserId).Returns(collectionDetails);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
Assert.False(context.HasSucceeded);
|
||||
sutProvider.GetDependency<ICurrentContext>().ReceivedWithAnyArgs().GetOrganization(default);
|
||||
await sutProvider.GetDependency<ICollectionRepository>().ReceivedWithAnyArgs()
|
||||
.GetManyByUserIdAsync(default);
|
||||
}
|
||||
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(OrganizationUserType.User, false, false, true)]
|
||||
[BitAutoData(OrganizationUserType.Admin, false, true, false)]
|
||||
@@ -619,10 +106,7 @@ public class BulkCollectionAuthorizationHandlerTests
|
||||
}
|
||||
|
||||
organization.Type = userType;
|
||||
organization.Permissions = new Permissions
|
||||
{
|
||||
DeleteAnyCollection = deleteAnyCollection
|
||||
};
|
||||
organization.Permissions.DeleteAnyCollection = deleteAnyCollection;
|
||||
organization.LimitCollectionCreationDeletion = limitCollectionCreateDelete;
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
@@ -639,125 +123,6 @@ public class BulkCollectionAuthorizationHandlerTests
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task CanDeleteAsync_WithProviderUser_Success(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = OrganizationUserType.User;
|
||||
organization.Permissions = new Permissions
|
||||
{
|
||||
DeleteAnyCollection = false
|
||||
};
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.Delete },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<ICurrentContext>().ProviderUserForOrgAsync(organization.Id).Returns(true);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task CanDeleteAsync_WhenCustomUserWithRequiredPermissions_Success(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<CollectionDetails> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = OrganizationUserType.Custom;
|
||||
organization.Permissions = new Permissions
|
||||
{
|
||||
DeleteAnyCollection = true
|
||||
};
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.Delete },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(OrganizationUserType.User)]
|
||||
[BitAutoData(OrganizationUserType.Custom)]
|
||||
public async Task CanDeleteAsync_WhenMissingPermissions_Failure(
|
||||
OrganizationUserType userType,
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
organization.Type = userType;
|
||||
organization.Permissions = new Permissions
|
||||
{
|
||||
DeleteAnyCollection = false
|
||||
};
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.Delete },
|
||||
new ClaimsPrincipal(),
|
||||
collections);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.False(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task HandleRequirementAsync_NullResource_NoSuccessOrFailure(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider)
|
||||
{
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.Create },
|
||||
new ClaimsPrincipal(),
|
||||
null
|
||||
);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.False(context.HasSucceeded);
|
||||
Assert.False(context.HasFailed);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task HandleRequirementAsync_EmptyResourceList_NoSuccessOrFailure(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider)
|
||||
{
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.Create },
|
||||
new ClaimsPrincipal(),
|
||||
new List<Collection>()
|
||||
);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(new Guid());
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.False(context.HasSucceeded);
|
||||
Assert.False(context.HasFailed);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task HandleRequirementAsync_MissingUserId_Failure(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
@@ -778,7 +143,7 @@ public class BulkCollectionAuthorizationHandlerTests
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task HandleRequirementAsync_TargetCollectionsMultipleOrgs_Failure(
|
||||
public async Task HandleRequirementAsync_TargetCollectionsMultipleOrgs_Exception(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
IList<Collection> collections)
|
||||
{
|
||||
@@ -801,7 +166,7 @@ public class BulkCollectionAuthorizationHandlerTests
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task HandleRequirementAsync_MissingOrg_Failure(
|
||||
public async Task HandleRequirementAsync_MissingOrg_NoSuccess(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections)
|
||||
{
|
||||
@@ -817,6 +182,76 @@ public class BulkCollectionAuthorizationHandlerTests
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(Arg.Any<Guid>()).Returns((CurrentContextOrganization)null);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
Assert.True(context.HasFailed);
|
||||
Assert.False(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task HandleRequirementAsync_Provider_Success(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections)
|
||||
{
|
||||
var operationsToTest = new[]
|
||||
{
|
||||
CollectionOperations.Create, CollectionOperations.Delete, CollectionOperations.ModifyAccess
|
||||
};
|
||||
|
||||
foreach (var op in operationsToTest)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { op },
|
||||
new ClaimsPrincipal(),
|
||||
collections
|
||||
);
|
||||
var orgId = collections.First().OrganizationId;
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(orgId).Returns((CurrentContextOrganization)null);
|
||||
sutProvider.GetDependency<ICurrentContext>().ProviderUserForOrgAsync(Arg.Any<Guid>()).Returns(true);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
Assert.True(context.HasSucceeded);
|
||||
await sutProvider.GetDependency<ICurrentContext>().Received().ProviderUserForOrgAsync(orgId);
|
||||
|
||||
// Recreate the SUT to reset the mocks/dependencies between tests
|
||||
sutProvider.Recreate();
|
||||
}
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task CanManageCollectionAccessAsync_MissingManageCollectionPermission_NoSuccess(
|
||||
SutProvider<BulkCollectionAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
ICollection<CollectionDetails> collectionDetails,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
var actingUserId = Guid.NewGuid();
|
||||
|
||||
foreach (var collectionDetail in collectionDetails)
|
||||
{
|
||||
collectionDetail.Manage = true;
|
||||
}
|
||||
// Simulate one collection missing the manage permission
|
||||
collectionDetails.First().Manage = false;
|
||||
|
||||
// Ensure the user is not an owner/admin and does not have edit any collection permission
|
||||
organization.Type = OrganizationUserType.User;
|
||||
organization.Permissions.EditAnyCollection = false;
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionOperations.ModifyAccess },
|
||||
new ClaimsPrincipal(),
|
||||
collections
|
||||
);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(Arg.Any<Guid>()).Returns(organization);
|
||||
sutProvider.GetDependency<ICollectionRepository>().GetManyByUserIdAsync(actingUserId).Returns(collectionDetails);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
Assert.False(context.HasSucceeded);
|
||||
sutProvider.GetDependency<ICurrentContext>().ReceivedWithAnyArgs().GetOrganization(default);
|
||||
await sutProvider.GetDependency<ICollectionRepository>().ReceivedWithAnyArgs()
|
||||
.GetManyByUserIdAsync(default);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Text.Json;
|
||||
using AutoFixture;
|
||||
using Bit.Api.Vault.Controllers;
|
||||
using Bit.Api.Vault.Models.Response;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums.Provider;
|
||||
using Bit.Core.AdminConsole.Models.Data.Provider;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
|
||||
@@ -374,6 +374,24 @@
|
||||
"Microsoft.Win32.Registry": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "4HVjzx1F8v5J+U7oa8RGAQGj2QzmzNSu87r18Sh+dlh10uyZZL8teAaT/FaVLDObnfItGdPFvN8mwpF/HkI3Xw==",
|
||||
"dependencies": {
|
||||
"Duende.IdentityServer.Storage": "6.0.4",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "s5gAjfbpr2IMgI+fU2Nx+2AZdzstmbt9gpo13iX7GwvqSeSaBVqj9ZskAN0R2KF1OemPdZuGnfaTcevdXMUrrw==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "6.0.0",
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Fare": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
@@ -418,49 +436,8 @@
|
||||
},
|
||||
"IdentityModel": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==",
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "11.0.2",
|
||||
"System.Text.Encodings.Web": "4.7.0"
|
||||
}
|
||||
},
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0",
|
||||
"IdentityServer4.Storage": "4.1.2",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0",
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0",
|
||||
"Newtonsoft.Json": "12.0.2"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.AccessTokenValidation": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.1",
|
||||
"contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==",
|
||||
"dependencies": {
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0"
|
||||
}
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "eVHCR7a6m/dm5RFcBzE3qs/Jg5j9R5Rjpu8aTOv9e4AFvaQtBXb5ah7kmwU+YwA0ufRwz4wf1hnIvsD2hSnI4g=="
|
||||
},
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": {
|
||||
"type": "Transitive",
|
||||
@@ -561,10 +538,10 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "cJxdro36spFzk/K2OFCddM6vZ+yoj6ug8mTFRH3Gdv1Pul/buSuCtfb/FSCp31UmS5S4C1315dU7wX3ErLFuDg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0"
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Cryptography.Internal": {
|
||||
@@ -597,8 +574,8 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.32",
|
||||
"contentHash": "MPL4iVyiaRxnOUY5VATHjvhDWaAEFb77KFiUxVRklv3Z3v+STofUr1UG/aCt1O9cgN7FVTDaC5A7U+zsLub8Xg=="
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "Z/UU4NEBm5UgNufJmw+j5baW26ytCOIZ0G7sZocPaOzsUeBon1bkM3lSMNZQG2GmDjAIVP2XMSODf2jzSGbibw=="
|
||||
},
|
||||
"Microsoft.Azure.Amqp": {
|
||||
"type": "Transitive",
|
||||
@@ -3031,25 +3008,25 @@
|
||||
"AspNetCore.HealthChecks.SqlServer": "[6.0.2, )",
|
||||
"AspNetCore.HealthChecks.Uris": "[6.0.3, )",
|
||||
"Azure.Messaging.EventGrid": "[4.10.0, )",
|
||||
"Commercial.Core": "[2023.10.2, )",
|
||||
"Commercial.Infrastructure.EntityFramework": "[2023.10.2, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"SharedWeb": "[2023.10.2, )",
|
||||
"Commercial.Core": "[2023.10.3, )",
|
||||
"Commercial.Infrastructure.EntityFramework": "[2023.10.3, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"SharedWeb": "[2023.10.3, )",
|
||||
"Swashbuckle.AspNetCore": "[6.5.0, )"
|
||||
}
|
||||
},
|
||||
"commercial.core": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )"
|
||||
"Core": "[2023.10.3, )"
|
||||
}
|
||||
},
|
||||
"commercial.infrastructure.entityframework": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.2, )"
|
||||
"Core": "[2023.10.3, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.3, )"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
@@ -3057,7 +3034,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "[4.17.0, )",
|
||||
"AutoFixture.Xunit2": "[4.17.0, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )",
|
||||
"Microsoft.NET.Test.Sdk": "[17.1.0, )",
|
||||
"NSubstitute": "[4.3.0, )",
|
||||
@@ -3079,10 +3056,9 @@
|
||||
"BitPay.Light": "[1.0.1907, )",
|
||||
"Braintree": "[5.19.0, )",
|
||||
"DnsClient": "[1.7.0, )",
|
||||
"Duende.IdentityServer": "[6.0.4, )",
|
||||
"Fido2.AspNet": "[3.0.1, )",
|
||||
"Handlebars.Net": "[2.1.2, )",
|
||||
"IdentityServer4": "[4.1.2, )",
|
||||
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
|
||||
"LaunchDarkly.ServerSdk": "[8.0.0, )",
|
||||
"MailKit": "[4.2.0, )",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
|
||||
@@ -3112,8 +3088,8 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "[4.17.0, )",
|
||||
"AutoFixture.Xunit2": "[4.17.0, )",
|
||||
"Common": "[2023.10.2, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Common": "[2023.10.3, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )",
|
||||
"Microsoft.NET.Test.Sdk": "[17.1.0, )",
|
||||
"NSubstitute": "[4.3.0, )",
|
||||
@@ -3123,7 +3099,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Dapper": "[2.0.123, )"
|
||||
}
|
||||
},
|
||||
@@ -3131,7 +3107,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
|
||||
@@ -3143,9 +3119,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"Infrastructure.Dapper": "[2023.10.2, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.2, )"
|
||||
"Core": "[2023.10.3, )",
|
||||
"Infrastructure.Dapper": "[2023.10.3, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.3, )"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,6 +280,24 @@
|
||||
"Microsoft.Win32.Registry": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "4HVjzx1F8v5J+U7oa8RGAQGj2QzmzNSu87r18Sh+dlh10uyZZL8teAaT/FaVLDObnfItGdPFvN8mwpF/HkI3Xw==",
|
||||
"dependencies": {
|
||||
"Duende.IdentityServer.Storage": "6.0.4",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "s5gAjfbpr2IMgI+fU2Nx+2AZdzstmbt9gpo13iX7GwvqSeSaBVqj9ZskAN0R2KF1OemPdZuGnfaTcevdXMUrrw==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "6.0.0",
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Fare": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
@@ -324,49 +342,8 @@
|
||||
},
|
||||
"IdentityModel": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==",
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "11.0.2",
|
||||
"System.Text.Encodings.Web": "4.7.0"
|
||||
}
|
||||
},
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0",
|
||||
"IdentityServer4.Storage": "4.1.2",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0",
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0",
|
||||
"Newtonsoft.Json": "12.0.2"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.AccessTokenValidation": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.1",
|
||||
"contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==",
|
||||
"dependencies": {
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0"
|
||||
}
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "eVHCR7a6m/dm5RFcBzE3qs/Jg5j9R5Rjpu8aTOv9e4AFvaQtBXb5ah7kmwU+YwA0ufRwz4wf1hnIvsD2hSnI4g=="
|
||||
},
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": {
|
||||
"type": "Transitive",
|
||||
@@ -467,10 +444,10 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "cJxdro36spFzk/K2OFCddM6vZ+yoj6ug8mTFRH3Gdv1Pul/buSuCtfb/FSCp31UmS5S4C1315dU7wX3ErLFuDg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0"
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Cryptography.Internal": {
|
||||
@@ -503,8 +480,8 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.32",
|
||||
"contentHash": "MPL4iVyiaRxnOUY5VATHjvhDWaAEFb77KFiUxVRklv3Z3v+STofUr1UG/aCt1O9cgN7FVTDaC5A7U+zsLub8Xg=="
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "Z/UU4NEBm5UgNufJmw+j5baW26ytCOIZ0G7sZocPaOzsUeBon1bkM3lSMNZQG2GmDjAIVP2XMSODf2jzSGbibw=="
|
||||
},
|
||||
"Microsoft.Azure.Amqp": {
|
||||
"type": "Transitive",
|
||||
@@ -2858,8 +2835,8 @@
|
||||
"billing": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"SharedWeb": "[2023.10.2, )"
|
||||
"Core": "[2023.10.3, )",
|
||||
"SharedWeb": "[2023.10.3, )"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
@@ -2867,7 +2844,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "[4.17.0, )",
|
||||
"AutoFixture.Xunit2": "[4.17.0, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )",
|
||||
"Microsoft.NET.Test.Sdk": "[17.1.0, )",
|
||||
"NSubstitute": "[4.3.0, )",
|
||||
@@ -2889,10 +2866,9 @@
|
||||
"BitPay.Light": "[1.0.1907, )",
|
||||
"Braintree": "[5.19.0, )",
|
||||
"DnsClient": "[1.7.0, )",
|
||||
"Duende.IdentityServer": "[6.0.4, )",
|
||||
"Fido2.AspNet": "[3.0.1, )",
|
||||
"Handlebars.Net": "[2.1.2, )",
|
||||
"IdentityServer4": "[4.1.2, )",
|
||||
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
|
||||
"LaunchDarkly.ServerSdk": "[8.0.0, )",
|
||||
"MailKit": "[4.2.0, )",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
|
||||
@@ -2920,7 +2896,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Dapper": "[2.0.123, )"
|
||||
}
|
||||
},
|
||||
@@ -2928,7 +2904,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
|
||||
@@ -2940,9 +2916,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"Infrastructure.Dapper": "[2023.10.2, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.2, )"
|
||||
"Core": "[2023.10.3, )",
|
||||
"Infrastructure.Dapper": "[2023.10.3, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.3, )"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,12 @@ public class SutProvider<TSut> : ISutProvider
|
||||
Sut = default;
|
||||
}
|
||||
|
||||
public void Recreate()
|
||||
{
|
||||
_dependencies = new Dictionary<Type, Dictionary<string, object>>();
|
||||
Sut = _fixture.Create<TSut>();
|
||||
}
|
||||
|
||||
ISutProvider ISutProvider.Create() => Create();
|
||||
public SutProvider<TSut> Create()
|
||||
{
|
||||
|
||||
@@ -254,6 +254,24 @@
|
||||
"Microsoft.Win32.Registry": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "4HVjzx1F8v5J+U7oa8RGAQGj2QzmzNSu87r18Sh+dlh10uyZZL8teAaT/FaVLDObnfItGdPFvN8mwpF/HkI3Xw==",
|
||||
"dependencies": {
|
||||
"Duende.IdentityServer.Storage": "6.0.4",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "s5gAjfbpr2IMgI+fU2Nx+2AZdzstmbt9gpo13iX7GwvqSeSaBVqj9ZskAN0R2KF1OemPdZuGnfaTcevdXMUrrw==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "6.0.0",
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Fare": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
@@ -298,49 +316,8 @@
|
||||
},
|
||||
"IdentityModel": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==",
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "11.0.2",
|
||||
"System.Text.Encodings.Web": "4.7.0"
|
||||
}
|
||||
},
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0",
|
||||
"IdentityServer4.Storage": "4.1.2",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0",
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0",
|
||||
"Newtonsoft.Json": "12.0.2"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.AccessTokenValidation": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.1",
|
||||
"contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==",
|
||||
"dependencies": {
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0"
|
||||
}
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "eVHCR7a6m/dm5RFcBzE3qs/Jg5j9R5Rjpu8aTOv9e4AFvaQtBXb5ah7kmwU+YwA0ufRwz4wf1hnIvsD2hSnI4g=="
|
||||
},
|
||||
"LaunchDarkly.Cache": {
|
||||
"type": "Transitive",
|
||||
@@ -418,10 +395,10 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "cJxdro36spFzk/K2OFCddM6vZ+yoj6ug8mTFRH3Gdv1Pul/buSuCtfb/FSCp31UmS5S4C1315dU7wX3ErLFuDg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0"
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Cryptography.Internal": {
|
||||
@@ -454,8 +431,8 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.32",
|
||||
"contentHash": "MPL4iVyiaRxnOUY5VATHjvhDWaAEFb77KFiUxVRklv3Z3v+STofUr1UG/aCt1O9cgN7FVTDaC5A7U+zsLub8Xg=="
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "Z/UU4NEBm5UgNufJmw+j5baW26ytCOIZ0G7sZocPaOzsUeBon1bkM3lSMNZQG2GmDjAIVP2XMSODf2jzSGbibw=="
|
||||
},
|
||||
"Microsoft.Azure.Amqp": {
|
||||
"type": "Transitive",
|
||||
@@ -2690,10 +2667,9 @@
|
||||
"BitPay.Light": "[1.0.1907, )",
|
||||
"Braintree": "[5.19.0, )",
|
||||
"DnsClient": "[1.7.0, )",
|
||||
"Duende.IdentityServer": "[6.0.4, )",
|
||||
"Fido2.AspNet": "[3.0.1, )",
|
||||
"Handlebars.Net": "[2.1.2, )",
|
||||
"IdentityServer4": "[4.1.2, )",
|
||||
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
|
||||
"LaunchDarkly.ServerSdk": "[8.0.0, )",
|
||||
"MailKit": "[4.2.0, )",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System.Reflection;
|
||||
using AutoFixture;
|
||||
using AutoFixture.Xunit2;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
|
||||
namespace Bit.Core.Test.AutoFixture.PolicyFixtures;
|
||||
namespace Bit.Core.Test.AdminConsole.AutoFixture;
|
||||
|
||||
internal class PolicyCustomization : ICustomization
|
||||
{
|
||||
@@ -1,4 +1,9 @@
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.AdminConsole.Services.Implementations;
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models.Data;
|
||||
using Bit.Core.Auth.Repositories;
|
||||
@@ -6,24 +11,23 @@ using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
|
||||
using Bit.Core.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
using AdminConsoleFixtures = Bit.Core.Test.AdminConsole.AutoFixture;
|
||||
using GlobalSettings = Bit.Core.Settings.GlobalSettings;
|
||||
using PolicyFixtures = Bit.Core.Test.AutoFixture.PolicyFixtures;
|
||||
|
||||
namespace Bit.Core.Test.Services;
|
||||
namespace Bit.Core.Test.AdminConsole.Services;
|
||||
|
||||
[SutProviderCustomize]
|
||||
public class PolicyServiceTests
|
||||
{
|
||||
[Theory, BitAutoData]
|
||||
public async Task SaveAsync_OrganizationDoesNotExist_ThrowsBadRequest(
|
||||
[PolicyFixtures.Policy(PolicyType.DisableSend)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
[AdminConsoleFixtures.Policy(PolicyType.DisableSend)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
{
|
||||
SetupOrg(sutProvider, policy.OrganizationId, null);
|
||||
|
||||
@@ -46,7 +50,7 @@ public class PolicyServiceTests
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SaveAsync_OrganizationCannotUsePolicies_ThrowsBadRequest(
|
||||
[PolicyFixtures.Policy(PolicyType.DisableSend)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
[AdminConsoleFixtures.Policy(PolicyType.DisableSend)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
{
|
||||
var orgId = Guid.NewGuid();
|
||||
|
||||
@@ -74,7 +78,7 @@ public class PolicyServiceTests
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SaveAsync_SingleOrg_RequireSsoEnabled_ThrowsBadRequest(
|
||||
[PolicyFixtures.Policy(PolicyType.SingleOrg)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
[AdminConsoleFixtures.Policy(PolicyType.SingleOrg)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
{
|
||||
policy.Enabled = false;
|
||||
|
||||
@@ -106,7 +110,7 @@ public class PolicyServiceTests
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SaveAsync_SingleOrg_VaultTimeoutEnabled_ThrowsBadRequest([PolicyFixtures.Policy(Enums.PolicyType.SingleOrg)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
public async Task SaveAsync_SingleOrg_VaultTimeoutEnabled_ThrowsBadRequest([AdminConsoleFixtures.Policy(PolicyType.SingleOrg)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
{
|
||||
policy.Enabled = false;
|
||||
|
||||
@@ -117,7 +121,7 @@ public class PolicyServiceTests
|
||||
});
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>()
|
||||
.GetByOrganizationIdTypeAsync(policy.OrganizationId, Enums.PolicyType.MaximumVaultTimeout)
|
||||
.GetByOrganizationIdTypeAsync(policy.OrganizationId, PolicyType.MaximumVaultTimeout)
|
||||
.Returns(new Policy { Enabled = true });
|
||||
|
||||
var badRequestException = await Assert.ThrowsAsync<BadRequestException>(
|
||||
@@ -137,7 +141,7 @@ public class PolicyServiceTests
|
||||
[BitAutoData(PolicyType.SingleOrg)]
|
||||
[BitAutoData(PolicyType.RequireSso)]
|
||||
public async Task SaveAsync_PolicyRequiredByKeyConnector_DisablePolicy_ThrowsBadRequest(
|
||||
Enums.PolicyType policyType,
|
||||
PolicyType policyType,
|
||||
Policy policy,
|
||||
SutProvider<PolicyService> sutProvider)
|
||||
{
|
||||
@@ -173,7 +177,7 @@ public class PolicyServiceTests
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SaveAsync_RequireSsoPolicy_NotEnabled_ThrowsBadRequestAsync(
|
||||
[PolicyFixtures.Policy(Enums.PolicyType.RequireSso)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
[AdminConsoleFixtures.Policy(PolicyType.RequireSso)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
{
|
||||
policy.Enabled = true;
|
||||
|
||||
@@ -206,7 +210,7 @@ public class PolicyServiceTests
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SaveAsync_NewPolicy_Created(
|
||||
[PolicyFixtures.Policy(PolicyType.ResetPassword)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
[AdminConsoleFixtures.Policy(PolicyType.ResetPassword)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
{
|
||||
policy.Id = default;
|
||||
policy.Data = null;
|
||||
@@ -218,7 +222,7 @@ public class PolicyServiceTests
|
||||
});
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>()
|
||||
.GetByOrganizationIdTypeAsync(policy.OrganizationId, Enums.PolicyType.SingleOrg)
|
||||
.GetByOrganizationIdTypeAsync(policy.OrganizationId, PolicyType.SingleOrg)
|
||||
.Returns(Task.FromResult(new Policy { Enabled = true }));
|
||||
|
||||
var utcNow = DateTime.UtcNow;
|
||||
@@ -237,7 +241,7 @@ public class PolicyServiceTests
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SaveAsync_VaultTimeoutPolicy_NotEnabled_ThrowsBadRequestAsync(
|
||||
[PolicyFixtures.Policy(PolicyType.MaximumVaultTimeout)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
[AdminConsoleFixtures.Policy(PolicyType.MaximumVaultTimeout)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
{
|
||||
policy.Enabled = true;
|
||||
|
||||
@@ -248,7 +252,7 @@ public class PolicyServiceTests
|
||||
});
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>()
|
||||
.GetByOrganizationIdTypeAsync(policy.OrganizationId, Enums.PolicyType.SingleOrg)
|
||||
.GetByOrganizationIdTypeAsync(policy.OrganizationId, PolicyType.SingleOrg)
|
||||
.Returns(Task.FromResult(new Policy { Enabled = false }));
|
||||
|
||||
var badRequestException = await Assert.ThrowsAsync<BadRequestException>(
|
||||
@@ -270,7 +274,7 @@ public class PolicyServiceTests
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SaveAsync_ExistingPolicy_UpdateTwoFactor(
|
||||
[PolicyFixtures.Policy(PolicyType.TwoFactorAuthentication)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
[AdminConsoleFixtures.Policy(PolicyType.TwoFactorAuthentication)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
{
|
||||
// If the policy that this is updating isn't enabled then do some work now that the current one is enabled
|
||||
|
||||
@@ -340,7 +344,7 @@ public class PolicyServiceTests
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SaveAsync_ExistingPolicy_UpdateSingleOrg(
|
||||
[PolicyFixtures.Policy(PolicyType.TwoFactorAuthentication)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
[AdminConsoleFixtures.Policy(PolicyType.TwoFactorAuthentication)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
{
|
||||
// If the policy that this is updating isn't enabled then do some work now that the current one is enabled
|
||||
|
||||
@@ -409,7 +413,7 @@ public class PolicyServiceTests
|
||||
public async Task SaveAsync_ResetPasswordPolicyRequiredByTrustedDeviceEncryption_DisablePolicyOrDisableAutomaticEnrollment_ThrowsBadRequest(
|
||||
bool policyEnabled,
|
||||
bool autoEnrollEnabled,
|
||||
[PolicyFixtures.Policy(PolicyType.ResetPassword)] Policy policy,
|
||||
[AdminConsoleFixtures.Policy(PolicyType.ResetPassword)] Policy policy,
|
||||
SutProvider<PolicyService> sutProvider)
|
||||
{
|
||||
policy.Enabled = policyEnabled;
|
||||
@@ -450,7 +454,7 @@ public class PolicyServiceTests
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SaveAsync_RequireSsoPolicyRequiredByTrustedDeviceEncryption_DisablePolicy_ThrowsBadRequest(
|
||||
[PolicyFixtures.Policy(PolicyType.RequireSso)] Policy policy,
|
||||
[AdminConsoleFixtures.Policy(PolicyType.RequireSso)] Policy policy,
|
||||
SutProvider<PolicyService> sutProvider)
|
||||
{
|
||||
policy.Enabled = false;
|
||||
@@ -487,7 +491,7 @@ public class PolicyServiceTests
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SaveAsync_PolicyRequiredForAccountRecovery_NotEnabled_ThrowsBadRequestAsync(
|
||||
[PolicyFixtures.Policy(Enums.PolicyType.ResetPassword)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
[AdminConsoleFixtures.Policy(PolicyType.ResetPassword)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
{
|
||||
policy.Enabled = true;
|
||||
policy.SetDataModel(new ResetPasswordDataModel());
|
||||
@@ -522,7 +526,7 @@ public class PolicyServiceTests
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SaveAsync_SingleOrg_AccountRecoveryEnabled_ThrowsBadRequest(
|
||||
[PolicyFixtures.Policy(Enums.PolicyType.SingleOrg)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
[AdminConsoleFixtures.Policy(PolicyType.SingleOrg)] Policy policy, SutProvider<PolicyService> sutProvider)
|
||||
{
|
||||
policy.Enabled = false;
|
||||
|
||||
@@ -533,7 +537,7 @@ public class PolicyServiceTests
|
||||
});
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>()
|
||||
.GetByOrganizationIdTypeAsync(policy.OrganizationId, Enums.PolicyType.ResetPassword)
|
||||
.GetByOrganizationIdTypeAsync(policy.OrganizationId, PolicyType.ResetPassword)
|
||||
.Returns(new Policy { Enabled = true });
|
||||
|
||||
var badRequestException = await Assert.ThrowsAsync<BadRequestException>(
|
||||
@@ -0,0 +1,61 @@
|
||||
using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models.Business.Tokenables;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using Fido2NetLib;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Core.Test.Auth.Models.Business.Tokenables;
|
||||
|
||||
public class WebAuthnLoginAssertionOptionsTokenableTests
|
||||
{
|
||||
[Theory, BitAutoData]
|
||||
public void Valid_TokenWithoutOptions_ReturnsFalse(WebAuthnLoginAssertionOptionsScope scope)
|
||||
{
|
||||
var token = new WebAuthnLoginAssertionOptionsTokenable(scope, null);
|
||||
|
||||
var isValid = token.Valid;
|
||||
|
||||
Assert.False(isValid);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public void Valid_NewlyCreatedToken_ReturnsTrue(WebAuthnLoginAssertionOptionsScope scope, AssertionOptions createOptions)
|
||||
{
|
||||
var token = new WebAuthnLoginAssertionOptionsTokenable(scope, createOptions);
|
||||
|
||||
|
||||
var isValid = token.Valid;
|
||||
|
||||
Assert.True(isValid);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public void ValidIsValid_TokenWithoutOptions_ReturnsFalse(WebAuthnLoginAssertionOptionsScope scope)
|
||||
{
|
||||
var token = new WebAuthnLoginAssertionOptionsTokenable(scope, null);
|
||||
|
||||
var isValid = token.TokenIsValid(scope);
|
||||
|
||||
Assert.False(isValid);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public void ValidIsValid_NonMatchingScope_ReturnsFalse(WebAuthnLoginAssertionOptionsScope scope1, WebAuthnLoginAssertionOptionsScope scope2, AssertionOptions createOptions)
|
||||
{
|
||||
var token = new WebAuthnLoginAssertionOptionsTokenable(scope1, createOptions);
|
||||
|
||||
var isValid = token.TokenIsValid(scope2);
|
||||
|
||||
Assert.False(isValid);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public void ValidIsValid_SameScope_ReturnsTrue(WebAuthnLoginAssertionOptionsScope scope, AssertionOptions createOptions)
|
||||
{
|
||||
var token = new WebAuthnLoginAssertionOptionsTokenable(scope, createOptions);
|
||||
|
||||
var isValid = token.TokenIsValid(scope);
|
||||
|
||||
Assert.True(isValid);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,9 @@
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.AdminConsole.Services;
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models.Data;
|
||||
using Bit.Core.Auth.Repositories;
|
||||
@@ -6,7 +11,6 @@ using Bit.Core.Auth.Services;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
|
||||
using Bit.Core.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
@@ -205,7 +209,7 @@ public class SsoConfigServiceTests
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>().GetByOrganizationIdTypeAsync(
|
||||
Arg.Any<Guid>(), Enums.PolicyType.SingleOrg).Returns(new Policy
|
||||
Arg.Any<Guid>(), PolicyType.SingleOrg).Returns(new Policy
|
||||
{
|
||||
Enabled = true
|
||||
});
|
||||
@@ -239,7 +243,7 @@ public class SsoConfigServiceTests
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>().GetByOrganizationIdTypeAsync(
|
||||
Arg.Any<Guid>(), Arg.Any<Enums.PolicyType>()).Returns(new Policy
|
||||
Arg.Any<Guid>(), Arg.Any<PolicyType>()).Returns(new Policy
|
||||
{
|
||||
Enabled = true
|
||||
});
|
||||
@@ -274,7 +278,7 @@ public class SsoConfigServiceTests
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>().GetByOrganizationIdTypeAsync(
|
||||
Arg.Any<Guid>(), Arg.Any<Enums.PolicyType>()).Returns(new Policy
|
||||
Arg.Any<Guid>(), Arg.Any<PolicyType>()).Returns(new Policy
|
||||
{
|
||||
Enabled = true,
|
||||
});
|
||||
@@ -309,7 +313,7 @@ public class SsoConfigServiceTests
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>().GetByOrganizationIdTypeAsync(
|
||||
Arg.Any<Guid>(), Arg.Any<Enums.PolicyType>()).Returns(new Policy
|
||||
Arg.Any<Guid>(), Arg.Any<PolicyType>()).Returns(new Policy
|
||||
{
|
||||
Enabled = true,
|
||||
});
|
||||
@@ -338,7 +342,7 @@ public class SsoConfigServiceTests
|
||||
|
||||
await sutProvider.GetDependency<IPolicyService>().Received(1)
|
||||
.SaveAsync(
|
||||
Arg.Is<Policy>(t => t.Type == Enums.PolicyType.SingleOrg),
|
||||
Arg.Is<Policy>(t => t.Type == PolicyType.SingleOrg),
|
||||
Arg.Any<IUserService>(),
|
||||
Arg.Any<IOrganizationService>(),
|
||||
null
|
||||
@@ -346,7 +350,7 @@ public class SsoConfigServiceTests
|
||||
|
||||
await sutProvider.GetDependency<IPolicyService>().Received(1)
|
||||
.SaveAsync(
|
||||
Arg.Is<Policy>(t => t.Type == Enums.PolicyType.ResetPassword && t.GetDataModel<ResetPasswordDataModel>().AutoEnrollEnabled),
|
||||
Arg.Is<Policy>(t => t.Type == PolicyType.ResetPassword && t.GetDataModel<ResetPasswordDataModel>().AutoEnrollEnabled),
|
||||
Arg.Any<IUserService>(),
|
||||
Arg.Any<IOrganizationService>(),
|
||||
null
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Bit.Core.AdminConsole.Models.OrganizationConnectionConfigs;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Models.OrganizationConnectionConfigs;
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models.Data;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Bit.Core.Auth.Models.Business.Tokenables;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Services;
|
||||
using Bit.Core.Auth.Models.Business.Tokenables;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Text.Json;
|
||||
using Bit.Core.AdminConsole.Entities.Provider;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Enums.Provider;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
@@ -21,9 +22,9 @@ using Bit.Core.OrganizationFeatures.OrganizationSubscriptions.Interface;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Core.Test.AdminConsole.AutoFixture;
|
||||
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
|
||||
using Bit.Core.Test.AutoFixture.OrganizationUserFixtures;
|
||||
using Bit.Core.Test.AutoFixture.PolicyFixtures;
|
||||
using Bit.Core.Tokens;
|
||||
using Bit.Core.Tools.Enums;
|
||||
using Bit.Core.Tools.Models.Business;
|
||||
@@ -34,10 +35,11 @@ using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using Bit.Test.Common.Fakes;
|
||||
using NSubstitute;
|
||||
using NSubstitute.ExceptionExtensions;
|
||||
using NSubstitute.ReturnsExtensions;
|
||||
using Xunit;
|
||||
using Organization = Bit.Core.Entities.Organization;
|
||||
using OrganizationUser = Bit.Core.Entities.OrganizationUser;
|
||||
using Policy = Bit.Core.Entities.Policy;
|
||||
using Policy = Bit.Core.AdminConsole.Entities.Policy;
|
||||
|
||||
namespace Bit.Core.Test.Services;
|
||||
|
||||
@@ -1606,15 +1608,16 @@ public class OrganizationServiceTests
|
||||
[BitAutoData(0, null, 100, true, "")]
|
||||
[BitAutoData(1, 100, null, true, "")]
|
||||
[BitAutoData(1, 100, 100, false, "Seat limit has been reached")]
|
||||
public void CanScale(int seatsToAdd, int? currentSeats, int? maxAutoscaleSeats,
|
||||
public async Task CanScaleAsync(int seatsToAdd, int? currentSeats, int? maxAutoscaleSeats,
|
||||
bool expectedResult, string expectedFailureMessage, Organization organization,
|
||||
SutProvider<OrganizationService> sutProvider)
|
||||
{
|
||||
organization.Seats = currentSeats;
|
||||
organization.MaxAutoscaleSeats = maxAutoscaleSeats;
|
||||
sutProvider.GetDependency<ICurrentContext>().ManageUsers(organization.Id).Returns(true);
|
||||
sutProvider.GetDependency<IProviderRepository>().GetByOrganizationIdAsync(organization.Id).ReturnsNull();
|
||||
|
||||
var (result, failureMessage) = sutProvider.Sut.CanScale(organization, seatsToAdd);
|
||||
var (result, failureMessage) = await sutProvider.Sut.CanScaleAsync(organization, seatsToAdd);
|
||||
|
||||
if (expectedFailureMessage == string.Empty)
|
||||
{
|
||||
@@ -1628,16 +1631,35 @@ public class OrganizationServiceTests
|
||||
}
|
||||
|
||||
[Theory, PaidOrganizationCustomize, BitAutoData]
|
||||
public void CanScale_FailsOnSelfHosted(Organization organization,
|
||||
public async Task CanScaleAsync_FailsOnSelfHosted(Organization organization,
|
||||
SutProvider<OrganizationService> sutProvider)
|
||||
{
|
||||
sutProvider.GetDependency<IGlobalSettings>().SelfHosted.Returns(true);
|
||||
var (result, failureMessage) = sutProvider.Sut.CanScale(organization, 10);
|
||||
var (result, failureMessage) = await sutProvider.Sut.CanScaleAsync(organization, 10);
|
||||
|
||||
Assert.False(result);
|
||||
Assert.Contains("Cannot autoscale on self-hosted instance", failureMessage);
|
||||
}
|
||||
|
||||
[Theory, PaidOrganizationCustomize, BitAutoData]
|
||||
public async Task CanScaleAsync_FailsOnResellerManagedOrganization(
|
||||
Organization organization,
|
||||
SutProvider<OrganizationService> sutProvider)
|
||||
{
|
||||
var provider = new Provider
|
||||
{
|
||||
Enabled = true,
|
||||
Type = ProviderType.Reseller
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IProviderRepository>().GetByOrganizationIdAsync(organization.Id).Returns(provider);
|
||||
|
||||
var (result, failureMessage) = await sutProvider.Sut.CanScaleAsync(organization, 10);
|
||||
|
||||
Assert.False(result);
|
||||
Assert.Contains("Seat limit has been reached. Contact your provider to purchase additional seats.", failureMessage);
|
||||
}
|
||||
|
||||
[Theory, PaidOrganizationCustomize, BitAutoData]
|
||||
public async Task Delete_Success(Organization organization, SutProvider<OrganizationService> sutProvider)
|
||||
{
|
||||
|
||||
@@ -739,300 +739,4 @@ public class StripePaymentServiceTests
|
||||
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task PreviewUpcomingInvoiceAndPayAsync_WithInAppPaymentMethod_ThrowsBadRequestException(SutProvider<StripePaymentService> sutProvider,
|
||||
Organization subscriber, List<Stripe.InvoiceSubscriptionItemOptions> subItemOptions)
|
||||
{
|
||||
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
||||
stripeAdapter.CustomerGetAsync(Arg.Any<string>(), Arg.Any<Stripe.CustomerGetOptions>())
|
||||
.Returns(new Stripe.Customer { Metadata = new Dictionary<string, string> { { "appleReceipt", "dummyData" } } });
|
||||
|
||||
var ex = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.PreviewUpcomingInvoiceAndPayAsync(subscriber, subItemOptions));
|
||||
Assert.Equal("Cannot perform this action with in-app purchase payment method. Contact support.", ex.Message);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async void PreviewUpcomingInvoiceAndPayAsync_UpcomingInvoiceBelowThreshold_DoesNotInvoiceNow(SutProvider<StripePaymentService> sutProvider,
|
||||
Organization subscriber, List<Stripe.InvoiceSubscriptionItemOptions> subItemOptions)
|
||||
{
|
||||
var prorateThreshold = 50000;
|
||||
var invoiceAmountBelowThreshold = prorateThreshold - 100;
|
||||
var customer = MockStripeCustomer(subscriber);
|
||||
sutProvider.GetDependency<IStripeAdapter>().CustomerGetAsync(default, default).ReturnsForAnyArgs(customer);
|
||||
var invoiceItem = MockInoviceItemList(subscriber, "planId", invoiceAmountBelowThreshold, customer);
|
||||
sutProvider.GetDependency<IStripeAdapter>().InvoiceItemListAsync(new Stripe.InvoiceItemListOptions
|
||||
{
|
||||
Customer = subscriber.GatewayCustomerId
|
||||
}).ReturnsForAnyArgs(invoiceItem);
|
||||
|
||||
var invoiceLineItem = CreateInvoiceLineTime(subscriber, "planId", invoiceAmountBelowThreshold);
|
||||
sutProvider.GetDependency<IStripeAdapter>().InvoiceUpcomingAsync(new Stripe.UpcomingInvoiceOptions
|
||||
{
|
||||
Customer = subscriber.GatewayCustomerId,
|
||||
Subscription = subscriber.GatewaySubscriptionId,
|
||||
SubscriptionItems = subItemOptions
|
||||
}).ReturnsForAnyArgs(invoiceLineItem);
|
||||
|
||||
sutProvider.GetDependency<IStripeAdapter>().InvoiceCreateAsync(Arg.Is<Stripe.InvoiceCreateOptions>(options =>
|
||||
options.CollectionMethod == "send_invoice" &&
|
||||
options.DaysUntilDue == 1 &&
|
||||
options.Customer == subscriber.GatewayCustomerId &&
|
||||
options.Subscription == subscriber.GatewaySubscriptionId &&
|
||||
options.DefaultPaymentMethod == customer.InvoiceSettings.DefaultPaymentMethod.Id
|
||||
)).ReturnsForAnyArgs(new Stripe.Invoice
|
||||
{
|
||||
Id = "mockInvoiceId",
|
||||
CollectionMethod = "send_invoice",
|
||||
DueDate = DateTime.Now.AddDays(1),
|
||||
Customer = customer,
|
||||
Subscription = new Stripe.Subscription
|
||||
{
|
||||
Id = "mockSubscriptionId",
|
||||
Customer = customer,
|
||||
Status = "active",
|
||||
CurrentPeriodStart = DateTime.UtcNow,
|
||||
CurrentPeriodEnd = DateTime.UtcNow.AddMonths(1),
|
||||
CollectionMethod = "charge_automatically",
|
||||
},
|
||||
DefaultPaymentMethod = customer.InvoiceSettings.DefaultPaymentMethod,
|
||||
AmountDue = invoiceAmountBelowThreshold,
|
||||
Currency = "usd",
|
||||
Status = "draft",
|
||||
});
|
||||
|
||||
var result = await sutProvider.Sut.PreviewUpcomingInvoiceAndPayAsync(subscriber, new List<Stripe.InvoiceSubscriptionItemOptions>(), prorateThreshold);
|
||||
|
||||
Assert.False(result.IsInvoicedNow);
|
||||
Assert.Null(result.PaymentIntentClientSecret);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async void PreviewUpcomingInvoiceAndPayAsync_NoPaymentMethod_ThrowsBadRequestException(SutProvider<StripePaymentService> sutProvider,
|
||||
Organization subscriber, List<Stripe.InvoiceSubscriptionItemOptions> subItemOptions, string planId)
|
||||
{
|
||||
var prorateThreshold = 120000;
|
||||
var invoiceAmountBelowThreshold = prorateThreshold;
|
||||
var customer = new Stripe.Customer
|
||||
{
|
||||
Metadata = new Dictionary<string, string>(),
|
||||
Id = subscriber.GatewayCustomerId,
|
||||
DefaultSource = null,
|
||||
InvoiceSettings = new Stripe.CustomerInvoiceSettings
|
||||
{
|
||||
DefaultPaymentMethod = null
|
||||
}
|
||||
};
|
||||
sutProvider.GetDependency<IStripeAdapter>().CustomerGetAsync(default, default).ReturnsForAnyArgs(customer);
|
||||
var invoiceItem = MockInoviceItemList(subscriber, planId, invoiceAmountBelowThreshold, customer);
|
||||
sutProvider.GetDependency<IStripeAdapter>().InvoiceItemListAsync(new Stripe.InvoiceItemListOptions
|
||||
{
|
||||
Customer = subscriber.GatewayCustomerId
|
||||
}).ReturnsForAnyArgs(invoiceItem);
|
||||
|
||||
var invoiceLineItem = CreateInvoiceLineTime(subscriber, planId, invoiceAmountBelowThreshold);
|
||||
sutProvider.GetDependency<IStripeAdapter>().InvoiceUpcomingAsync(new Stripe.UpcomingInvoiceOptions
|
||||
{
|
||||
Customer = subscriber.GatewayCustomerId,
|
||||
Subscription = subscriber.GatewaySubscriptionId,
|
||||
SubscriptionItems = subItemOptions
|
||||
}).ReturnsForAnyArgs(invoiceLineItem);
|
||||
|
||||
var ex = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.PreviewUpcomingInvoiceAndPayAsync(subscriber, subItemOptions));
|
||||
Assert.Equal("No payment method is available.", ex.Message);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async void PreviewUpcomingInvoiceAndPayAsync_UpcomingInvoiceAboveThreshold_DoesInvoiceNow(SutProvider<StripePaymentService> sutProvider,
|
||||
Organization subscriber, List<Stripe.InvoiceSubscriptionItemOptions> subItemOptions, string planId)
|
||||
{
|
||||
var prorateThreshold = 50000;
|
||||
var invoiceAmountBelowThreshold = 100000;
|
||||
var customer = MockStripeCustomer(subscriber);
|
||||
sutProvider.GetDependency<IStripeAdapter>().CustomerGetAsync(default, default).ReturnsForAnyArgs(customer);
|
||||
var invoiceItem = MockInoviceItemList(subscriber, planId, invoiceAmountBelowThreshold, customer);
|
||||
sutProvider.GetDependency<IStripeAdapter>().InvoiceItemListAsync(new Stripe.InvoiceItemListOptions
|
||||
{
|
||||
Customer = subscriber.GatewayCustomerId
|
||||
}).ReturnsForAnyArgs(invoiceItem);
|
||||
|
||||
var invoiceLineItem = CreateInvoiceLineTime(subscriber, planId, invoiceAmountBelowThreshold);
|
||||
sutProvider.GetDependency<IStripeAdapter>().InvoiceUpcomingAsync(new Stripe.UpcomingInvoiceOptions
|
||||
{
|
||||
Customer = subscriber.GatewayCustomerId,
|
||||
Subscription = subscriber.GatewaySubscriptionId,
|
||||
SubscriptionItems = subItemOptions
|
||||
}).ReturnsForAnyArgs(invoiceLineItem);
|
||||
|
||||
var invoice = MockInVoice(customer, invoiceAmountBelowThreshold);
|
||||
sutProvider.GetDependency<IStripeAdapter>().InvoiceCreateAsync(Arg.Is<Stripe.InvoiceCreateOptions>(options =>
|
||||
options.CollectionMethod == "send_invoice" &&
|
||||
options.DaysUntilDue == 1 &&
|
||||
options.Customer == subscriber.GatewayCustomerId &&
|
||||
options.Subscription == subscriber.GatewaySubscriptionId &&
|
||||
options.DefaultPaymentMethod == customer.InvoiceSettings.DefaultPaymentMethod.Id
|
||||
)).ReturnsForAnyArgs(invoice);
|
||||
|
||||
var result = await sutProvider.Sut.PreviewUpcomingInvoiceAndPayAsync(subscriber, new List<Stripe.InvoiceSubscriptionItemOptions>(), prorateThreshold);
|
||||
|
||||
await sutProvider.GetDependency<IStripeAdapter>().Received(1).InvoicePayAsync(invoice.Id,
|
||||
Arg.Is<Stripe.InvoicePayOptions>((options =>
|
||||
options.OffSession == true
|
||||
)));
|
||||
|
||||
|
||||
Assert.True(result.IsInvoicedNow);
|
||||
Assert.Null(result.PaymentIntentClientSecret);
|
||||
}
|
||||
|
||||
private static Stripe.Invoice MockInVoice(Stripe.Customer customer, int invoiceAmountBelowThreshold) =>
|
||||
new()
|
||||
{
|
||||
Id = "mockInvoiceId",
|
||||
CollectionMethod = "send_invoice",
|
||||
DueDate = DateTime.Now.AddDays(1),
|
||||
Customer = customer,
|
||||
Subscription = new Stripe.Subscription
|
||||
{
|
||||
Id = "mockSubscriptionId",
|
||||
Customer = customer,
|
||||
Status = "active",
|
||||
CurrentPeriodStart = DateTime.UtcNow,
|
||||
CurrentPeriodEnd = DateTime.UtcNow.AddMonths(1),
|
||||
CollectionMethod = "charge_automatically",
|
||||
},
|
||||
DefaultPaymentMethod = customer.InvoiceSettings.DefaultPaymentMethod,
|
||||
AmountDue = invoiceAmountBelowThreshold,
|
||||
Currency = "usd",
|
||||
Status = "draft",
|
||||
};
|
||||
|
||||
private static List<Stripe.InvoiceItem> MockInoviceItemList(Organization subscriber, string planId, int invoiceAmountBelowThreshold, Stripe.Customer customer) =>
|
||||
new()
|
||||
{
|
||||
new Stripe.InvoiceItem
|
||||
{
|
||||
Id = "ii_1234567890",
|
||||
Amount = invoiceAmountBelowThreshold,
|
||||
Currency = "usd",
|
||||
CustomerId = subscriber.GatewayCustomerId,
|
||||
Description = "Sample invoice item 1",
|
||||
Date = DateTime.UtcNow,
|
||||
Discountable = true,
|
||||
InvoiceId = "548458365"
|
||||
},
|
||||
new Stripe.InvoiceItem
|
||||
{
|
||||
Id = "ii_0987654321",
|
||||
Amount = invoiceAmountBelowThreshold,
|
||||
Currency = "usd",
|
||||
CustomerId = customer.Id,
|
||||
Description = "Sample invoice item 2",
|
||||
Date = DateTime.UtcNow.AddDays(-5),
|
||||
Discountable = false,
|
||||
InvoiceId = null,
|
||||
Proration = true,
|
||||
Plan = new Stripe.Plan
|
||||
{
|
||||
Id = planId,
|
||||
Amount = invoiceAmountBelowThreshold,
|
||||
Currency = "usd",
|
||||
Interval = "month",
|
||||
IntervalCount = 1,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
private static Stripe.Customer MockStripeCustomer(Organization subscriber)
|
||||
{
|
||||
var customer = new Stripe.Customer
|
||||
{
|
||||
Metadata = new Dictionary<string, string>(),
|
||||
Id = subscriber.GatewayCustomerId,
|
||||
DefaultSource = new Stripe.Card
|
||||
{
|
||||
Id = "card_12345",
|
||||
Last4 = "1234",
|
||||
Brand = "Visa",
|
||||
ExpYear = 2025,
|
||||
ExpMonth = 12
|
||||
},
|
||||
InvoiceSettings = new Stripe.CustomerInvoiceSettings
|
||||
{
|
||||
DefaultPaymentMethod = new Stripe.PaymentMethod
|
||||
{
|
||||
Id = "pm_12345",
|
||||
Type = "card",
|
||||
Card = new Stripe.PaymentMethodCard
|
||||
{
|
||||
Last4 = "1234",
|
||||
Brand = "Visa",
|
||||
ExpYear = 2025,
|
||||
ExpMonth = 12
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
return customer;
|
||||
}
|
||||
|
||||
private static Stripe.Invoice CreateInvoiceLineTime(Organization subscriber, string planId, int invoiceAmountBelowThreshold) =>
|
||||
new()
|
||||
{
|
||||
AmountDue = invoiceAmountBelowThreshold,
|
||||
AmountPaid = 0,
|
||||
AmountRemaining = invoiceAmountBelowThreshold,
|
||||
CustomerId = subscriber.GatewayCustomerId,
|
||||
SubscriptionId = subscriber.GatewaySubscriptionId,
|
||||
ApplicationFeeAmount = 0,
|
||||
Currency = "usd",
|
||||
Description = "Upcoming Invoice",
|
||||
Discount = null,
|
||||
DueDate = DateTime.UtcNow.AddDays(1),
|
||||
EndingBalance = 0,
|
||||
Number = "INV12345",
|
||||
Paid = false,
|
||||
PeriodStart = DateTime.UtcNow,
|
||||
PeriodEnd = DateTime.UtcNow.AddMonths(1),
|
||||
ReceiptNumber = null,
|
||||
StartingBalance = 0,
|
||||
Status = "draft",
|
||||
Id = "ii_0987654321",
|
||||
Total = invoiceAmountBelowThreshold,
|
||||
Lines = new Stripe.StripeList<Stripe.InvoiceLineItem>
|
||||
{
|
||||
Data = new List<Stripe.InvoiceLineItem>
|
||||
{
|
||||
new Stripe.InvoiceLineItem
|
||||
{
|
||||
Amount = invoiceAmountBelowThreshold,
|
||||
Currency = "usd",
|
||||
Description = "Sample line item",
|
||||
Id = "ii_0987654321",
|
||||
Livemode = false,
|
||||
Object = "line_item",
|
||||
Discountable = false,
|
||||
Period = new Stripe.InvoiceLineItemPeriod()
|
||||
{
|
||||
Start = DateTime.UtcNow,
|
||||
End = DateTime.UtcNow.AddMonths(1)
|
||||
},
|
||||
Plan = new Stripe.Plan
|
||||
{
|
||||
Id = planId,
|
||||
Amount = invoiceAmountBelowThreshold,
|
||||
Currency = "usd",
|
||||
Interval = "month",
|
||||
IntervalCount = 1,
|
||||
},
|
||||
Proration = true,
|
||||
Quantity = 1,
|
||||
Subscription = subscriber.GatewaySubscriptionId,
|
||||
SubscriptionItem = "si_12345",
|
||||
Type = "subscription",
|
||||
UnitAmountExcludingTax = invoiceAmountBelowThreshold,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System.Text.Json;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using AutoFixture;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.AdminConsole.Services;
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models;
|
||||
@@ -8,26 +10,29 @@ using Bit.Core.Auth.Models.Business.Tokenables;
|
||||
using Bit.Core.Auth.Repositories;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Business;
|
||||
using Bit.Core.Models.Data.Organizations;
|
||||
using Bit.Core.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Core.Tokens;
|
||||
using Bit.Core.Tools.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Core.Vault.Repositories;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using Bit.Test.Common.Fakes;
|
||||
using Bit.Test.Common.Helpers;
|
||||
using Fido2NetLib;
|
||||
using Fido2NetLib.Objects;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using NSubstitute;
|
||||
using NSubstitute.ReceivedExtensions;
|
||||
using NSubstitute.ReturnsExtensions;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Core.Test.Services;
|
||||
@@ -188,7 +193,7 @@ public class UserServiceTests
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async void CompleteWebAuthLoginRegistrationAsync_ExceedsExistingCredentialsLimit_ReturnsFalse(SutProvider<UserService> sutProvider, User user, CredentialCreateOptions options, AuthenticatorAttestationRawResponse response, Generator<WebAuthnCredential> credentialGenerator)
|
||||
public async Task CompleteWebAuthLoginRegistrationAsync_ExceedsExistingCredentialsLimit_ReturnsFalse(SutProvider<UserService> sutProvider, User user, CredentialCreateOptions options, AuthenticatorAttestationRawResponse response, Generator<WebAuthnCredential> credentialGenerator)
|
||||
{
|
||||
// Arrange
|
||||
var existingCredentials = credentialGenerator.Take(5).ToList();
|
||||
@@ -202,6 +207,92 @@ public class UserServiceTests
|
||||
sutProvider.GetDependency<IWebAuthnCredentialRepository>().DidNotReceive();
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task CompleteWebAuthLoginAssertionAsync_InvalidUserHandle_ThrowsBadRequestException(SutProvider<UserService> sutProvider, AssertionOptions options, AuthenticatorAssertionRawResponse response)
|
||||
{
|
||||
// Arrange
|
||||
response.Response.UserHandle = Encoding.UTF8.GetBytes("invalid-user-handle");
|
||||
|
||||
// Act
|
||||
var result = async () => await sutProvider.Sut.CompleteWebAuthLoginAssertionAsync(options, response);
|
||||
|
||||
// Assert
|
||||
await Assert.ThrowsAsync<BadRequestException>(result);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task CompleteWebAuthLoginAssertionAsync_UserNotFound_ThrowsBadRequestException(SutProvider<UserService> sutProvider, User user, AssertionOptions options, AuthenticatorAssertionRawResponse response)
|
||||
{
|
||||
// Arrange
|
||||
response.Response.UserHandle = user.Id.ToByteArray();
|
||||
sutProvider.GetDependency<IUserRepository>().GetByIdAsync(user.Id).ReturnsNull();
|
||||
|
||||
// Act
|
||||
var result = async () => await sutProvider.Sut.CompleteWebAuthLoginAssertionAsync(options, response);
|
||||
|
||||
// Assert
|
||||
await Assert.ThrowsAsync<BadRequestException>(result);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task CompleteWebAuthLoginAssertionAsync_NoMatchingCredentialExists_ThrowsBadRequestException(SutProvider<UserService> sutProvider, User user, AssertionOptions options, AuthenticatorAssertionRawResponse response)
|
||||
{
|
||||
// Arrange
|
||||
response.Response.UserHandle = user.Id.ToByteArray();
|
||||
sutProvider.GetDependency<IUserRepository>().GetByIdAsync(user.Id).Returns(user);
|
||||
sutProvider.GetDependency<IWebAuthnCredentialRepository>().GetManyByUserIdAsync(user.Id).Returns(new WebAuthnCredential[] { });
|
||||
|
||||
// Act
|
||||
var result = async () => await sutProvider.Sut.CompleteWebAuthLoginAssertionAsync(options, response);
|
||||
|
||||
// Assert
|
||||
await Assert.ThrowsAsync<BadRequestException>(result);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task CompleteWebAuthLoginAssertionAsync_AssertionFails_ThrowsBadRequestException(SutProvider<UserService> sutProvider, User user, AssertionOptions options, AuthenticatorAssertionRawResponse response, WebAuthnCredential credential, AssertionVerificationResult assertionResult)
|
||||
{
|
||||
// Arrange
|
||||
var credentialId = Guid.NewGuid().ToByteArray();
|
||||
credential.CredentialId = CoreHelpers.Base64UrlEncode(credentialId);
|
||||
response.Id = credentialId;
|
||||
response.Response.UserHandle = user.Id.ToByteArray();
|
||||
assertionResult.Status = "Not ok";
|
||||
sutProvider.GetDependency<IUserRepository>().GetByIdAsync(user.Id).Returns(user);
|
||||
sutProvider.GetDependency<IWebAuthnCredentialRepository>().GetManyByUserIdAsync(user.Id).Returns(new WebAuthnCredential[] { credential });
|
||||
sutProvider.GetDependency<IFido2>().MakeAssertionAsync(response, options, Arg.Any<byte[]>(), Arg.Any<uint>(), Arg.Any<IsUserHandleOwnerOfCredentialIdAsync>())
|
||||
.Returns(assertionResult);
|
||||
|
||||
// Act
|
||||
var result = async () => await sutProvider.Sut.CompleteWebAuthLoginAssertionAsync(options, response);
|
||||
|
||||
// Assert
|
||||
await Assert.ThrowsAsync<BadRequestException>(result);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task CompleteWebAuthLoginAssertionAsync_AssertionSucceeds_ReturnsUserAndCredential(SutProvider<UserService> sutProvider, User user, AssertionOptions options, AuthenticatorAssertionRawResponse response, WebAuthnCredential credential, AssertionVerificationResult assertionResult)
|
||||
{
|
||||
// Arrange
|
||||
var credentialId = Guid.NewGuid().ToByteArray();
|
||||
credential.CredentialId = CoreHelpers.Base64UrlEncode(credentialId);
|
||||
response.Id = credentialId;
|
||||
response.Response.UserHandle = user.Id.ToByteArray();
|
||||
assertionResult.Status = "ok";
|
||||
sutProvider.GetDependency<IUserRepository>().GetByIdAsync(user.Id).Returns(user);
|
||||
sutProvider.GetDependency<IWebAuthnCredentialRepository>().GetManyByUserIdAsync(user.Id).Returns(new WebAuthnCredential[] { credential });
|
||||
sutProvider.GetDependency<IFido2>().MakeAssertionAsync(response, options, Arg.Any<byte[]>(), Arg.Any<uint>(), Arg.Any<IsUserHandleOwnerOfCredentialIdAsync>())
|
||||
.Returns(assertionResult);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.CompleteWebAuthLoginAssertionAsync(options, response);
|
||||
|
||||
// Assert
|
||||
var (userResult, credentialResult) = result;
|
||||
Assert.Equal(user, userResult);
|
||||
Assert.Equal(credential, credentialResult);
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ShouldCheck
|
||||
{
|
||||
@@ -278,8 +369,7 @@ public class UserServiceTests
|
||||
sutProvider.GetDependency<IProviderUserRepository>(),
|
||||
sutProvider.GetDependency<IStripeSyncService>(),
|
||||
new FakeDataProtectorTokenFactory<OrgUserInviteTokenable>(),
|
||||
sutProvider.GetDependency<IWebAuthnCredentialRepository>(),
|
||||
sutProvider.GetDependency<IDataProtectorTokenFactory<WebAuthnLoginTokenable>>()
|
||||
sutProvider.GetDependency<IWebAuthnCredentialRepository>()
|
||||
);
|
||||
|
||||
var actualIsVerified = await sut.VerifySecretAsync(user, secret);
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.AdminConsole.Services;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
|
||||
using Bit.Core.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Test.AutoFixture.CurrentContextFixtures;
|
||||
|
||||
@@ -4,6 +4,9 @@ using Bit.Core.Exceptions;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Test.AutoFixture.CipherFixtures;
|
||||
using Bit.Core.Tools.Enums;
|
||||
using Bit.Core.Tools.Models.Business;
|
||||
using Bit.Core.Tools.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Core.Vault.Entities;
|
||||
using Bit.Core.Vault.Models.Data;
|
||||
@@ -21,6 +24,64 @@ namespace Bit.Core.Test.Services;
|
||||
[SutProviderCustomize]
|
||||
public class CipherServiceTests
|
||||
{
|
||||
[Theory, BitAutoData]
|
||||
public async Task ImportCiphersAsync_IntoOrganization_Success(
|
||||
Organization organization,
|
||||
Guid importingUserId,
|
||||
OrganizationUser importingOrganizationUser,
|
||||
List<Collection> collections,
|
||||
List<CipherDetails> ciphers,
|
||||
SutProvider<CipherService> sutProvider)
|
||||
{
|
||||
organization.MaxCollections = null;
|
||||
importingOrganizationUser.OrganizationId = organization.Id;
|
||||
|
||||
foreach (var collection in collections)
|
||||
{
|
||||
collection.OrganizationId = organization.Id;
|
||||
}
|
||||
|
||||
foreach (var cipher in ciphers)
|
||||
{
|
||||
cipher.OrganizationId = organization.Id;
|
||||
}
|
||||
|
||||
KeyValuePair<int, int>[] collectionRelationships = {
|
||||
new(0, 0),
|
||||
new(1, 1),
|
||||
new(2, 2)
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>()
|
||||
.GetByIdAsync(organization.Id)
|
||||
.Returns(organization);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetByOrganizationAsync(organization.Id, importingUserId)
|
||||
.Returns(importingOrganizationUser);
|
||||
|
||||
// Set up a collection that already exists in the organization
|
||||
sutProvider.GetDependency<ICollectionRepository>()
|
||||
.GetManyByOrganizationIdAsync(organization.Id)
|
||||
.Returns(new List<Collection> { collections[0] });
|
||||
|
||||
await sutProvider.Sut.ImportCiphersAsync(collections, ciphers, collectionRelationships, importingUserId);
|
||||
|
||||
await sutProvider.GetDependency<ICipherRepository>().Received(1).CreateAsync(
|
||||
ciphers,
|
||||
Arg.Is<IEnumerable<Collection>>(cols => cols.Count() == collections.Count - 1 &&
|
||||
!cols.Any(c => c.Id == collections[0].Id) && // Check that the collection that already existed in the organization was not added
|
||||
cols.All(c => collections.Any(x => c.Name == x.Name))),
|
||||
Arg.Is<IEnumerable<CollectionCipher>>(c => c.Count() == ciphers.Count),
|
||||
Arg.Is<IEnumerable<CollectionUser>>(cus =>
|
||||
cus.Count() == collections.Count - 1 &&
|
||||
!cus.Any(cu => cu.CollectionId == collections[0].Id) && // Check that access was not added for the collection that already existed in the organization
|
||||
cus.All(cu => cu.OrganizationUserId == importingOrganizationUser.Id && cu.Manage == true)));
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(1).PushSyncVaultAsync(importingUserId);
|
||||
await sutProvider.GetDependency<IReferenceEventService>().Received(1).RaiseEventAsync(
|
||||
Arg.Is<ReferenceEvent>(e => e.Type == ReferenceEventType.VaultImported));
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SaveAsync_WrongRevisionDate_Throws(SutProvider<CipherService> sutProvider, Cipher cipher)
|
||||
{
|
||||
|
||||
@@ -260,6 +260,24 @@
|
||||
"Microsoft.Win32.Registry": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "4HVjzx1F8v5J+U7oa8RGAQGj2QzmzNSu87r18Sh+dlh10uyZZL8teAaT/FaVLDObnfItGdPFvN8mwpF/HkI3Xw==",
|
||||
"dependencies": {
|
||||
"Duende.IdentityServer.Storage": "6.0.4",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "s5gAjfbpr2IMgI+fU2Nx+2AZdzstmbt9gpo13iX7GwvqSeSaBVqj9ZskAN0R2KF1OemPdZuGnfaTcevdXMUrrw==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "6.0.0",
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Fare": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
@@ -304,49 +322,8 @@
|
||||
},
|
||||
"IdentityModel": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==",
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "11.0.2",
|
||||
"System.Text.Encodings.Web": "4.7.0"
|
||||
}
|
||||
},
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0",
|
||||
"IdentityServer4.Storage": "4.1.2",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0",
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0",
|
||||
"Newtonsoft.Json": "12.0.2"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.AccessTokenValidation": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.1",
|
||||
"contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==",
|
||||
"dependencies": {
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0"
|
||||
}
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "eVHCR7a6m/dm5RFcBzE3qs/Jg5j9R5Rjpu8aTOv9e4AFvaQtBXb5ah7kmwU+YwA0ufRwz4wf1hnIvsD2hSnI4g=="
|
||||
},
|
||||
"LaunchDarkly.Cache": {
|
||||
"type": "Transitive",
|
||||
@@ -424,10 +401,10 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "cJxdro36spFzk/K2OFCddM6vZ+yoj6ug8mTFRH3Gdv1Pul/buSuCtfb/FSCp31UmS5S4C1315dU7wX3ErLFuDg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0"
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Cryptography.Internal": {
|
||||
@@ -460,8 +437,8 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.32",
|
||||
"contentHash": "MPL4iVyiaRxnOUY5VATHjvhDWaAEFb77KFiUxVRklv3Z3v+STofUr1UG/aCt1O9cgN7FVTDaC5A7U+zsLub8Xg=="
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "Z/UU4NEBm5UgNufJmw+j5baW26ytCOIZ0G7sZocPaOzsUeBon1bkM3lSMNZQG2GmDjAIVP2XMSODf2jzSGbibw=="
|
||||
},
|
||||
"Microsoft.Azure.Amqp": {
|
||||
"type": "Transitive",
|
||||
@@ -2686,7 +2663,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "[4.17.0, )",
|
||||
"AutoFixture.Xunit2": "[4.17.0, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )",
|
||||
"Microsoft.NET.Test.Sdk": "[17.1.0, )",
|
||||
"NSubstitute": "[4.3.0, )",
|
||||
@@ -2708,10 +2685,9 @@
|
||||
"BitPay.Light": "[1.0.1907, )",
|
||||
"Braintree": "[5.19.0, )",
|
||||
"DnsClient": "[1.7.0, )",
|
||||
"Duende.IdentityServer": "[6.0.4, )",
|
||||
"Fido2.AspNet": "[3.0.1, )",
|
||||
"Handlebars.Net": "[2.1.2, )",
|
||||
"IdentityServer4": "[4.1.2, )",
|
||||
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
|
||||
"LaunchDarkly.ServerSdk": "[8.0.0, )",
|
||||
"MailKit": "[4.2.0, )",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
|
||||
|
||||
@@ -278,6 +278,24 @@
|
||||
"Microsoft.Win32.Registry": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "4HVjzx1F8v5J+U7oa8RGAQGj2QzmzNSu87r18Sh+dlh10uyZZL8teAaT/FaVLDObnfItGdPFvN8mwpF/HkI3Xw==",
|
||||
"dependencies": {
|
||||
"Duende.IdentityServer.Storage": "6.0.4",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "s5gAjfbpr2IMgI+fU2Nx+2AZdzstmbt9gpo13iX7GwvqSeSaBVqj9ZskAN0R2KF1OemPdZuGnfaTcevdXMUrrw==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "6.0.0",
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Fare": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
@@ -322,49 +340,8 @@
|
||||
},
|
||||
"IdentityModel": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==",
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "11.0.2",
|
||||
"System.Text.Encodings.Web": "4.7.0"
|
||||
}
|
||||
},
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0",
|
||||
"IdentityServer4.Storage": "4.1.2",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0",
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0",
|
||||
"Newtonsoft.Json": "12.0.2"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.AccessTokenValidation": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.1",
|
||||
"contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==",
|
||||
"dependencies": {
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0"
|
||||
}
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "eVHCR7a6m/dm5RFcBzE3qs/Jg5j9R5Rjpu8aTOv9e4AFvaQtBXb5ah7kmwU+YwA0ufRwz4wf1hnIvsD2hSnI4g=="
|
||||
},
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": {
|
||||
"type": "Transitive",
|
||||
@@ -465,10 +442,10 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "cJxdro36spFzk/K2OFCddM6vZ+yoj6ug8mTFRH3Gdv1Pul/buSuCtfb/FSCp31UmS5S4C1315dU7wX3ErLFuDg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0"
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Cryptography.Internal": {
|
||||
@@ -501,8 +478,8 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.32",
|
||||
"contentHash": "MPL4iVyiaRxnOUY5VATHjvhDWaAEFb77KFiUxVRklv3Z3v+STofUr1UG/aCt1O9cgN7FVTDaC5A7U+zsLub8Xg=="
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "Z/UU4NEBm5UgNufJmw+j5baW26ytCOIZ0G7sZocPaOzsUeBon1bkM3lSMNZQG2GmDjAIVP2XMSODf2jzSGbibw=="
|
||||
},
|
||||
"Microsoft.Azure.Amqp": {
|
||||
"type": "Transitive",
|
||||
@@ -2858,7 +2835,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "[4.17.0, )",
|
||||
"AutoFixture.Xunit2": "[4.17.0, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )",
|
||||
"Microsoft.NET.Test.Sdk": "[17.1.0, )",
|
||||
"NSubstitute": "[4.3.0, )",
|
||||
@@ -2880,10 +2857,9 @@
|
||||
"BitPay.Light": "[1.0.1907, )",
|
||||
"Braintree": "[5.19.0, )",
|
||||
"DnsClient": "[1.7.0, )",
|
||||
"Duende.IdentityServer": "[6.0.4, )",
|
||||
"Fido2.AspNet": "[3.0.1, )",
|
||||
"Handlebars.Net": "[2.1.2, )",
|
||||
"IdentityServer4": "[4.1.2, )",
|
||||
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
|
||||
"LaunchDarkly.ServerSdk": "[8.0.0, )",
|
||||
"MailKit": "[4.2.0, )",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
|
||||
@@ -2912,14 +2888,14 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AngleSharp": "[1.0.4, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"SharedWeb": "[2023.10.2, )"
|
||||
"Core": "[2023.10.3, )",
|
||||
"SharedWeb": "[2023.10.3, )"
|
||||
}
|
||||
},
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Dapper": "[2.0.123, )"
|
||||
}
|
||||
},
|
||||
@@ -2927,7 +2903,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
|
||||
@@ -2939,9 +2915,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"Infrastructure.Dapper": "[2023.10.2, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.2, )"
|
||||
"Core": "[2023.10.3, )",
|
||||
"Infrastructure.Dapper": "[2023.10.3, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.3, )"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.IntegrationTestCommon.Factories;
|
||||
using Bit.Test.Common.Helpers;
|
||||
using Duende.IdentityServer.Models;
|
||||
using Duende.IdentityServer.Stores;
|
||||
using IdentityModel;
|
||||
using IdentityServer4.Models;
|
||||
using IdentityServer4.Stores;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
@@ -564,7 +564,7 @@ public class IdentityServerSsoTests
|
||||
new Claim(JwtClaimTypes.SessionId, "SOMETHING"),
|
||||
new Claim(JwtClaimTypes.AuthenticationMethod, "external"),
|
||||
new Claim(JwtClaimTypes.AuthenticationTime, DateTime.UtcNow.AddMinutes(-1).ToEpochTime().ToString())
|
||||
}, "IdentityServer4", JwtClaimTypes.Name, JwtClaimTypes.Role));
|
||||
}, "Duende.IdentityServer", JwtClaimTypes.Name, JwtClaimTypes.Role));
|
||||
|
||||
authorizationCode.Subject = subject;
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Text.Json;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.Auth.Models.Api.Request.Accounts;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Repositories;
|
||||
@@ -569,7 +572,7 @@ public class IdentityServerTests : IClassFixture<IdentityApplicationFactory>
|
||||
};
|
||||
await organizationUserRepository.CreateAsync(organizationUser);
|
||||
|
||||
var ssoPolicy = new Bit.Core.Entities.Policy { OrganizationId = organization.Id, Type = PolicyType.RequireSso, Enabled = ssoPolicyEnabled };
|
||||
var ssoPolicy = new Policy { OrganizationId = organization.Id, Type = PolicyType.RequireSso, Enabled = ssoPolicyEnabled };
|
||||
await policyRepository.CreateAsync(ssoPolicy);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"authorization_endpoint": "http://localhost:33656/connect/authorize",
|
||||
"token_endpoint": "http://localhost:33656/connect/token",
|
||||
"device_authorization_endpoint": "http://localhost:33656/connect/deviceauthorization",
|
||||
"backchannel_authentication_endpoint": "http://localhost:33656/connect/ciba",
|
||||
"scopes_supported": [
|
||||
"api",
|
||||
"api.push",
|
||||
@@ -38,7 +39,9 @@
|
||||
"refresh_token",
|
||||
"implicit",
|
||||
"password",
|
||||
"urn:ietf:params:oauth:grant-type:device_code"
|
||||
"urn:ietf:params:oauth:grant-type:device_code",
|
||||
"urn:openid:params:grant-type:ciba",
|
||||
"webauthn"
|
||||
],
|
||||
"response_types_supported": [
|
||||
"code",
|
||||
@@ -49,24 +52,30 @@
|
||||
"code token",
|
||||
"code id_token token"
|
||||
],
|
||||
"response_modes_supported": [
|
||||
"form_post",
|
||||
"query",
|
||||
"fragment"
|
||||
],
|
||||
"response_modes_supported": ["form_post", "query", "fragment"],
|
||||
"token_endpoint_auth_methods_supported": [
|
||||
"client_secret_basic",
|
||||
"client_secret_post"
|
||||
],
|
||||
"id_token_signing_alg_values_supported": [
|
||||
"RS256"
|
||||
"id_token_signing_alg_values_supported": ["RS256"],
|
||||
"subject_types_supported": ["public"],
|
||||
"code_challenge_methods_supported": ["plain", "S256"],
|
||||
"request_parameter_supported": true,
|
||||
"request_object_signing_alg_values_supported": [
|
||||
"RS256",
|
||||
"RS384",
|
||||
"RS512",
|
||||
"PS256",
|
||||
"PS384",
|
||||
"PS512",
|
||||
"ES256",
|
||||
"ES384",
|
||||
"ES512",
|
||||
"HS256",
|
||||
"HS384",
|
||||
"HS512"
|
||||
],
|
||||
"subject_types_supported": [
|
||||
"public"
|
||||
],
|
||||
"code_challenge_methods_supported": [
|
||||
"plain",
|
||||
"S256"
|
||||
],
|
||||
"request_parameter_supported": true
|
||||
"authorization_response_iss_parameter_supported": true,
|
||||
"backchannel_token_delivery_modes_supported": ["poll"],
|
||||
"backchannel_user_code_parameter_supported": true
|
||||
}
|
||||
|
||||
@@ -282,6 +282,24 @@
|
||||
"Microsoft.Win32.Registry": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "4HVjzx1F8v5J+U7oa8RGAQGj2QzmzNSu87r18Sh+dlh10uyZZL8teAaT/FaVLDObnfItGdPFvN8mwpF/HkI3Xw==",
|
||||
"dependencies": {
|
||||
"Duende.IdentityServer.Storage": "6.0.4",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "s5gAjfbpr2IMgI+fU2Nx+2AZdzstmbt9gpo13iX7GwvqSeSaBVqj9ZskAN0R2KF1OemPdZuGnfaTcevdXMUrrw==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "6.0.0",
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Fare": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
@@ -326,49 +344,8 @@
|
||||
},
|
||||
"IdentityModel": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==",
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "11.0.2",
|
||||
"System.Text.Encodings.Web": "4.7.0"
|
||||
}
|
||||
},
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0",
|
||||
"IdentityServer4.Storage": "4.1.2",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0",
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0",
|
||||
"Newtonsoft.Json": "12.0.2"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.AccessTokenValidation": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.1",
|
||||
"contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==",
|
||||
"dependencies": {
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0"
|
||||
}
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "eVHCR7a6m/dm5RFcBzE3qs/Jg5j9R5Rjpu8aTOv9e4AFvaQtBXb5ah7kmwU+YwA0ufRwz4wf1hnIvsD2hSnI4g=="
|
||||
},
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": {
|
||||
"type": "Transitive",
|
||||
@@ -469,10 +446,10 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "cJxdro36spFzk/K2OFCddM6vZ+yoj6ug8mTFRH3Gdv1Pul/buSuCtfb/FSCp31UmS5S4C1315dU7wX3ErLFuDg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0"
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Cryptography.Internal": {
|
||||
@@ -505,8 +482,8 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.32",
|
||||
"contentHash": "MPL4iVyiaRxnOUY5VATHjvhDWaAEFb77KFiUxVRklv3Z3v+STofUr1UG/aCt1O9cgN7FVTDaC5A7U+zsLub8Xg=="
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "Z/UU4NEBm5UgNufJmw+j5baW26ytCOIZ0G7sZocPaOzsUeBon1bkM3lSMNZQG2GmDjAIVP2XMSODf2jzSGbibw=="
|
||||
},
|
||||
"Microsoft.AspNetCore.TestHost": {
|
||||
"type": "Transitive",
|
||||
@@ -2997,7 +2974,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "[4.17.0, )",
|
||||
"AutoFixture.Xunit2": "[4.17.0, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )",
|
||||
"Microsoft.NET.Test.Sdk": "[17.1.0, )",
|
||||
"NSubstitute": "[4.3.0, )",
|
||||
@@ -3019,10 +2996,9 @@
|
||||
"BitPay.Light": "[1.0.1907, )",
|
||||
"Braintree": "[5.19.0, )",
|
||||
"DnsClient": "[1.7.0, )",
|
||||
"Duende.IdentityServer": "[6.0.4, )",
|
||||
"Fido2.AspNet": "[3.0.1, )",
|
||||
"Handlebars.Net": "[2.1.2, )",
|
||||
"IdentityServer4": "[4.1.2, )",
|
||||
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
|
||||
"LaunchDarkly.ServerSdk": "[8.0.0, )",
|
||||
"MailKit": "[4.2.0, )",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
|
||||
@@ -3050,15 +3026,15 @@
|
||||
"identity": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"SharedWeb": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"SharedWeb": "[2023.10.3, )",
|
||||
"Swashbuckle.AspNetCore.SwaggerGen": "[6.5.0, )"
|
||||
}
|
||||
},
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Dapper": "[2.0.123, )"
|
||||
}
|
||||
},
|
||||
@@ -3066,7 +3042,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
|
||||
@@ -3078,8 +3054,8 @@
|
||||
"integrationtestcommon": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Common": "[2023.10.2, )",
|
||||
"Identity": "[2023.10.2, )",
|
||||
"Common": "[2023.10.3, )",
|
||||
"Identity": "[2023.10.3, )",
|
||||
"Microsoft.AspNetCore.Mvc.Testing": "[6.0.5, )",
|
||||
"Microsoft.Extensions.Configuration": "[6.0.1, )"
|
||||
}
|
||||
@@ -3087,9 +3063,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"Infrastructure.Dapper": "[2023.10.2, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.2, )"
|
||||
"Core": "[2023.10.3, )",
|
||||
"Infrastructure.Dapper": "[2023.10.3, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.3, )"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Bit.Core.Auth.Models.Api.Request.Accounts;
|
||||
using Bit.Core.Auth.Models.Business.Tokenables;
|
||||
using Bit.Core.Auth.Services;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
@@ -6,6 +7,7 @@ using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Tokens;
|
||||
using Bit.Identity.Controllers;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -22,6 +24,7 @@ public class AccountsControllerTests : IDisposable
|
||||
private readonly IUserRepository _userRepository;
|
||||
private readonly IUserService _userService;
|
||||
private readonly ICaptchaValidationService _captchaValidationService;
|
||||
private readonly IDataProtectorTokenFactory<WebAuthnLoginAssertionOptionsTokenable> _assertionOptionsDataProtector;
|
||||
|
||||
public AccountsControllerTests()
|
||||
{
|
||||
@@ -29,11 +32,13 @@ public class AccountsControllerTests : IDisposable
|
||||
_userRepository = Substitute.For<IUserRepository>();
|
||||
_userService = Substitute.For<IUserService>();
|
||||
_captchaValidationService = Substitute.For<ICaptchaValidationService>();
|
||||
_assertionOptionsDataProtector = Substitute.For<IDataProtectorTokenFactory<WebAuthnLoginAssertionOptionsTokenable>>();
|
||||
_sut = new AccountsController(
|
||||
_logger,
|
||||
_userRepository,
|
||||
_userService,
|
||||
_captchaValidationService
|
||||
_captchaValidationService,
|
||||
_assertionOptionsDataProtector
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
using Bit.Core;
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models.Data;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Identity.IdentityServer;
|
||||
using Bit.Identity.Utilities;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Identity.Test.IdentityServer;
|
||||
|
||||
public class UserDecryptionOptionsBuilderTests
|
||||
{
|
||||
private readonly ICurrentContext _currentContext;
|
||||
private readonly IFeatureService _featureService;
|
||||
private readonly IDeviceRepository _deviceRepository;
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
private readonly UserDecryptionOptionsBuilder _builder;
|
||||
|
||||
public UserDecryptionOptionsBuilderTests()
|
||||
{
|
||||
_currentContext = Substitute.For<ICurrentContext>();
|
||||
_featureService = Substitute.For<IFeatureService>();
|
||||
_deviceRepository = Substitute.For<IDeviceRepository>();
|
||||
_organizationUserRepository = Substitute.For<IOrganizationUserRepository>();
|
||||
_builder = new UserDecryptionOptionsBuilder(_currentContext, _featureService, _deviceRepository, _organizationUserRepository);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(true, true, true)] // All keys are non-null
|
||||
[BitAutoData(false, false, false)] // All keys are null
|
||||
[BitAutoData(false, false, true)] // EncryptedUserKey is non-null, others are null
|
||||
[BitAutoData(false, true, false)] // EncryptedPublicKey is non-null, others are null
|
||||
[BitAutoData(true, false, false)] // EncryptedPrivateKey is non-null, others are null
|
||||
[BitAutoData(true, false, true)] // EncryptedPrivateKey and EncryptedUserKey are non-null, EncryptedPublicKey is null
|
||||
[BitAutoData(true, true, false)] // EncryptedPrivateKey and EncryptedPublicKey are non-null, EncryptedUserKey is null
|
||||
[BitAutoData(false, true, true)] // EncryptedPublicKey and EncryptedUserKey are non-null, EncryptedPrivateKey is null
|
||||
public async Task WithWebAuthnLoginCredential_VariousKeyCombinations_ShouldReturnCorrectPrfOption(
|
||||
bool hasEncryptedPrivateKey,
|
||||
bool hasEncryptedPublicKey,
|
||||
bool hasEncryptedUserKey,
|
||||
WebAuthnCredential credential)
|
||||
{
|
||||
credential.EncryptedPrivateKey = hasEncryptedPrivateKey ? "encryptedPrivateKey" : null;
|
||||
credential.EncryptedPublicKey = hasEncryptedPublicKey ? "encryptedPublicKey" : null;
|
||||
credential.EncryptedUserKey = hasEncryptedUserKey ? "encryptedUserKey" : null;
|
||||
|
||||
var result = await _builder.WithWebAuthnLoginCredential(credential).BuildAsync();
|
||||
|
||||
if (credential.GetPrfStatus() == WebAuthnPrfStatus.Enabled)
|
||||
{
|
||||
Assert.NotNull(result.WebAuthnPrfOption);
|
||||
Assert.Equal(credential.EncryptedPrivateKey, result.WebAuthnPrfOption!.EncryptedPrivateKey);
|
||||
Assert.Equal(credential.EncryptedUserKey, result.WebAuthnPrfOption!.EncryptedUserKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Null(result.WebAuthnPrfOption);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Build_WhenKeyConnectorIsEnabled_ShouldReturnKeyConnectorOptions(SsoConfig ssoConfig, SsoConfigurationData configurationData)
|
||||
{
|
||||
configurationData.MemberDecryptionType = MemberDecryptionType.KeyConnector;
|
||||
ssoConfig.Data = configurationData.Serialize();
|
||||
|
||||
var result = await _builder.WithSso(ssoConfig).BuildAsync();
|
||||
|
||||
Assert.NotNull(result.KeyConnectorOption);
|
||||
Assert.Equal(configurationData.KeyConnectorUrl, result.KeyConnectorOption!.KeyConnectorUrl);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Build_WhenTrustedDeviceIsEnabled_ShouldReturnTrustedDeviceOptions(SsoConfig ssoConfig, SsoConfigurationData configurationData, Device device)
|
||||
{
|
||||
_featureService.IsEnabled(FeatureFlagKeys.TrustedDeviceEncryption, _currentContext).Returns(true);
|
||||
configurationData.MemberDecryptionType = MemberDecryptionType.TrustedDeviceEncryption;
|
||||
ssoConfig.Data = configurationData.Serialize();
|
||||
|
||||
var result = await _builder.WithSso(ssoConfig).WithDevice(device).BuildAsync();
|
||||
|
||||
Assert.NotNull(result.TrustedDeviceOption);
|
||||
Assert.False(result.TrustedDeviceOption!.HasAdminApproval);
|
||||
Assert.False(result.TrustedDeviceOption!.HasLoginApprovingDevice);
|
||||
Assert.False(result.TrustedDeviceOption!.HasManageResetPasswordPermission);
|
||||
}
|
||||
|
||||
// TODO: Remove when FeatureFlagKeys.TrustedDeviceEncryption is removed
|
||||
[Theory, BitAutoData]
|
||||
public async Task Build_WhenTrustedDeviceIsEnabledButFeatureFlagIsDisabled_ShouldNotReturnTrustedDeviceOptions(SsoConfig ssoConfig, SsoConfigurationData configurationData, Device device)
|
||||
{
|
||||
_featureService.IsEnabled(FeatureFlagKeys.TrustedDeviceEncryption, _currentContext).Returns(false);
|
||||
configurationData.MemberDecryptionType = MemberDecryptionType.TrustedDeviceEncryption;
|
||||
ssoConfig.Data = configurationData.Serialize();
|
||||
|
||||
var result = await _builder.WithSso(ssoConfig).WithDevice(device).BuildAsync();
|
||||
|
||||
Assert.Null(result.TrustedDeviceOption);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Build_WhenDeviceIsTrusted_ShouldReturnKeys(SsoConfig ssoConfig, SsoConfigurationData configurationData, Device device)
|
||||
{
|
||||
_featureService.IsEnabled(FeatureFlagKeys.TrustedDeviceEncryption, _currentContext).Returns(true);
|
||||
configurationData.MemberDecryptionType = MemberDecryptionType.TrustedDeviceEncryption;
|
||||
ssoConfig.Data = configurationData.Serialize();
|
||||
device.EncryptedPrivateKey = "encryptedPrivateKey";
|
||||
device.EncryptedPublicKey = "encryptedPublicKey";
|
||||
device.EncryptedUserKey = "encryptedUserKey";
|
||||
|
||||
var result = await _builder.WithSso(ssoConfig).WithDevice(device).BuildAsync();
|
||||
|
||||
Assert.Equal(device.EncryptedPrivateKey, result.TrustedDeviceOption?.EncryptedPrivateKey);
|
||||
Assert.Equal(device.EncryptedUserKey, result.TrustedDeviceOption?.EncryptedUserKey);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Build_WhenHasLoginApprovingDevice_ShouldApprovingDeviceTrue(SsoConfig ssoConfig, SsoConfigurationData configurationData, User user, Device device, Device approvingDevice)
|
||||
{
|
||||
_featureService.IsEnabled(FeatureFlagKeys.TrustedDeviceEncryption, _currentContext).Returns(true);
|
||||
configurationData.MemberDecryptionType = MemberDecryptionType.TrustedDeviceEncryption;
|
||||
ssoConfig.Data = configurationData.Serialize();
|
||||
approvingDevice.Type = LoginApprovingDeviceTypes.Types.First();
|
||||
_deviceRepository.GetManyByUserIdAsync(user.Id).Returns(new Device[] { approvingDevice });
|
||||
|
||||
var result = await _builder.ForUser(user).WithSso(ssoConfig).WithDevice(device).BuildAsync();
|
||||
|
||||
Assert.True(result.TrustedDeviceOption?.HasLoginApprovingDevice);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Build_WhenManageResetPasswordPermissions_ShouldReturnHasManageResetPasswordPermissionTrue(
|
||||
SsoConfig ssoConfig,
|
||||
SsoConfigurationData configurationData,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
_featureService.IsEnabled(FeatureFlagKeys.TrustedDeviceEncryption, _currentContext).Returns(true);
|
||||
configurationData.MemberDecryptionType = MemberDecryptionType.TrustedDeviceEncryption;
|
||||
ssoConfig.Data = configurationData.Serialize();
|
||||
ssoConfig.OrganizationId = organization.Id;
|
||||
_currentContext.Organizations.Returns(new List<CurrentContextOrganization>(new CurrentContextOrganization[] { organization }));
|
||||
_currentContext.ManageResetPassword(organization.Id).Returns(true);
|
||||
|
||||
var result = await _builder.WithSso(ssoConfig).BuildAsync();
|
||||
|
||||
Assert.True(result.TrustedDeviceOption?.HasManageResetPasswordPermission);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Build_WhenUserHasEnrolledIntoPasswordReset_ShouldReturnHasAdminApprovalTrue(
|
||||
SsoConfig ssoConfig,
|
||||
SsoConfigurationData configurationData,
|
||||
OrganizationUser organizationUser,
|
||||
User user)
|
||||
{
|
||||
_featureService.IsEnabled(FeatureFlagKeys.TrustedDeviceEncryption, _currentContext).Returns(true);
|
||||
configurationData.MemberDecryptionType = MemberDecryptionType.TrustedDeviceEncryption;
|
||||
ssoConfig.Data = configurationData.Serialize();
|
||||
organizationUser.ResetPasswordKey = "resetPasswordKey";
|
||||
_organizationUserRepository.GetByOrganizationAsync(ssoConfig.OrganizationId, user.Id).Returns(organizationUser);
|
||||
|
||||
var result = await _builder.ForUser(user).WithSso(ssoConfig).BuildAsync();
|
||||
|
||||
Assert.True(result.TrustedDeviceOption?.HasAdminApproval);
|
||||
}
|
||||
}
|
||||
@@ -271,6 +271,24 @@
|
||||
"Microsoft.Win32.Registry": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "4HVjzx1F8v5J+U7oa8RGAQGj2QzmzNSu87r18Sh+dlh10uyZZL8teAaT/FaVLDObnfItGdPFvN8mwpF/HkI3Xw==",
|
||||
"dependencies": {
|
||||
"Duende.IdentityServer.Storage": "6.0.4",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "s5gAjfbpr2IMgI+fU2Nx+2AZdzstmbt9gpo13iX7GwvqSeSaBVqj9ZskAN0R2KF1OemPdZuGnfaTcevdXMUrrw==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "6.0.0",
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Fare": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
@@ -315,49 +333,8 @@
|
||||
},
|
||||
"IdentityModel": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==",
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "11.0.2",
|
||||
"System.Text.Encodings.Web": "4.7.0"
|
||||
}
|
||||
},
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0",
|
||||
"IdentityServer4.Storage": "4.1.2",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0",
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0",
|
||||
"Newtonsoft.Json": "12.0.2"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.AccessTokenValidation": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.1",
|
||||
"contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==",
|
||||
"dependencies": {
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0"
|
||||
}
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "eVHCR7a6m/dm5RFcBzE3qs/Jg5j9R5Rjpu8aTOv9e4AFvaQtBXb5ah7kmwU+YwA0ufRwz4wf1hnIvsD2hSnI4g=="
|
||||
},
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": {
|
||||
"type": "Transitive",
|
||||
@@ -458,10 +435,10 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "cJxdro36spFzk/K2OFCddM6vZ+yoj6ug8mTFRH3Gdv1Pul/buSuCtfb/FSCp31UmS5S4C1315dU7wX3ErLFuDg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0"
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Cryptography.Internal": {
|
||||
@@ -494,8 +471,8 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.32",
|
||||
"contentHash": "MPL4iVyiaRxnOUY5VATHjvhDWaAEFb77KFiUxVRklv3Z3v+STofUr1UG/aCt1O9cgN7FVTDaC5A7U+zsLub8Xg=="
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "Z/UU4NEBm5UgNufJmw+j5baW26ytCOIZ0G7sZocPaOzsUeBon1bkM3lSMNZQG2GmDjAIVP2XMSODf2jzSGbibw=="
|
||||
},
|
||||
"Microsoft.Azure.Amqp": {
|
||||
"type": "Transitive",
|
||||
@@ -2872,7 +2849,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "[4.17.0, )",
|
||||
"AutoFixture.Xunit2": "[4.17.0, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )",
|
||||
"Microsoft.NET.Test.Sdk": "[17.1.0, )",
|
||||
"NSubstitute": "[4.3.0, )",
|
||||
@@ -2894,10 +2871,9 @@
|
||||
"BitPay.Light": "[1.0.1907, )",
|
||||
"Braintree": "[5.19.0, )",
|
||||
"DnsClient": "[1.7.0, )",
|
||||
"Duende.IdentityServer": "[6.0.4, )",
|
||||
"Fido2.AspNet": "[3.0.1, )",
|
||||
"Handlebars.Net": "[2.1.2, )",
|
||||
"IdentityServer4": "[4.1.2, )",
|
||||
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
|
||||
"LaunchDarkly.ServerSdk": "[8.0.0, )",
|
||||
"MailKit": "[4.2.0, )",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
|
||||
@@ -2925,15 +2901,15 @@
|
||||
"identity": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"SharedWeb": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"SharedWeb": "[2023.10.3, )",
|
||||
"Swashbuckle.AspNetCore.SwaggerGen": "[6.5.0, )"
|
||||
}
|
||||
},
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Dapper": "[2.0.123, )"
|
||||
}
|
||||
},
|
||||
@@ -2941,7 +2917,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
|
||||
@@ -2953,9 +2929,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"Infrastructure.Dapper": "[2023.10.2, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.2, )"
|
||||
"Core": "[2023.10.3, )",
|
||||
"Infrastructure.Dapper": "[2023.10.3, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.3, )"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,13 @@ using Bit.Core.Test.AutoFixture.Attributes;
|
||||
using Bit.Infrastructure.EFIntegration.Test.AutoFixture;
|
||||
using Bit.Infrastructure.EFIntegration.Test.Repositories.EqualityComparers;
|
||||
using Xunit;
|
||||
using EfAdminConsoleRepo = Bit.Infrastructure.EntityFramework.AdminConsole.Repositories;
|
||||
using EfRepo = Bit.Infrastructure.EntityFramework.Repositories;
|
||||
using Policy = Bit.Core.Entities.Policy;
|
||||
using Policy = Bit.Core.AdminConsole.Entities.Policy;
|
||||
using SqlAdminConsoleRepo = Bit.Infrastructure.Dapper.AdminConsole.Repositories;
|
||||
using SqlRepo = Bit.Infrastructure.Dapper.Repositories;
|
||||
|
||||
namespace Bit.Infrastructure.EFIntegration.Test.Repositories;
|
||||
namespace Bit.Infrastructure.EFIntegration.Test.AdminConsole.Repositories;
|
||||
|
||||
public class PolicyRepositoryTests
|
||||
{
|
||||
@@ -16,9 +18,9 @@ public class PolicyRepositoryTests
|
||||
Policy policy,
|
||||
Organization organization,
|
||||
PolicyCompare equalityComparer,
|
||||
List<EfRepo.PolicyRepository> suts,
|
||||
List<EfAdminConsoleRepo.PolicyRepository> suts,
|
||||
List<EfRepo.OrganizationRepository> efOrganizationRepos,
|
||||
SqlRepo.PolicyRepository sqlPolicyRepo,
|
||||
SqlAdminConsoleRepo.PolicyRepository sqlPolicyRepo,
|
||||
SqlRepo.OrganizationRepository sqlOrganizationRepo
|
||||
)
|
||||
{
|
||||
@@ -4,6 +4,7 @@ using AutoFixture.Kernel;
|
||||
using AutoMapper;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Infrastructure.EFIntegration.Test.Helpers;
|
||||
using Bit.Infrastructure.EntityFramework.AdminConsole.Models;
|
||||
using Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider;
|
||||
using Bit.Infrastructure.EntityFramework.Auth.Models;
|
||||
using Bit.Infrastructure.EntityFramework.Models;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using AutoFixture;
|
||||
using AutoFixture.Kernel;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Infrastructure.EntityFramework.AdminConsole.Repositories;
|
||||
using Bit.Infrastructure.EntityFramework.Repositories;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
|
||||
namespace Bit.Infrastructure.EFIntegration.Test.Repositories.EqualityComparers;
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System.Text.Json;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Entities.Provider;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
@@ -13,6 +15,7 @@ using Xunit;
|
||||
using EfAdminConsoleRepo = Bit.Infrastructure.EntityFramework.AdminConsole.Repositories;
|
||||
using EfRepo = Bit.Infrastructure.EntityFramework.Repositories;
|
||||
using OrganizationUser = Bit.Core.Entities.OrganizationUser;
|
||||
using SqlAdminConsoleRepo = Bit.Infrastructure.Dapper.AdminConsole.Repositories;
|
||||
using SqlRepo = Bit.Infrastructure.Dapper.Repositories;
|
||||
|
||||
namespace Bit.Infrastructure.EFIntegration.Test.Repositories;
|
||||
@@ -182,7 +185,7 @@ public class OrganizationUserRepositoryTests
|
||||
OrganizationUserPolicyDetailsCompare equalityComparer,
|
||||
|
||||
// Auto data - EF repos
|
||||
List<EfRepo.PolicyRepository> efPolicyRepository,
|
||||
List<EfAdminConsoleRepo.PolicyRepository> efPolicyRepository,
|
||||
List<EfRepo.UserRepository> efUserRepository,
|
||||
List<EfRepo.OrganizationRepository> efOrganizationRepository,
|
||||
List<EfRepo.OrganizationUserRepository> suts,
|
||||
@@ -191,7 +194,7 @@ public class OrganizationUserRepositoryTests
|
||||
List<EfAdminConsoleRepo.ProviderUserRepository> efProviderUserRepository,
|
||||
|
||||
// Auto data - SQL repos
|
||||
SqlRepo.PolicyRepository sqlPolicyRepo,
|
||||
SqlAdminConsoleRepo.PolicyRepository sqlPolicyRepo,
|
||||
SqlRepo.UserRepository sqlUserRepo,
|
||||
SqlRepo.OrganizationRepository sqlOrganizationRepo,
|
||||
EfAdminConsoleRepo.ProviderRepository sqlProviderRepo,
|
||||
|
||||
@@ -272,6 +272,24 @@
|
||||
"Microsoft.Win32.Registry": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "4HVjzx1F8v5J+U7oa8RGAQGj2QzmzNSu87r18Sh+dlh10uyZZL8teAaT/FaVLDObnfItGdPFvN8mwpF/HkI3Xw==",
|
||||
"dependencies": {
|
||||
"Duende.IdentityServer.Storage": "6.0.4",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "s5gAjfbpr2IMgI+fU2Nx+2AZdzstmbt9gpo13iX7GwvqSeSaBVqj9ZskAN0R2KF1OemPdZuGnfaTcevdXMUrrw==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "6.0.0",
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Fare": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
@@ -316,49 +334,8 @@
|
||||
},
|
||||
"IdentityModel": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==",
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "11.0.2",
|
||||
"System.Text.Encodings.Web": "4.7.0"
|
||||
}
|
||||
},
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0",
|
||||
"IdentityServer4.Storage": "4.1.2",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0",
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0",
|
||||
"Newtonsoft.Json": "12.0.2"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.AccessTokenValidation": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.1",
|
||||
"contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==",
|
||||
"dependencies": {
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0"
|
||||
}
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "eVHCR7a6m/dm5RFcBzE3qs/Jg5j9R5Rjpu8aTOv9e4AFvaQtBXb5ah7kmwU+YwA0ufRwz4wf1hnIvsD2hSnI4g=="
|
||||
},
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": {
|
||||
"type": "Transitive",
|
||||
@@ -459,10 +436,10 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "cJxdro36spFzk/K2OFCddM6vZ+yoj6ug8mTFRH3Gdv1Pul/buSuCtfb/FSCp31UmS5S4C1315dU7wX3ErLFuDg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0"
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Cryptography.Internal": {
|
||||
@@ -495,8 +472,8 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.32",
|
||||
"contentHash": "MPL4iVyiaRxnOUY5VATHjvhDWaAEFb77KFiUxVRklv3Z3v+STofUr1UG/aCt1O9cgN7FVTDaC5A7U+zsLub8Xg=="
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "Z/UU4NEBm5UgNufJmw+j5baW26ytCOIZ0G7sZocPaOzsUeBon1bkM3lSMNZQG2GmDjAIVP2XMSODf2jzSGbibw=="
|
||||
},
|
||||
"Microsoft.Azure.Amqp": {
|
||||
"type": "Transitive",
|
||||
@@ -2852,7 +2829,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "[4.17.0, )",
|
||||
"AutoFixture.Xunit2": "[4.17.0, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )",
|
||||
"Microsoft.NET.Test.Sdk": "[17.1.0, )",
|
||||
"NSubstitute": "[4.3.0, )",
|
||||
@@ -2874,10 +2851,9 @@
|
||||
"BitPay.Light": "[1.0.1907, )",
|
||||
"Braintree": "[5.19.0, )",
|
||||
"DnsClient": "[1.7.0, )",
|
||||
"Duende.IdentityServer": "[6.0.4, )",
|
||||
"Fido2.AspNet": "[3.0.1, )",
|
||||
"Handlebars.Net": "[2.1.2, )",
|
||||
"IdentityServer4": "[4.1.2, )",
|
||||
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
|
||||
"LaunchDarkly.ServerSdk": "[8.0.0, )",
|
||||
"MailKit": "[4.2.0, )",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
|
||||
@@ -2907,8 +2883,8 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "[4.17.0, )",
|
||||
"AutoFixture.Xunit2": "[4.17.0, )",
|
||||
"Common": "[2023.10.2, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Common": "[2023.10.3, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )",
|
||||
"Microsoft.NET.Test.Sdk": "[17.1.0, )",
|
||||
"NSubstitute": "[4.3.0, )",
|
||||
@@ -2918,7 +2894,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Dapper": "[2.0.123, )"
|
||||
}
|
||||
},
|
||||
@@ -2926,7 +2902,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
|
||||
|
||||
@@ -254,6 +254,24 @@
|
||||
"Microsoft.Win32.Registry": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "4HVjzx1F8v5J+U7oa8RGAQGj2QzmzNSu87r18Sh+dlh10uyZZL8teAaT/FaVLDObnfItGdPFvN8mwpF/HkI3Xw==",
|
||||
"dependencies": {
|
||||
"Duende.IdentityServer.Storage": "6.0.4",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "s5gAjfbpr2IMgI+fU2Nx+2AZdzstmbt9gpo13iX7GwvqSeSaBVqj9ZskAN0R2KF1OemPdZuGnfaTcevdXMUrrw==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "6.0.0",
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Fido2": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.1",
|
||||
@@ -290,49 +308,8 @@
|
||||
},
|
||||
"IdentityModel": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==",
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "11.0.2",
|
||||
"System.Text.Encodings.Web": "4.7.0"
|
||||
}
|
||||
},
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0",
|
||||
"IdentityServer4.Storage": "4.1.2",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0",
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0",
|
||||
"Newtonsoft.Json": "12.0.2"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.AccessTokenValidation": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.1",
|
||||
"contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==",
|
||||
"dependencies": {
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0"
|
||||
}
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "eVHCR7a6m/dm5RFcBzE3qs/Jg5j9R5Rjpu8aTOv9e4AFvaQtBXb5ah7kmwU+YwA0ufRwz4wf1hnIvsD2hSnI4g=="
|
||||
},
|
||||
"LaunchDarkly.Cache": {
|
||||
"type": "Transitive",
|
||||
@@ -424,10 +401,10 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "cJxdro36spFzk/K2OFCddM6vZ+yoj6ug8mTFRH3Gdv1Pul/buSuCtfb/FSCp31UmS5S4C1315dU7wX3ErLFuDg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0"
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Cryptography.Internal": {
|
||||
@@ -460,8 +437,8 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.32",
|
||||
"contentHash": "MPL4iVyiaRxnOUY5VATHjvhDWaAEFb77KFiUxVRklv3Z3v+STofUr1UG/aCt1O9cgN7FVTDaC5A7U+zsLub8Xg=="
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "Z/UU4NEBm5UgNufJmw+j5baW26ytCOIZ0G7sZocPaOzsUeBon1bkM3lSMNZQG2GmDjAIVP2XMSODf2jzSGbibw=="
|
||||
},
|
||||
"Microsoft.Azure.Amqp": {
|
||||
"type": "Transitive",
|
||||
@@ -2732,10 +2709,9 @@
|
||||
"BitPay.Light": "[1.0.1907, )",
|
||||
"Braintree": "[5.19.0, )",
|
||||
"DnsClient": "[1.7.0, )",
|
||||
"Duende.IdentityServer": "[6.0.4, )",
|
||||
"Fido2.AspNet": "[3.0.1, )",
|
||||
"Handlebars.Net": "[2.1.2, )",
|
||||
"IdentityServer4": "[4.1.2, )",
|
||||
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
|
||||
"LaunchDarkly.ServerSdk": "[8.0.0, )",
|
||||
"MailKit": "[4.2.0, )",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
|
||||
@@ -2763,7 +2739,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Dapper": "[2.0.123, )"
|
||||
}
|
||||
},
|
||||
@@ -2771,7 +2747,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
|
||||
|
||||
@@ -249,6 +249,24 @@
|
||||
"Microsoft.Win32.Registry": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "4HVjzx1F8v5J+U7oa8RGAQGj2QzmzNSu87r18Sh+dlh10uyZZL8teAaT/FaVLDObnfItGdPFvN8mwpF/HkI3Xw==",
|
||||
"dependencies": {
|
||||
"Duende.IdentityServer.Storage": "6.0.4",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Duende.IdentityServer.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.4",
|
||||
"contentHash": "s5gAjfbpr2IMgI+fU2Nx+2AZdzstmbt9gpo13iX7GwvqSeSaBVqj9ZskAN0R2KF1OemPdZuGnfaTcevdXMUrrw==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "6.0.0",
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Fare": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
@@ -293,49 +311,8 @@
|
||||
},
|
||||
"IdentityModel": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==",
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "11.0.2",
|
||||
"System.Text.Encodings.Web": "4.7.0"
|
||||
}
|
||||
},
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0",
|
||||
"IdentityServer4.Storage": "4.1.2",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0",
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0",
|
||||
"Newtonsoft.Json": "12.0.2"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.AccessTokenValidation": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.1",
|
||||
"contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==",
|
||||
"dependencies": {
|
||||
"IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0"
|
||||
}
|
||||
},
|
||||
"IdentityServer4.Storage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.2",
|
||||
"contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==",
|
||||
"dependencies": {
|
||||
"IdentityModel": "4.4.0"
|
||||
}
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "eVHCR7a6m/dm5RFcBzE3qs/Jg5j9R5Rjpu8aTOv9e4AFvaQtBXb5ah7kmwU+YwA0ufRwz4wf1hnIvsD2hSnI4g=="
|
||||
},
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": {
|
||||
"type": "Transitive",
|
||||
@@ -436,10 +413,10 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "cJxdro36spFzk/K2OFCddM6vZ+yoj6ug8mTFRH3Gdv1Pul/buSuCtfb/FSCp31UmS5S4C1315dU7wX3ErLFuDg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0"
|
||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Cryptography.Internal": {
|
||||
@@ -472,8 +449,8 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.32",
|
||||
"contentHash": "MPL4iVyiaRxnOUY5VATHjvhDWaAEFb77KFiUxVRklv3Z3v+STofUr1UG/aCt1O9cgN7FVTDaC5A7U+zsLub8Xg=="
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "Z/UU4NEBm5UgNufJmw+j5baW26ytCOIZ0G7sZocPaOzsUeBon1bkM3lSMNZQG2GmDjAIVP2XMSODf2jzSGbibw=="
|
||||
},
|
||||
"Microsoft.AspNetCore.TestHost": {
|
||||
"type": "Transitive",
|
||||
@@ -2982,7 +2959,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "[4.17.0, )",
|
||||
"AutoFixture.Xunit2": "[4.17.0, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )",
|
||||
"Microsoft.NET.Test.Sdk": "[17.1.0, )",
|
||||
"NSubstitute": "[4.3.0, )",
|
||||
@@ -3004,10 +2981,9 @@
|
||||
"BitPay.Light": "[1.0.1907, )",
|
||||
"Braintree": "[5.19.0, )",
|
||||
"DnsClient": "[1.7.0, )",
|
||||
"Duende.IdentityServer": "[6.0.4, )",
|
||||
"Fido2.AspNet": "[3.0.1, )",
|
||||
"Handlebars.Net": "[2.1.2, )",
|
||||
"IdentityServer4": "[4.1.2, )",
|
||||
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
|
||||
"LaunchDarkly.ServerSdk": "[8.0.0, )",
|
||||
"MailKit": "[4.2.0, )",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
|
||||
@@ -3035,15 +3011,15 @@
|
||||
"identity": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"SharedWeb": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"SharedWeb": "[2023.10.3, )",
|
||||
"Swashbuckle.AspNetCore.SwaggerGen": "[6.5.0, )"
|
||||
}
|
||||
},
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Dapper": "[2.0.123, )"
|
||||
}
|
||||
},
|
||||
@@ -3051,7 +3027,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.10.2, )",
|
||||
"Core": "[2023.10.3, )",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
|
||||
@@ -3063,9 +3039,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.10.2, )",
|
||||
"Infrastructure.Dapper": "[2023.10.2, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.2, )"
|
||||
"Core": "[2023.10.3, )",
|
||||
"Infrastructure.Dapper": "[2023.10.3, )",
|
||||
"Infrastructure.EntityFramework": "[2023.10.3, )"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user