1
0
mirror of https://github.com/bitwarden/server synced 2026-01-15 15:03:34 +00:00

Merge remote-tracking branch 'origin/master' into ac/ac-1638/disallow-secrets-manager-for-msp-managed-organizations

This commit is contained in:
Thomas Rittson
2023-09-25 14:29:59 +10:00
104 changed files with 9865 additions and 2034 deletions

View File

@@ -44,7 +44,7 @@
<div class="float-right">
@if (org.Status == OrganizationStatusType.Pending)
{
<a href="#" class="float-right" onclick="return resendOwnerInvite('@org.OrganizationId', '@org.OrganizationName');">
<a href="#" class="float-right" onclick="return resendOwnerInvite('@org.OrganizationId');">
<i class="fa fa-envelope-o fa-lg" title="Resend Setup Invite"></i>
</a>
}

View File

@@ -1,14 +1,14 @@
<script>
function resendOwnerInvite(orgId, orgName) {
if (confirm('Resend invite to "' + orgName + '"?')) {
function resendOwnerInvite(orgId) {
if (confirm('Resend invite to organization?')) {
$.ajax({
type: "POST",
url: '@Url.Action("ResendOwnerInvite", "Organizations")' + '?id=' + orgId,
dataType: 'json',
contentType: false,
processData: false,
processData: false,
success: function (response) {
alert('Invitation has been resent!');
alert('Invitation has been resent!');
},
error: function (response) {
alert("Error!");
@@ -17,4 +17,4 @@
}
return false;
}
</script>
</script>

View File

@@ -178,10 +178,11 @@
},
"Braintree": {
"type": "Transitive",
"resolved": "5.12.0",
"contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==",
"resolved": "5.19.0",
"contentHash": "B60wIX54g78nMsy5cJkvSfqs1VasYDXWFZQW0cUQ4QeW8Y5jPyBSaoxHwKC806lXUDaKC8kr5Y7Q6EdsBkPANQ==",
"dependencies": {
"Newtonsoft.Json": "9.0.1",
"Microsoft.CSharp": "4.7.0",
"Newtonsoft.Json": "13.0.1",
"System.Xml.XPath.XmlDocument": "4.3.0"
}
},
@@ -2791,114 +2792,114 @@
"commercial.core": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2"
"Core": "[2023.9.0, )"
}
},
"commercial.infrastructure.entityframework": {
"type": "Project",
"dependencies": {
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
"Core": "2023.7.2",
"Infrastructure.EntityFramework": "2023.7.2"
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
"Core": "[2023.9.0, )",
"Infrastructure.EntityFramework": "[2023.9.0, )"
}
},
"core": {
"type": "Project",
"dependencies": {
"AWSSDK.SQS": "3.7.2.47",
"AWSSDK.SimpleEmail": "3.7.0.150",
"AspNetCoreRateLimit": "4.0.2",
"AspNetCoreRateLimit.Redis": "1.0.1",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "1.3.2",
"Azure.Messaging.ServiceBus": "7.15.0",
"Azure.Storage.Blobs": "12.14.1",
"Azure.Storage.Queues": "12.12.0",
"BitPay.Light": "1.0.1907",
"Braintree": "5.12.0",
"DnsClient": "1.7.0",
"Fido2.AspNet": "3.0.1",
"Handlebars.Net": "2.1.2",
"IdentityServer4": "4.1.2",
"IdentityServer4.AccessTokenValidation": "3.0.1",
"LaunchDarkly.ServerSdk": "7.0.0",
"MailKit": "3.2.0",
"Microsoft.AspNetCore.Authentication.JwtBearer": "6.0.4",
"Microsoft.Azure.Cosmos.Table": "1.0.8",
"Microsoft.Azure.NotificationHubs": "4.1.0",
"Microsoft.Data.SqlClient": "5.0.1",
"Microsoft.Extensions.Caching.StackExchangeRedis": "6.0.6",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1",
"Microsoft.Extensions.Configuration.UserSecrets": "6.0.1",
"Microsoft.Extensions.Identity.Stores": "6.0.4",
"Newtonsoft.Json": "13.0.1",
"Otp.NET": "1.2.2",
"Quartz": "3.4.0",
"SendGrid": "9.27.0",
"Sentry.Serilog": "3.16.0",
"Serilog.AspNetCore": "5.0.0",
"Serilog.Extensions.Logging": "3.1.0",
"Serilog.Extensions.Logging.File": "2.0.0",
"Serilog.Sinks.AzureCosmosDB": "2.0.0",
"Serilog.Sinks.SyslogMessages": "2.0.6",
"Stripe.net": "40.0.0",
"YubicoDotNetClient": "1.2.0"
"AWSSDK.SQS": "[3.7.2.47, )",
"AWSSDK.SimpleEmail": "[3.7.0.150, )",
"AspNetCoreRateLimit": "[4.0.2, )",
"AspNetCoreRateLimit.Redis": "[1.0.1, )",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.3.2, )",
"Azure.Messaging.ServiceBus": "[7.15.0, )",
"Azure.Storage.Blobs": "[12.14.1, )",
"Azure.Storage.Queues": "[12.12.0, )",
"BitPay.Light": "[1.0.1907, )",
"Braintree": "[5.19.0, )",
"DnsClient": "[1.7.0, )",
"Fido2.AspNet": "[3.0.1, )",
"Handlebars.Net": "[2.1.2, )",
"IdentityServer4": "[4.1.2, )",
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
"LaunchDarkly.ServerSdk": "[7.0.0, )",
"MailKit": "[3.2.0, )",
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
"Microsoft.Azure.Cosmos.Table": "[1.0.8, )",
"Microsoft.Azure.NotificationHubs": "[4.1.0, )",
"Microsoft.Data.SqlClient": "[5.0.1, )",
"Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )",
"Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )",
"Microsoft.Extensions.Identity.Stores": "[6.0.4, )",
"Newtonsoft.Json": "[13.0.1, )",
"Otp.NET": "[1.2.2, )",
"Quartz": "[3.4.0, )",
"SendGrid": "[9.27.0, )",
"Sentry.Serilog": "[3.16.0, )",
"Serilog.AspNetCore": "[5.0.0, )",
"Serilog.Extensions.Logging": "[3.1.0, )",
"Serilog.Extensions.Logging.File": "[2.0.0, )",
"Serilog.Sinks.AzureCosmosDB": "[2.0.0, )",
"Serilog.Sinks.SyslogMessages": "[2.0.6, )",
"Stripe.net": "[40.0.0, )",
"YubicoDotNetClient": "[1.2.0, )"
}
},
"infrastructure.dapper": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Dapper": "2.0.123"
"Core": "[2023.9.0, )",
"Dapper": "[2.0.123, )"
}
},
"infrastructure.entityframework": {
"type": "Project",
"dependencies": {
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
"Core": "2023.7.2",
"Microsoft.EntityFrameworkCore.Relational": "7.0.5",
"Microsoft.EntityFrameworkCore.SqlServer": "7.0.5",
"Microsoft.EntityFrameworkCore.Sqlite": "7.0.5",
"Npgsql.EntityFrameworkCore.PostgreSQL": "7.0.4",
"Pomelo.EntityFrameworkCore.MySql": "7.0.0",
"linq2db.EntityFrameworkCore": "7.5.0"
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
"Core": "[2023.9.0, )",
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
"Npgsql.EntityFrameworkCore.PostgreSQL": "[7.0.4, )",
"Pomelo.EntityFrameworkCore.MySql": "[7.0.0, )",
"linq2db.EntityFrameworkCore": "[7.5.0, )"
}
},
"migrator": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Microsoft.Extensions.Logging": "6.0.0",
"dbup-sqlserver": "5.0.8"
"Core": "[2023.9.0, )",
"Microsoft.Extensions.Logging": "[6.0.0, )",
"dbup-sqlserver": "[5.0.8, )"
}
},
"mysqlmigrations": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Infrastructure.EntityFramework": "2023.7.2"
"Core": "[2023.9.0, )",
"Infrastructure.EntityFramework": "[2023.9.0, )"
}
},
"postgresmigrations": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Infrastructure.EntityFramework": "2023.7.2"
"Core": "[2023.9.0, )",
"Infrastructure.EntityFramework": "[2023.9.0, )"
}
},
"sharedweb": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Infrastructure.Dapper": "2023.7.2",
"Infrastructure.EntityFramework": "2023.7.2"
"Core": "[2023.9.0, )",
"Infrastructure.Dapper": "[2023.9.0, )",
"Infrastructure.EntityFramework": "[2023.9.0, )"
}
},
"sqlitemigrations": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Infrastructure.EntityFramework": "2023.7.2"
"Core": "[2023.9.0, )",
"Infrastructure.EntityFramework": "[2023.9.0, )"
}
}
}

View File

@@ -236,7 +236,7 @@ public class TwoFactorController : Controller
[HttpPost("get-webauthn")]
public async Task<TwoFactorWebAuthnResponseModel> GetWebAuthn([FromBody] SecretVerificationRequestModel model)
{
var user = await CheckAsync(model, true);
var user = await CheckAsync(model, false);
var response = new TwoFactorWebAuthnResponseModel(user);
return response;
}
@@ -245,7 +245,7 @@ public class TwoFactorController : Controller
[ApiExplorerSettings(IgnoreApi = true)] // Disable Swagger due to CredentialCreateOptions not converting properly
public async Task<CredentialCreateOptions> GetWebAuthnChallenge([FromBody] SecretVerificationRequestModel model)
{
var user = await CheckAsync(model, true);
var user = await CheckAsync(model, false);
var reg = await _userService.StartWebAuthnRegistrationAsync(user);
return reg;
}
@@ -254,7 +254,7 @@ public class TwoFactorController : Controller
[HttpPost("webauthn")]
public async Task<TwoFactorWebAuthnResponseModel> PutWebAuthn([FromBody] TwoFactorWebAuthnRequestModel model)
{
var user = await CheckAsync(model, true);
var user = await CheckAsync(model, false);
var success = await _userService.CompleteWebAuthRegistrationAsync(
user, model.Id.Value, model.Name, model.DeviceResponse);
@@ -271,7 +271,7 @@ public class TwoFactorController : Controller
public async Task<TwoFactorWebAuthnResponseModel> DeleteWebAuthn(
[FromBody] TwoFactorWebAuthnDeleteRequestModel model)
{
var user = await CheckAsync(model, true);
var user = await CheckAsync(model, false);
await _userService.DeleteWebAuthnKeyAsync(user, model.Id.Value);
var response = new TwoFactorWebAuthnResponseModel(user);
return response;

View File

@@ -30,6 +30,7 @@ public class OrganizationUsersController : Controller
private readonly ICurrentContext _currentContext;
private readonly ICountNewSmSeatsRequiredQuery _countNewSmSeatsRequiredQuery;
private readonly IUpdateSecretsManagerSubscriptionCommand _updateSecretsManagerSubscriptionCommand;
private readonly IUpdateOrganizationUserGroupsCommand _updateOrganizationUserGroupsCommand;
public OrganizationUsersController(
IOrganizationRepository organizationRepository,
@@ -41,7 +42,8 @@ public class OrganizationUsersController : Controller
IPolicyRepository policyRepository,
ICurrentContext currentContext,
ICountNewSmSeatsRequiredQuery countNewSmSeatsRequiredQuery,
IUpdateSecretsManagerSubscriptionCommand updateSecretsManagerSubscriptionCommand)
IUpdateSecretsManagerSubscriptionCommand updateSecretsManagerSubscriptionCommand,
IUpdateOrganizationUserGroupsCommand updateOrganizationUserGroupsCommand)
{
_organizationRepository = organizationRepository;
_organizationUserRepository = organizationUserRepository;
@@ -53,6 +55,7 @@ public class OrganizationUsersController : Controller
_currentContext = currentContext;
_countNewSmSeatsRequiredQuery = countNewSmSeatsRequiredQuery;
_updateSecretsManagerSubscriptionCommand = updateSecretsManagerSubscriptionCommand;
_updateOrganizationUserGroupsCommand = updateOrganizationUserGroupsCommand;
}
[HttpGet("{id}")]
@@ -308,7 +311,7 @@ public class OrganizationUsersController : Controller
}
var loggedInUserId = _userService.GetProperUserId(User);
await _organizationService.UpdateUserGroupsAsync(organizationUser, model.GroupIds.Select(g => new Guid(g)), loggedInUserId);
await _updateOrganizationUserGroupsCommand.UpdateUserGroupsAsync(organizationUser, model.GroupIds.Select(g => new Guid(g)), loggedInUserId);
}
[HttpPut("{userId}/reset-password-enrollment")]

View File

@@ -3,6 +3,7 @@ using Bit.Api.Models.Public.Request;
using Bit.Api.Models.Public.Response;
using Bit.Core.Context;
using Bit.Core.Models.Business;
using Bit.Core.OrganizationFeatures.OrganizationUsers.Interfaces;
using Bit.Core.Repositories;
using Bit.Core.Services;
using Microsoft.AspNetCore.Authorization;
@@ -19,19 +20,22 @@ public class MembersController : Controller
private readonly IOrganizationService _organizationService;
private readonly IUserService _userService;
private readonly ICurrentContext _currentContext;
private readonly IUpdateOrganizationUserGroupsCommand _updateOrganizationUserGroupsCommand;
public MembersController(
IOrganizationUserRepository organizationUserRepository,
IGroupRepository groupRepository,
IOrganizationService organizationService,
IUserService userService,
ICurrentContext currentContext)
ICurrentContext currentContext,
IUpdateOrganizationUserGroupsCommand updateOrganizationUserGroupsCommand)
{
_organizationUserRepository = organizationUserRepository;
_groupRepository = groupRepository;
_organizationService = organizationService;
_userService = userService;
_currentContext = currentContext;
_updateOrganizationUserGroupsCommand = updateOrganizationUserGroupsCommand;
}
/// <summary>
@@ -183,7 +187,7 @@ public class MembersController : Controller
{
return new NotFoundResult();
}
await _organizationService.UpdateUserGroupsAsync(existingUser, model.GroupIds, null);
await _updateOrganizationUserGroupsCommand.UpdateUserGroupsAsync(existingUser, model.GroupIds, null);
return new OkResult();
}

View File

@@ -79,8 +79,8 @@ public class ProjectsController : Controller
throw new NotFoundException();
}
var (max, atMax) = await _maxProjectsQuery.GetByOrgIdAsync(organizationId);
if (atMax != null && atMax.Value)
var (max, overMax) = await _maxProjectsQuery.GetByOrgIdAsync(organizationId, 1);
if (overMax != null && overMax.Value)
{
throw new BadRequestException($"You have reached the maximum number of projects ({max}) for this plan.");
}

View File

@@ -4,6 +4,7 @@ using Bit.Core.Context;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.SecretsManager.Commands.Porting.Interfaces;
using Bit.Core.SecretsManager.Queries.Projects.Interfaces;
using Bit.Core.SecretsManager.Repositories;
using Bit.Core.Services;
using Bit.Core.Utilities;
@@ -19,14 +20,18 @@ public class SecretsManagerPortingController : Controller
private readonly ISecretRepository _secretRepository;
private readonly IProjectRepository _projectRepository;
private readonly IUserService _userService;
private readonly IMaxProjectsQuery _maxProjectsQuery;
private readonly IImportCommand _importCommand;
private readonly ICurrentContext _currentContext;
public SecretsManagerPortingController(ISecretRepository secretRepository, IProjectRepository projectRepository, IUserService userService, IImportCommand importCommand, ICurrentContext currentContext)
public SecretsManagerPortingController(ISecretRepository secretRepository, IProjectRepository projectRepository,
IUserService userService, IMaxProjectsQuery maxProjectsQuery, IImportCommand importCommand,
ICurrentContext currentContext)
{
_secretRepository = secretRepository;
_projectRepository = projectRepository;
_userService = userService;
_maxProjectsQuery = maxProjectsQuery;
_importCommand = importCommand;
_currentContext = currentContext;
}
@@ -69,6 +74,16 @@ public class SecretsManagerPortingController : Controller
throw new BadRequestException("A secret can only be in one project at a time.");
}
var projectsToAdd = importRequest.Projects?.Count();
if (projectsToAdd is > 0)
{
var (max, overMax) = await _maxProjectsQuery.GetByOrgIdAsync(organizationId, projectsToAdd.Value);
if (overMax != null && overMax.Value)
{
throw new BadRequestException($"The maximum number of projects for this plan is ({max}).");
}
}
await _importCommand.ImportAsync(organizationId, importRequest.ToSMImport());
}
}

View File

@@ -281,10 +281,11 @@
},
"Braintree": {
"type": "Transitive",
"resolved": "5.12.0",
"contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==",
"resolved": "5.19.0",
"contentHash": "B60wIX54g78nMsy5cJkvSfqs1VasYDXWFZQW0cUQ4QeW8Y5jPyBSaoxHwKC806lXUDaKC8kr5Y7Q6EdsBkPANQ==",
"dependencies": {
"Newtonsoft.Json": "9.0.1",
"Microsoft.CSharp": "4.7.0",
"Newtonsoft.Json": "13.0.1",
"System.Xml.XPath.XmlDocument": "4.3.0"
}
},
@@ -2771,85 +2772,85 @@
"commercial.core": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2"
"Core": "[2023.9.0, )"
}
},
"commercial.infrastructure.entityframework": {
"type": "Project",
"dependencies": {
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
"Core": "2023.7.2",
"Infrastructure.EntityFramework": "2023.7.2"
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
"Core": "[2023.9.0, )",
"Infrastructure.EntityFramework": "[2023.9.0, )"
}
},
"core": {
"type": "Project",
"dependencies": {
"AWSSDK.SQS": "3.7.2.47",
"AWSSDK.SimpleEmail": "3.7.0.150",
"AspNetCoreRateLimit": "4.0.2",
"AspNetCoreRateLimit.Redis": "1.0.1",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "1.3.2",
"Azure.Messaging.ServiceBus": "7.15.0",
"Azure.Storage.Blobs": "12.14.1",
"Azure.Storage.Queues": "12.12.0",
"BitPay.Light": "1.0.1907",
"Braintree": "5.12.0",
"DnsClient": "1.7.0",
"Fido2.AspNet": "3.0.1",
"Handlebars.Net": "2.1.2",
"IdentityServer4": "4.1.2",
"IdentityServer4.AccessTokenValidation": "3.0.1",
"LaunchDarkly.ServerSdk": "7.0.0",
"MailKit": "3.2.0",
"Microsoft.AspNetCore.Authentication.JwtBearer": "6.0.4",
"Microsoft.Azure.Cosmos.Table": "1.0.8",
"Microsoft.Azure.NotificationHubs": "4.1.0",
"Microsoft.Data.SqlClient": "5.0.1",
"Microsoft.Extensions.Caching.StackExchangeRedis": "6.0.6",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1",
"Microsoft.Extensions.Configuration.UserSecrets": "6.0.1",
"Microsoft.Extensions.Identity.Stores": "6.0.4",
"Newtonsoft.Json": "13.0.1",
"Otp.NET": "1.2.2",
"Quartz": "3.4.0",
"SendGrid": "9.27.0",
"Sentry.Serilog": "3.16.0",
"Serilog.AspNetCore": "5.0.0",
"Serilog.Extensions.Logging": "3.1.0",
"Serilog.Extensions.Logging.File": "2.0.0",
"Serilog.Sinks.AzureCosmosDB": "2.0.0",
"Serilog.Sinks.SyslogMessages": "2.0.6",
"Stripe.net": "40.0.0",
"YubicoDotNetClient": "1.2.0"
"AWSSDK.SQS": "[3.7.2.47, )",
"AWSSDK.SimpleEmail": "[3.7.0.150, )",
"AspNetCoreRateLimit": "[4.0.2, )",
"AspNetCoreRateLimit.Redis": "[1.0.1, )",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.3.2, )",
"Azure.Messaging.ServiceBus": "[7.15.0, )",
"Azure.Storage.Blobs": "[12.14.1, )",
"Azure.Storage.Queues": "[12.12.0, )",
"BitPay.Light": "[1.0.1907, )",
"Braintree": "[5.19.0, )",
"DnsClient": "[1.7.0, )",
"Fido2.AspNet": "[3.0.1, )",
"Handlebars.Net": "[2.1.2, )",
"IdentityServer4": "[4.1.2, )",
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
"LaunchDarkly.ServerSdk": "[7.0.0, )",
"MailKit": "[3.2.0, )",
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
"Microsoft.Azure.Cosmos.Table": "[1.0.8, )",
"Microsoft.Azure.NotificationHubs": "[4.1.0, )",
"Microsoft.Data.SqlClient": "[5.0.1, )",
"Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )",
"Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )",
"Microsoft.Extensions.Identity.Stores": "[6.0.4, )",
"Newtonsoft.Json": "[13.0.1, )",
"Otp.NET": "[1.2.2, )",
"Quartz": "[3.4.0, )",
"SendGrid": "[9.27.0, )",
"Sentry.Serilog": "[3.16.0, )",
"Serilog.AspNetCore": "[5.0.0, )",
"Serilog.Extensions.Logging": "[3.1.0, )",
"Serilog.Extensions.Logging.File": "[2.0.0, )",
"Serilog.Sinks.AzureCosmosDB": "[2.0.0, )",
"Serilog.Sinks.SyslogMessages": "[2.0.6, )",
"Stripe.net": "[40.0.0, )",
"YubicoDotNetClient": "[1.2.0, )"
}
},
"infrastructure.dapper": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Dapper": "2.0.123"
"Core": "[2023.9.0, )",
"Dapper": "[2.0.123, )"
}
},
"infrastructure.entityframework": {
"type": "Project",
"dependencies": {
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
"Core": "2023.7.2",
"Microsoft.EntityFrameworkCore.Relational": "7.0.5",
"Microsoft.EntityFrameworkCore.SqlServer": "7.0.5",
"Microsoft.EntityFrameworkCore.Sqlite": "7.0.5",
"Npgsql.EntityFrameworkCore.PostgreSQL": "7.0.4",
"Pomelo.EntityFrameworkCore.MySql": "7.0.0",
"linq2db.EntityFrameworkCore": "7.5.0"
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
"Core": "[2023.9.0, )",
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
"Npgsql.EntityFrameworkCore.PostgreSQL": "[7.0.4, )",
"Pomelo.EntityFrameworkCore.MySql": "[7.0.0, )",
"linq2db.EntityFrameworkCore": "[7.5.0, )"
}
},
"sharedweb": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Infrastructure.Dapper": "2023.7.2",
"Infrastructure.EntityFramework": "2023.7.2"
"Core": "[2023.9.0, )",
"Infrastructure.Dapper": "[2023.9.0, )",
"Infrastructure.EntityFramework": "[2023.9.0, )"
}
}
}

View File

@@ -158,10 +158,11 @@
},
"Braintree": {
"type": "Transitive",
"resolved": "5.12.0",
"contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==",
"resolved": "5.19.0",
"contentHash": "B60wIX54g78nMsy5cJkvSfqs1VasYDXWFZQW0cUQ4QeW8Y5jPyBSaoxHwKC806lXUDaKC8kr5Y7Q6EdsBkPANQ==",
"dependencies": {
"Newtonsoft.Json": "9.0.1",
"Microsoft.CSharp": "4.7.0",
"Newtonsoft.Json": "13.0.1",
"System.Xml.XPath.XmlDocument": "4.3.0"
}
},
@@ -2588,71 +2589,71 @@
"core": {
"type": "Project",
"dependencies": {
"AWSSDK.SQS": "3.7.2.47",
"AWSSDK.SimpleEmail": "3.7.0.150",
"AspNetCoreRateLimit": "4.0.2",
"AspNetCoreRateLimit.Redis": "1.0.1",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "1.3.2",
"Azure.Messaging.ServiceBus": "7.15.0",
"Azure.Storage.Blobs": "12.14.1",
"Azure.Storage.Queues": "12.12.0",
"BitPay.Light": "1.0.1907",
"Braintree": "5.12.0",
"DnsClient": "1.7.0",
"Fido2.AspNet": "3.0.1",
"Handlebars.Net": "2.1.2",
"IdentityServer4": "4.1.2",
"IdentityServer4.AccessTokenValidation": "3.0.1",
"LaunchDarkly.ServerSdk": "7.0.0",
"MailKit": "3.2.0",
"Microsoft.AspNetCore.Authentication.JwtBearer": "6.0.4",
"Microsoft.Azure.Cosmos.Table": "1.0.8",
"Microsoft.Azure.NotificationHubs": "4.1.0",
"Microsoft.Data.SqlClient": "5.0.1",
"Microsoft.Extensions.Caching.StackExchangeRedis": "6.0.6",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1",
"Microsoft.Extensions.Configuration.UserSecrets": "6.0.1",
"Microsoft.Extensions.Identity.Stores": "6.0.4",
"Newtonsoft.Json": "13.0.1",
"Otp.NET": "1.2.2",
"Quartz": "3.4.0",
"SendGrid": "9.27.0",
"Sentry.Serilog": "3.16.0",
"Serilog.AspNetCore": "5.0.0",
"Serilog.Extensions.Logging": "3.1.0",
"Serilog.Extensions.Logging.File": "2.0.0",
"Serilog.Sinks.AzureCosmosDB": "2.0.0",
"Serilog.Sinks.SyslogMessages": "2.0.6",
"Stripe.net": "40.0.0",
"YubicoDotNetClient": "1.2.0"
"AWSSDK.SQS": "[3.7.2.47, )",
"AWSSDK.SimpleEmail": "[3.7.0.150, )",
"AspNetCoreRateLimit": "[4.0.2, )",
"AspNetCoreRateLimit.Redis": "[1.0.1, )",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.3.2, )",
"Azure.Messaging.ServiceBus": "[7.15.0, )",
"Azure.Storage.Blobs": "[12.14.1, )",
"Azure.Storage.Queues": "[12.12.0, )",
"BitPay.Light": "[1.0.1907, )",
"Braintree": "[5.19.0, )",
"DnsClient": "[1.7.0, )",
"Fido2.AspNet": "[3.0.1, )",
"Handlebars.Net": "[2.1.2, )",
"IdentityServer4": "[4.1.2, )",
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
"LaunchDarkly.ServerSdk": "[7.0.0, )",
"MailKit": "[3.2.0, )",
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
"Microsoft.Azure.Cosmos.Table": "[1.0.8, )",
"Microsoft.Azure.NotificationHubs": "[4.1.0, )",
"Microsoft.Data.SqlClient": "[5.0.1, )",
"Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )",
"Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )",
"Microsoft.Extensions.Identity.Stores": "[6.0.4, )",
"Newtonsoft.Json": "[13.0.1, )",
"Otp.NET": "[1.2.2, )",
"Quartz": "[3.4.0, )",
"SendGrid": "[9.27.0, )",
"Sentry.Serilog": "[3.16.0, )",
"Serilog.AspNetCore": "[5.0.0, )",
"Serilog.Extensions.Logging": "[3.1.0, )",
"Serilog.Extensions.Logging.File": "[2.0.0, )",
"Serilog.Sinks.AzureCosmosDB": "[2.0.0, )",
"Serilog.Sinks.SyslogMessages": "[2.0.6, )",
"Stripe.net": "[40.0.0, )",
"YubicoDotNetClient": "[1.2.0, )"
}
},
"infrastructure.dapper": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Dapper": "2.0.123"
"Core": "[2023.9.0, )",
"Dapper": "[2.0.123, )"
}
},
"infrastructure.entityframework": {
"type": "Project",
"dependencies": {
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
"Core": "2023.7.2",
"Microsoft.EntityFrameworkCore.Relational": "7.0.5",
"Microsoft.EntityFrameworkCore.SqlServer": "7.0.5",
"Microsoft.EntityFrameworkCore.Sqlite": "7.0.5",
"Npgsql.EntityFrameworkCore.PostgreSQL": "7.0.4",
"Pomelo.EntityFrameworkCore.MySql": "7.0.0",
"linq2db.EntityFrameworkCore": "7.5.0"
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
"Core": "[2023.9.0, )",
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
"Npgsql.EntityFrameworkCore.PostgreSQL": "[7.0.4, )",
"Pomelo.EntityFrameworkCore.MySql": "[7.0.0, )",
"linq2db.EntityFrameworkCore": "[7.5.0, )"
}
},
"sharedweb": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Infrastructure.Dapper": "2023.7.2",
"Infrastructure.EntityFramework": "2023.7.2"
"Core": "[2023.9.0, )",
"Infrastructure.Dapper": "[2023.9.0, )",
"Infrastructure.EntityFramework": "[2023.9.0, )"
}
}
}

View File

@@ -28,10 +28,6 @@ public class WebAuthnTokenProvider : IUserTwoFactorTokenProvider<User>
public async Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<User> manager, User user)
{
var userService = _serviceProvider.GetRequiredService<IUserService>();
if (!(await userService.CanAccessPremium(user)))
{
return false;
}
var webAuthnProvider = user.GetTwoFactorProvider(TwoFactorProviderType.WebAuthn);
if (!HasProperMetaData(webAuthnProvider))
@@ -45,10 +41,6 @@ public class WebAuthnTokenProvider : IUserTwoFactorTokenProvider<User>
public async Task<string> GenerateAsync(string purpose, UserManager<User> manager, User user)
{
var userService = _serviceProvider.GetRequiredService<IUserService>();
if (!(await userService.CanAccessPremium(user)))
{
return null;
}
var provider = user.GetTwoFactorProvider(TwoFactorProviderType.WebAuthn);
var keys = LoadKeys(provider);
@@ -81,7 +73,7 @@ public class WebAuthnTokenProvider : IUserTwoFactorTokenProvider<User>
public async Task<bool> ValidateAsync(string purpose, string token, UserManager<User> manager, User user)
{
var userService = _serviceProvider.GetRequiredService<IUserService>();
if (!(await userService.CanAccessPremium(user)) || string.IsNullOrWhiteSpace(token))
if (string.IsNullOrWhiteSpace(token))
{
return false;
}

View File

@@ -6,11 +6,12 @@ namespace Bit.Core.Auth.Models.Business.Tokenables;
// This token just provides a verifiable authN mechanism for the API service
// TwoFactorController.cs SendEmailLogin anonymous endpoint so it cannot be
// used maliciously.
// used maliciously.
public class SsoEmail2faSessionTokenable : ExpiringTokenable
{
// Just over 2 min expiration (client expires session after 2 min)
private static readonly TimeSpan _tokenLifetime = TimeSpan.FromMinutes(2.05);
public static TimeSpan GetTokenLifetime() => TimeSpan.FromMinutes(2.05);
public const string ClearTextPrefix = "BwSsoEmail2FaSessionToken_";
public const string DataProtectorPurpose = "SsoEmail2faSessionTokenDataProtector";
@@ -24,7 +25,7 @@ public class SsoEmail2faSessionTokenable : ExpiringTokenable
[JsonConstructor]
public SsoEmail2faSessionTokenable()
{
ExpirationDate = DateTime.UtcNow.Add(_tokenLifetime);
ExpirationDate = DateTime.UtcNow.Add(GetTokenLifetime());
}
public SsoEmail2faSessionTokenable(User user) : this()
@@ -44,7 +45,7 @@ public class SsoEmail2faSessionTokenable : ExpiringTokenable
Email.Equals(user.Email, StringComparison.InvariantCultureIgnoreCase);
}
// Validates deserialized
// Validates deserialized
protected override bool TokenIsValid() =>
Identifier == TokenIdentifier && Id != default && !string.IsNullOrWhiteSpace(Email);
}

View File

@@ -57,7 +57,6 @@ public class TwoFactorProvider
case TwoFactorProviderType.Duo:
case TwoFactorProviderType.YubiKey:
case TwoFactorProviderType.U2f: // Keep to ensure old U2f keys are considered premium
case TwoFactorProviderType.WebAuthn:
return true;
default:
return false;

View File

@@ -82,34 +82,39 @@ public class AuthRequestService : IAuthRequestService
/// </remarks>
public async Task<AuthRequest> CreateAuthRequestAsync(AuthRequestCreateRequestModel model)
{
var user = await _userRepository.GetByEmailAsync(model.Email);
if (user == null)
{
throw new NotFoundException();
}
if (!_currentContext.DeviceType.HasValue)
{
throw new BadRequestException("Device type not provided.");
}
if (_globalSettings.PasswordlessAuth.KnownDevicesOnly)
var userNotFound = false;
var user = await _userRepository.GetByEmailAsync(model.Email);
if (user == null)
{
userNotFound = true;
}
else if (_globalSettings.PasswordlessAuth.KnownDevicesOnly)
{
var devices = await _deviceRepository.GetManyByUserIdAsync(user.Id);
if (devices == null || !devices.Any(d => d.Identifier == model.DeviceIdentifier))
{
throw new BadRequestException(
"Login with device is only available on devices that have been previously logged in.");
userNotFound = true;
}
}
// Anonymous endpoints must not leak that a user exists or not
if (userNotFound)
{
throw new BadRequestException("User or known device not found.");
}
// AdminApproval requests require correlating the user and their organization
if (model.Type == AuthRequestType.AdminApproval)
{
// TODO: When single org policy is turned on we should query for only a single organization from the current user
// and create only an AuthRequest for that organization and return only that one
// This will send out the request to all organizations this user belongs to
// This will send out the request to all organizations this user belongs to
var organizationUsers = await _organizationUserRepository.GetManyByUserAsync(_currentContext.UserId!.Value);
if (organizationUsers.Count == 0)
@@ -173,7 +178,7 @@ public class AuthRequestService : IAuthRequestService
switch (authRequest.Type)
{
case AuthRequestType.AdminApproval:
// AdminApproval has a different expiration time, by default is 7 days compared to
// AdminApproval has a different expiration time, by default is 7 days compared to
// non-AdminApproval ones having a default of 15 minutes.
if (IsDateExpired(authRequest.CreationDate, _globalSettings.PasswordlessAuth.AdminRequestExpiration))
{
@@ -213,7 +218,7 @@ public class AuthRequestService : IAuthRequestService
await _authRequestRepository.ReplaceAsync(authRequest);
// We only want to send an approval notification if the request is approved (or null),
// We only want to send an approval notification if the request is approved (or null),
// to not leak that it was denied to the originating client if it was originated by a malicious actor.
if (authRequest.Approved ?? true)
{

View File

@@ -36,7 +36,6 @@ public static class FeatureFlagKeys
public const string DisplayEuEnvironment = "display-eu-environment";
public const string DisplayLowKdfIterationWarning = "display-kdf-iteration-warning";
public const string TrustedDeviceEncryption = "trusted-device-encryption";
public const string SecretsManagerBilling = "sm-ga-billing";
public const string AutofillV2 = "autofill-v2";
public static List<string> GetAllKeys()
@@ -46,4 +45,13 @@ public static class FeatureFlagKeys
.Select(x => (string)x.GetRawConstantValue())
.ToList();
}
public static Dictionary<string, string> GetLocalOverrideFlagValues()
{
// place overriding values when needed locally (offline), or return null
return new Dictionary<string, string>()
{
{ TrustedDeviceEncryption, "true" }
};
}
}

View File

@@ -358,7 +358,9 @@ public class CurrentContext : ICurrentContext
public async Task<bool> ViewAssignedCollections(Guid orgId)
{
return await EditAssignedCollections(orgId) || await DeleteAssignedCollections(orgId);
return await CreateNewCollections(orgId) // Required to display the existing collections under which the new collection can be nested
|| await EditAssignedCollections(orgId)
|| await DeleteAssignedCollections(orgId);
}
public async Task<bool> ManageGroups(Guid orgId)

View File

@@ -51,7 +51,7 @@
<PackageReference Include="Serilog.Sinks.AzureCosmosDB" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.SyslogMessages" Version="2.0.6" />
<PackageReference Include="AspNetCoreRateLimit" Version="4.0.2" />
<PackageReference Include="Braintree" Version="5.12.0" />
<PackageReference Include="Braintree" Version="5.19.0" />
<PackageReference Include="Stripe.net" Version="40.0.0" />
<PackageReference Include="Otp.NET" Version="1.2.2" />
<PackageReference Include="YubicoDotNetClient" Version="1.2.0" />

View File

@@ -35,14 +35,23 @@ public class TaxInfo
return _taxIdType;
}
switch (BillingAddressCountry)
switch (BillingAddressCountry.ToUpper())
{
case "AD":
_taxIdType = "ad_nrt";
break;
case "AE":
_taxIdType = "ae_trn";
break;
case "AR":
_taxIdType = "ar_cuit";
break;
case "AU":
_taxIdType = "au_abn";
break;
case "BO":
_taxIdType = "bo_tin";
break;
case "BR":
_taxIdType = "br_cnpj";
break;
@@ -55,9 +64,45 @@ public class TaxInfo
}
_taxIdType = "ca_bn";
break;
case "CH":
_taxIdType = "ch_vat";
break;
case "CL":
_taxIdType = "cl_tin";
break;
case "CN":
_taxIdType = "cn_tin";
break;
case "CO":
_taxIdType = "co_nit";
break;
case "CR":
_taxIdType = "cr_tin";
break;
case "DO":
_taxIdType = "do_rcn";
break;
case "EC":
_taxIdType = "ec_ruc";
break;
case "EG":
_taxIdType = "eg_tin";
break;
case "GE":
_taxIdType = "ge_vat";
break;
case "ID":
_taxIdType = "id_npwp";
break;
case "IL":
_taxIdType = "il_vat";
break;
case "IS":
_taxIdType = "is_vat";
break;
case "KE":
_taxIdType = "ke_pin";
break;
case "AT":
case "BE":
case "BG":
@@ -115,6 +160,15 @@ public class TaxInfo
case "NZ":
_taxIdType = "nz_gst";
break;
case "PE":
_taxIdType = "pe_ruc";
break;
case "PH":
_taxIdType = "ph_tin";
break;
case "RS":
_taxIdType = "rs_pib";
break;
case "RU":
_taxIdType = "ru_inn";
break;
@@ -124,15 +178,33 @@ public class TaxInfo
case "SG":
_taxIdType = "sg_gst";
break;
case "SV":
_taxIdType = "sv_nit";
break;
case "TH":
_taxIdType = "th_vat";
break;
case "TR":
_taxIdType = "tr_tin";
break;
case "TW":
_taxIdType = "tw_vat";
break;
case "UA":
_taxIdType = "ua_vat";
break;
case "US":
_taxIdType = "us_ein";
break;
case "UY":
_taxIdType = "uy_ruc";
break;
case "VE":
_taxIdType = "ve_rif";
break;
case "VN":
_taxIdType = "vn_tin";
break;
case "ZA":
_taxIdType = "za_vat";
break;

View File

@@ -45,6 +45,7 @@ public static class OrganizationServiceCollectionExtensions
services.AddOrganizationLicenseCommandsQueries();
services.AddOrganizationDomainCommandsQueries();
services.AddOrganizationAuthCommands();
services.AddOrganizationUserCommands();
services.AddOrganizationUserCommandsQueries();
services.AddBaseOrganizationSubscriptionCommandsQueries();
}
@@ -81,6 +82,12 @@ public static class OrganizationServiceCollectionExtensions
}
}
private static void AddOrganizationUserCommands(this IServiceCollection services)
{
services.AddScoped<IDeleteOrganizationUserCommand, DeleteOrganizationUserCommand>();
services.AddScoped<IUpdateOrganizationUserGroupsCommand, UpdateOrganizationUserGroupsCommand>();
}
private static void AddOrganizationApiKeyCommandsQueries(this IServiceCollection services)
{
services.AddScoped<IGetOrganizationApiKeyQuery, GetOrganizationApiKeyQuery>();

View File

@@ -0,0 +1,8 @@
using Bit.Core.Entities;
namespace Bit.Core.OrganizationFeatures.OrganizationUsers.Interfaces;
public interface IUpdateOrganizationUserGroupsCommand
{
Task UpdateUserGroupsAsync(OrganizationUser organizationUser, IEnumerable<Guid> groupIds, Guid? loggedInUserId);
}

View File

@@ -0,0 +1,34 @@
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.OrganizationFeatures.OrganizationUsers.Interfaces;
using Bit.Core.Repositories;
using Bit.Core.Services;
namespace Bit.Core.OrganizationFeatures.OrganizationUsers;
public class UpdateOrganizationUserGroupsCommand : IUpdateOrganizationUserGroupsCommand
{
private readonly IEventService _eventService;
private readonly IOrganizationService _organizationService;
private readonly IOrganizationUserRepository _organizationUserRepository;
public UpdateOrganizationUserGroupsCommand(
IEventService eventService,
IOrganizationService organizationService,
IOrganizationUserRepository organizationUserRepository)
{
_eventService = eventService;
_organizationService = organizationService;
_organizationUserRepository = organizationUserRepository;
}
public async Task UpdateUserGroupsAsync(OrganizationUser organizationUser, IEnumerable<Guid> groupIds, Guid? loggedInUserId)
{
if (loggedInUserId.HasValue)
{
await _organizationService.ValidateOrganizationUserUpdatePermissions(organizationUser.OrganizationId, organizationUser.Type, null, organizationUser.GetPermissions());
}
await _organizationUserRepository.UpdateGroupsAsync(organizationUser.Id, groupIds);
await _eventService.LogOrganizationUserEventAsync(organizationUser, EventType.OrganizationUser_UpdatedGroups);
}
}

View File

@@ -2,5 +2,5 @@
public interface IMaxProjectsQuery
{
Task<(short? max, bool? atMax)> GetByOrgIdAsync(Guid organizationId);
Task<(short? max, bool? overMax)> GetByOrgIdAsync(Guid organizationId, int projectsToAdd);
}

View File

@@ -39,6 +39,12 @@ public interface IOrganizationService
OrganizationUserType type, bool accessAll, string externalId, IEnumerable<CollectionAccessSelection> collections, IEnumerable<Guid> groups);
Task<IEnumerable<Tuple<OrganizationUser, string>>> ResendInvitesAsync(Guid organizationId, Guid? invitingUserId, IEnumerable<Guid> organizationUsersId);
Task ResendInviteAsync(Guid organizationId, Guid? invitingUserId, Guid organizationUserId, bool initOrganization = false);
/// <summary>
/// Moves an OrganizationUser into the Accepted status and marks their email as verified.
/// This method is used where the user has clicked the invitation link sent by email.
/// </summary>
/// <param name="token">The token embedded in the email invitation link</param>
/// <returns>The accepted OrganizationUser.</returns>
Task<OrganizationUser> AcceptUserAsync(Guid organizationUserId, User user, string token, IUserService userService);
Task<OrganizationUser> AcceptUserAsync(string orgIdentifier, User user, IUserService userService);
Task<OrganizationUser> AcceptUserAsync(Guid organizationId, User user, IUserService userService);
@@ -54,7 +60,6 @@ public interface IOrganizationService
Task DeleteUserAsync(Guid organizationId, Guid userId);
Task<List<Tuple<OrganizationUser, string>>> DeleteUsersAsync(Guid organizationId,
IEnumerable<Guid> organizationUserIds, Guid? deletingUserId);
Task UpdateUserGroupsAsync(OrganizationUser organizationUser, IEnumerable<Guid> groupIds, Guid? loggedInUserId);
Task UpdateUserResetPasswordEnrollmentAsync(Guid organizationId, Guid userId, string resetPasswordKey, Guid? callingUserId);
Task ImportAsync(Guid organizationId, Guid? importingUserId, IEnumerable<ImportedGroup> groups,
IEnumerable<ImportedOrganizationUser> newUsers, IEnumerable<string> removeUserExternalIds,
@@ -82,4 +87,6 @@ public interface IOrganizationService
void ValidatePasswordManagerPlan(Models.StaticStore.Plan plan, OrganizationUpgrade upgrade);
void ValidateSecretsManagerPlan(Models.StaticStore.Plan plan, OrganizationUpgrade upgrade);
Task ValidateOrganizationUserUpdatePermissions(Guid organizationId, OrganizationUserType newType,
OrganizationUserType? oldType, Permissions permissions);
}

View File

@@ -29,24 +29,12 @@ public class LaunchDarklyFeatureService : IFeatureService, IDisposable
// support configuration directly from settings
else if (globalSettings.LaunchDarkly?.FlagValues?.Any() is true)
{
var source = TestData.DataSource();
foreach (var kvp in globalSettings.LaunchDarkly.FlagValues)
{
if (bool.TryParse(kvp.Value, out bool boolValue))
{
source.Update(source.Flag(kvp.Key).ValueForAll(LaunchDarkly.Sdk.LdValue.Of(boolValue)));
}
else if (int.TryParse(kvp.Value, out int intValue))
{
source.Update(source.Flag(kvp.Key).ValueForAll(LaunchDarkly.Sdk.LdValue.Of(intValue)));
}
else
{
source.Update(source.Flag(kvp.Key).ValueForAll(LaunchDarkly.Sdk.LdValue.Of(kvp.Value)));
}
}
ldConfig.DataSource(source);
ldConfig.DataSource(BuildDataSource(globalSettings.LaunchDarkly.FlagValues));
}
// support local overrides
else if (FeatureFlagKeys.GetLocalOverrideFlagValues()?.Any() is true)
{
ldConfig.DataSource(BuildDataSource(FeatureFlagKeys.GetLocalOverrideFlagValues()));
}
else
{
@@ -187,4 +175,26 @@ public class LaunchDarklyFeatureService : IFeatureService, IDisposable
return builder.Build();
}
private TestData BuildDataSource(Dictionary<string, string> values)
{
var source = TestData.DataSource();
foreach (var kvp in values)
{
if (bool.TryParse(kvp.Value, out bool boolValue))
{
source.Update(source.Flag(kvp.Key).ValueForAll(LaunchDarkly.Sdk.LdValue.Of(boolValue)));
}
else if (int.TryParse(kvp.Value, out int intValue))
{
source.Update(source.Flag(kvp.Key).ValueForAll(LaunchDarkly.Sdk.LdValue.Of(intValue)));
}
else
{
source.Update(source.Flag(kvp.Key).ValueForAll(LaunchDarkly.Sdk.LdValue.Of(kvp.Value)));
}
}
return source;
}
}

View File

@@ -1098,7 +1098,15 @@ public class OrganizationService : IOrganizationService
throw new BadRequestException("User email does not match invite.");
}
return await AcceptUserAsync(orgUser, user, userService);
var organizationUser = await AcceptUserAsync(orgUser, user, userService);
if (user.EmailVerified == false)
{
user.EmailVerified = true;
await _userRepository.ReplaceAsync(user);
}
return organizationUser;
}
public async Task<OrganizationUser> AcceptUserAsync(string orgIdentifier, User user, IUserService userService)
@@ -1587,17 +1595,6 @@ public class OrganizationService : IOrganizationService
return hasOtherOwner;
}
public async Task UpdateUserGroupsAsync(OrganizationUser organizationUser, IEnumerable<Guid> groupIds, Guid? loggedInUserId)
{
if (loggedInUserId.HasValue)
{
await ValidateOrganizationUserUpdatePermissions(organizationUser.OrganizationId, organizationUser.Type, null, organizationUser.GetPermissions());
}
await _organizationUserRepository.UpdateGroupsAsync(organizationUser.Id, groupIds);
await _eventService.LogOrganizationUserEventAsync(organizationUser,
EventType.OrganizationUser_UpdatedGroups);
}
public async Task UpdateUserResetPasswordEnrollmentAsync(Guid organizationId, Guid userId, string resetPasswordKey, Guid? callingUserId)
{
// Org User must be the same as the calling user and the organization ID associated with the user must match passed org ID
@@ -2037,7 +2034,7 @@ public class OrganizationService : IOrganizationService
}
}
private async Task ValidateOrganizationUserUpdatePermissions(Guid organizationId, OrganizationUserType newType, OrganizationUserType? oldType, Permissions permissions)
public async Task ValidateOrganizationUserUpdatePermissions(Guid organizationId, OrganizationUserType newType, OrganizationUserType? oldType, Permissions permissions)
{
if (await _currentContext.OrganizationOwner(organizationId))
{

View File

@@ -98,11 +98,12 @@
},
"Braintree": {
"type": "Direct",
"requested": "[5.12.0, )",
"resolved": "5.12.0",
"contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==",
"requested": "[5.19.0, )",
"resolved": "5.19.0",
"contentHash": "B60wIX54g78nMsy5cJkvSfqs1VasYDXWFZQW0cUQ4QeW8Y5jPyBSaoxHwKC806lXUDaKC8kr5Y7Q6EdsBkPANQ==",
"dependencies": {
"Newtonsoft.Json": "9.0.1",
"Microsoft.CSharp": "4.7.0",
"Newtonsoft.Json": "13.0.1",
"System.Xml.XPath.XmlDocument": "4.3.0"
}
},

View File

@@ -158,10 +158,11 @@
},
"Braintree": {
"type": "Transitive",
"resolved": "5.12.0",
"contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==",
"resolved": "5.19.0",
"contentHash": "B60wIX54g78nMsy5cJkvSfqs1VasYDXWFZQW0cUQ4QeW8Y5jPyBSaoxHwKC806lXUDaKC8kr5Y7Q6EdsBkPANQ==",
"dependencies": {
"Newtonsoft.Json": "9.0.1",
"Microsoft.CSharp": "4.7.0",
"Newtonsoft.Json": "13.0.1",
"System.Xml.XPath.XmlDocument": "4.3.0"
}
},
@@ -2588,71 +2589,71 @@
"core": {
"type": "Project",
"dependencies": {
"AWSSDK.SQS": "3.7.2.47",
"AWSSDK.SimpleEmail": "3.7.0.150",
"AspNetCoreRateLimit": "4.0.2",
"AspNetCoreRateLimit.Redis": "1.0.1",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "1.3.2",
"Azure.Messaging.ServiceBus": "7.15.0",
"Azure.Storage.Blobs": "12.14.1",
"Azure.Storage.Queues": "12.12.0",
"BitPay.Light": "1.0.1907",
"Braintree": "5.12.0",
"DnsClient": "1.7.0",
"Fido2.AspNet": "3.0.1",
"Handlebars.Net": "2.1.2",
"IdentityServer4": "4.1.2",
"IdentityServer4.AccessTokenValidation": "3.0.1",
"LaunchDarkly.ServerSdk": "7.0.0",
"MailKit": "3.2.0",
"Microsoft.AspNetCore.Authentication.JwtBearer": "6.0.4",
"Microsoft.Azure.Cosmos.Table": "1.0.8",
"Microsoft.Azure.NotificationHubs": "4.1.0",
"Microsoft.Data.SqlClient": "5.0.1",
"Microsoft.Extensions.Caching.StackExchangeRedis": "6.0.6",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1",
"Microsoft.Extensions.Configuration.UserSecrets": "6.0.1",
"Microsoft.Extensions.Identity.Stores": "6.0.4",
"Newtonsoft.Json": "13.0.1",
"Otp.NET": "1.2.2",
"Quartz": "3.4.0",
"SendGrid": "9.27.0",
"Sentry.Serilog": "3.16.0",
"Serilog.AspNetCore": "5.0.0",
"Serilog.Extensions.Logging": "3.1.0",
"Serilog.Extensions.Logging.File": "2.0.0",
"Serilog.Sinks.AzureCosmosDB": "2.0.0",
"Serilog.Sinks.SyslogMessages": "2.0.6",
"Stripe.net": "40.0.0",
"YubicoDotNetClient": "1.2.0"
"AWSSDK.SQS": "[3.7.2.47, )",
"AWSSDK.SimpleEmail": "[3.7.0.150, )",
"AspNetCoreRateLimit": "[4.0.2, )",
"AspNetCoreRateLimit.Redis": "[1.0.1, )",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.3.2, )",
"Azure.Messaging.ServiceBus": "[7.15.0, )",
"Azure.Storage.Blobs": "[12.14.1, )",
"Azure.Storage.Queues": "[12.12.0, )",
"BitPay.Light": "[1.0.1907, )",
"Braintree": "[5.19.0, )",
"DnsClient": "[1.7.0, )",
"Fido2.AspNet": "[3.0.1, )",
"Handlebars.Net": "[2.1.2, )",
"IdentityServer4": "[4.1.2, )",
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
"LaunchDarkly.ServerSdk": "[7.0.0, )",
"MailKit": "[3.2.0, )",
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
"Microsoft.Azure.Cosmos.Table": "[1.0.8, )",
"Microsoft.Azure.NotificationHubs": "[4.1.0, )",
"Microsoft.Data.SqlClient": "[5.0.1, )",
"Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )",
"Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )",
"Microsoft.Extensions.Identity.Stores": "[6.0.4, )",
"Newtonsoft.Json": "[13.0.1, )",
"Otp.NET": "[1.2.2, )",
"Quartz": "[3.4.0, )",
"SendGrid": "[9.27.0, )",
"Sentry.Serilog": "[3.16.0, )",
"Serilog.AspNetCore": "[5.0.0, )",
"Serilog.Extensions.Logging": "[3.1.0, )",
"Serilog.Extensions.Logging.File": "[2.0.0, )",
"Serilog.Sinks.AzureCosmosDB": "[2.0.0, )",
"Serilog.Sinks.SyslogMessages": "[2.0.6, )",
"Stripe.net": "[40.0.0, )",
"YubicoDotNetClient": "[1.2.0, )"
}
},
"infrastructure.dapper": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Dapper": "2.0.123"
"Core": "[2023.9.0, )",
"Dapper": "[2.0.123, )"
}
},
"infrastructure.entityframework": {
"type": "Project",
"dependencies": {
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
"Core": "2023.7.2",
"Microsoft.EntityFrameworkCore.Relational": "7.0.5",
"Microsoft.EntityFrameworkCore.SqlServer": "7.0.5",
"Microsoft.EntityFrameworkCore.Sqlite": "7.0.5",
"Npgsql.EntityFrameworkCore.PostgreSQL": "7.0.4",
"Pomelo.EntityFrameworkCore.MySql": "7.0.0",
"linq2db.EntityFrameworkCore": "7.5.0"
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
"Core": "[2023.9.0, )",
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
"Npgsql.EntityFrameworkCore.PostgreSQL": "[7.0.4, )",
"Pomelo.EntityFrameworkCore.MySql": "[7.0.0, )",
"linq2db.EntityFrameworkCore": "[7.5.0, )"
}
},
"sharedweb": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Infrastructure.Dapper": "2023.7.2",
"Infrastructure.EntityFramework": "2023.7.2"
"Core": "[2023.9.0, )",
"Infrastructure.Dapper": "[2023.9.0, )",
"Infrastructure.EntityFramework": "[2023.9.0, )"
}
}
}

View File

@@ -158,10 +158,11 @@
},
"Braintree": {
"type": "Transitive",
"resolved": "5.12.0",
"contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==",
"resolved": "5.19.0",
"contentHash": "B60wIX54g78nMsy5cJkvSfqs1VasYDXWFZQW0cUQ4QeW8Y5jPyBSaoxHwKC806lXUDaKC8kr5Y7Q6EdsBkPANQ==",
"dependencies": {
"Newtonsoft.Json": "9.0.1",
"Microsoft.CSharp": "4.7.0",
"Newtonsoft.Json": "13.0.1",
"System.Xml.XPath.XmlDocument": "4.3.0"
}
},
@@ -2588,71 +2589,71 @@
"core": {
"type": "Project",
"dependencies": {
"AWSSDK.SQS": "3.7.2.47",
"AWSSDK.SimpleEmail": "3.7.0.150",
"AspNetCoreRateLimit": "4.0.2",
"AspNetCoreRateLimit.Redis": "1.0.1",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "1.3.2",
"Azure.Messaging.ServiceBus": "7.15.0",
"Azure.Storage.Blobs": "12.14.1",
"Azure.Storage.Queues": "12.12.0",
"BitPay.Light": "1.0.1907",
"Braintree": "5.12.0",
"DnsClient": "1.7.0",
"Fido2.AspNet": "3.0.1",
"Handlebars.Net": "2.1.2",
"IdentityServer4": "4.1.2",
"IdentityServer4.AccessTokenValidation": "3.0.1",
"LaunchDarkly.ServerSdk": "7.0.0",
"MailKit": "3.2.0",
"Microsoft.AspNetCore.Authentication.JwtBearer": "6.0.4",
"Microsoft.Azure.Cosmos.Table": "1.0.8",
"Microsoft.Azure.NotificationHubs": "4.1.0",
"Microsoft.Data.SqlClient": "5.0.1",
"Microsoft.Extensions.Caching.StackExchangeRedis": "6.0.6",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1",
"Microsoft.Extensions.Configuration.UserSecrets": "6.0.1",
"Microsoft.Extensions.Identity.Stores": "6.0.4",
"Newtonsoft.Json": "13.0.1",
"Otp.NET": "1.2.2",
"Quartz": "3.4.0",
"SendGrid": "9.27.0",
"Sentry.Serilog": "3.16.0",
"Serilog.AspNetCore": "5.0.0",
"Serilog.Extensions.Logging": "3.1.0",
"Serilog.Extensions.Logging.File": "2.0.0",
"Serilog.Sinks.AzureCosmosDB": "2.0.0",
"Serilog.Sinks.SyslogMessages": "2.0.6",
"Stripe.net": "40.0.0",
"YubicoDotNetClient": "1.2.0"
"AWSSDK.SQS": "[3.7.2.47, )",
"AWSSDK.SimpleEmail": "[3.7.0.150, )",
"AspNetCoreRateLimit": "[4.0.2, )",
"AspNetCoreRateLimit.Redis": "[1.0.1, )",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.3.2, )",
"Azure.Messaging.ServiceBus": "[7.15.0, )",
"Azure.Storage.Blobs": "[12.14.1, )",
"Azure.Storage.Queues": "[12.12.0, )",
"BitPay.Light": "[1.0.1907, )",
"Braintree": "[5.19.0, )",
"DnsClient": "[1.7.0, )",
"Fido2.AspNet": "[3.0.1, )",
"Handlebars.Net": "[2.1.2, )",
"IdentityServer4": "[4.1.2, )",
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
"LaunchDarkly.ServerSdk": "[7.0.0, )",
"MailKit": "[3.2.0, )",
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
"Microsoft.Azure.Cosmos.Table": "[1.0.8, )",
"Microsoft.Azure.NotificationHubs": "[4.1.0, )",
"Microsoft.Data.SqlClient": "[5.0.1, )",
"Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )",
"Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )",
"Microsoft.Extensions.Identity.Stores": "[6.0.4, )",
"Newtonsoft.Json": "[13.0.1, )",
"Otp.NET": "[1.2.2, )",
"Quartz": "[3.4.0, )",
"SendGrid": "[9.27.0, )",
"Sentry.Serilog": "[3.16.0, )",
"Serilog.AspNetCore": "[5.0.0, )",
"Serilog.Extensions.Logging": "[3.1.0, )",
"Serilog.Extensions.Logging.File": "[2.0.0, )",
"Serilog.Sinks.AzureCosmosDB": "[2.0.0, )",
"Serilog.Sinks.SyslogMessages": "[2.0.6, )",
"Stripe.net": "[40.0.0, )",
"YubicoDotNetClient": "[1.2.0, )"
}
},
"infrastructure.dapper": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Dapper": "2.0.123"
"Core": "[2023.9.0, )",
"Dapper": "[2.0.123, )"
}
},
"infrastructure.entityframework": {
"type": "Project",
"dependencies": {
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
"Core": "2023.7.2",
"Microsoft.EntityFrameworkCore.Relational": "7.0.5",
"Microsoft.EntityFrameworkCore.SqlServer": "7.0.5",
"Microsoft.EntityFrameworkCore.Sqlite": "7.0.5",
"Npgsql.EntityFrameworkCore.PostgreSQL": "7.0.4",
"Pomelo.EntityFrameworkCore.MySql": "7.0.0",
"linq2db.EntityFrameworkCore": "7.5.0"
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
"Core": "[2023.9.0, )",
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
"Npgsql.EntityFrameworkCore.PostgreSQL": "[7.0.4, )",
"Pomelo.EntityFrameworkCore.MySql": "[7.0.0, )",
"linq2db.EntityFrameworkCore": "[7.5.0, )"
}
},
"sharedweb": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Infrastructure.Dapper": "2023.7.2",
"Infrastructure.EntityFramework": "2023.7.2"
"Core": "[2023.9.0, )",
"Infrastructure.Dapper": "[2023.9.0, )",
"Infrastructure.EntityFramework": "[2023.9.0, )"
}
}
}

View File

@@ -167,10 +167,11 @@
},
"Braintree": {
"type": "Transitive",
"resolved": "5.12.0",
"contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==",
"resolved": "5.19.0",
"contentHash": "B60wIX54g78nMsy5cJkvSfqs1VasYDXWFZQW0cUQ4QeW8Y5jPyBSaoxHwKC806lXUDaKC8kr5Y7Q6EdsBkPANQ==",
"dependencies": {
"Newtonsoft.Json": "9.0.1",
"Microsoft.CSharp": "4.7.0",
"Newtonsoft.Json": "13.0.1",
"System.Xml.XPath.XmlDocument": "4.3.0"
}
},
@@ -2597,71 +2598,71 @@
"core": {
"type": "Project",
"dependencies": {
"AWSSDK.SQS": "3.7.2.47",
"AWSSDK.SimpleEmail": "3.7.0.150",
"AspNetCoreRateLimit": "4.0.2",
"AspNetCoreRateLimit.Redis": "1.0.1",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "1.3.2",
"Azure.Messaging.ServiceBus": "7.15.0",
"Azure.Storage.Blobs": "12.14.1",
"Azure.Storage.Queues": "12.12.0",
"BitPay.Light": "1.0.1907",
"Braintree": "5.12.0",
"DnsClient": "1.7.0",
"Fido2.AspNet": "3.0.1",
"Handlebars.Net": "2.1.2",
"IdentityServer4": "4.1.2",
"IdentityServer4.AccessTokenValidation": "3.0.1",
"LaunchDarkly.ServerSdk": "7.0.0",
"MailKit": "3.2.0",
"Microsoft.AspNetCore.Authentication.JwtBearer": "6.0.4",
"Microsoft.Azure.Cosmos.Table": "1.0.8",
"Microsoft.Azure.NotificationHubs": "4.1.0",
"Microsoft.Data.SqlClient": "5.0.1",
"Microsoft.Extensions.Caching.StackExchangeRedis": "6.0.6",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1",
"Microsoft.Extensions.Configuration.UserSecrets": "6.0.1",
"Microsoft.Extensions.Identity.Stores": "6.0.4",
"Newtonsoft.Json": "13.0.1",
"Otp.NET": "1.2.2",
"Quartz": "3.4.0",
"SendGrid": "9.27.0",
"Sentry.Serilog": "3.16.0",
"Serilog.AspNetCore": "5.0.0",
"Serilog.Extensions.Logging": "3.1.0",
"Serilog.Extensions.Logging.File": "2.0.0",
"Serilog.Sinks.AzureCosmosDB": "2.0.0",
"Serilog.Sinks.SyslogMessages": "2.0.6",
"Stripe.net": "40.0.0",
"YubicoDotNetClient": "1.2.0"
"AWSSDK.SQS": "[3.7.2.47, )",
"AWSSDK.SimpleEmail": "[3.7.0.150, )",
"AspNetCoreRateLimit": "[4.0.2, )",
"AspNetCoreRateLimit.Redis": "[1.0.1, )",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.3.2, )",
"Azure.Messaging.ServiceBus": "[7.15.0, )",
"Azure.Storage.Blobs": "[12.14.1, )",
"Azure.Storage.Queues": "[12.12.0, )",
"BitPay.Light": "[1.0.1907, )",
"Braintree": "[5.19.0, )",
"DnsClient": "[1.7.0, )",
"Fido2.AspNet": "[3.0.1, )",
"Handlebars.Net": "[2.1.2, )",
"IdentityServer4": "[4.1.2, )",
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
"LaunchDarkly.ServerSdk": "[7.0.0, )",
"MailKit": "[3.2.0, )",
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
"Microsoft.Azure.Cosmos.Table": "[1.0.8, )",
"Microsoft.Azure.NotificationHubs": "[4.1.0, )",
"Microsoft.Data.SqlClient": "[5.0.1, )",
"Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )",
"Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )",
"Microsoft.Extensions.Identity.Stores": "[6.0.4, )",
"Newtonsoft.Json": "[13.0.1, )",
"Otp.NET": "[1.2.2, )",
"Quartz": "[3.4.0, )",
"SendGrid": "[9.27.0, )",
"Sentry.Serilog": "[3.16.0, )",
"Serilog.AspNetCore": "[5.0.0, )",
"Serilog.Extensions.Logging": "[3.1.0, )",
"Serilog.Extensions.Logging.File": "[2.0.0, )",
"Serilog.Sinks.AzureCosmosDB": "[2.0.0, )",
"Serilog.Sinks.SyslogMessages": "[2.0.6, )",
"Stripe.net": "[40.0.0, )",
"YubicoDotNetClient": "[1.2.0, )"
}
},
"infrastructure.dapper": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Dapper": "2.0.123"
"Core": "[2023.9.0, )",
"Dapper": "[2.0.123, )"
}
},
"infrastructure.entityframework": {
"type": "Project",
"dependencies": {
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
"Core": "2023.7.2",
"Microsoft.EntityFrameworkCore.Relational": "7.0.5",
"Microsoft.EntityFrameworkCore.SqlServer": "7.0.5",
"Microsoft.EntityFrameworkCore.Sqlite": "7.0.5",
"Npgsql.EntityFrameworkCore.PostgreSQL": "7.0.4",
"Pomelo.EntityFrameworkCore.MySql": "7.0.0",
"linq2db.EntityFrameworkCore": "7.5.0"
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
"Core": "[2023.9.0, )",
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
"Npgsql.EntityFrameworkCore.PostgreSQL": "[7.0.4, )",
"Pomelo.EntityFrameworkCore.MySql": "[7.0.0, )",
"linq2db.EntityFrameworkCore": "[7.5.0, )"
}
},
"sharedweb": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Infrastructure.Dapper": "2023.7.2",
"Infrastructure.EntityFramework": "2023.7.2"
"Core": "[2023.9.0, )",
"Infrastructure.Dapper": "[2023.9.0, )",
"Infrastructure.EntityFramework": "[2023.9.0, )"
}
}
}

View File

@@ -26,6 +26,7 @@ using Bit.Core.Utilities;
using Bit.Identity.Utilities;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Caching.Distributed;
namespace Bit.Identity.IdentityServer;
@@ -45,6 +46,8 @@ public abstract class BaseRequestValidator<T> where T : class
private readonly GlobalSettings _globalSettings;
private readonly IUserRepository _userRepository;
private readonly IDataProtectorTokenFactory<SsoEmail2faSessionTokenable> _tokenDataFactory;
private readonly IDistributedCache _distributedCache;
private readonly DistributedCacheEntryOptions _cacheEntryOptions;
protected ICurrentContext CurrentContext { get; }
protected IPolicyService PolicyService { get; }
@@ -69,7 +72,8 @@ public abstract class BaseRequestValidator<T> where T : class
IPolicyService policyService,
IDataProtectorTokenFactory<SsoEmail2faSessionTokenable> tokenDataFactory,
IFeatureService featureService,
ISsoConfigRepository ssoConfigRepository)
ISsoConfigRepository ssoConfigRepository,
IDistributedCache distributedCache)
{
_userManager = userManager;
_deviceRepository = deviceRepository;
@@ -89,6 +93,14 @@ public abstract class BaseRequestValidator<T> where T : class
_tokenDataFactory = tokenDataFactory;
FeatureService = featureService;
SsoConfigRepository = ssoConfigRepository;
_distributedCache = distributedCache;
_cacheEntryOptions = new DistributedCacheEntryOptions
{
// This sets the time an item is cached to 15 minutes. This value is hard coded
// to 15 because to it covers all time-out windows for both Authenticators and
// Email TOTP.
AbsoluteExpirationRelativeToNow = new TimeSpan(0, 15, 0)
};
}
protected async Task ValidateAsync(T context, ValidatedTokenRequest request,
@@ -135,18 +147,26 @@ public abstract class BaseRequestValidator<T> where T : class
var verified = await VerifyTwoFactor(user, twoFactorOrganization,
twoFactorProviderType, twoFactorToken);
if ((!verified || isBot) && twoFactorProviderType != TwoFactorProviderType.Remember)
var cacheKey = "TOTP_" + user.Email + "_" + twoFactorToken;
var isOtpCached = Core.Utilities.DistributedCacheExtensions.TryGetValue(_distributedCache, cacheKey, out string _);
if (!verified || isBot || isOtpCached)
{
await UpdateFailedAuthDetailsAsync(user, true, !validatorContext.KnownDevice);
await BuildErrorResultAsync("Two-step token is invalid. Try again.", true, context, user);
if (twoFactorProviderType != TwoFactorProviderType.Remember)
{
await UpdateFailedAuthDetailsAsync(user, true, !validatorContext.KnownDevice);
await BuildErrorResultAsync("Two-step token is invalid. Try again.", true, context, user);
}
else if (twoFactorProviderType == TwoFactorProviderType.Remember)
{
await BuildTwoFactorResultAsync(user, twoFactorOrganization, context);
}
return;
}
else if ((!verified || isBot) && twoFactorProviderType == TwoFactorProviderType.Remember)
// We only want to track TOTPs in the chache to enforce one time use.
if (twoFactorProviderType == TwoFactorProviderType.Authenticator || twoFactorProviderType == TwoFactorProviderType.Email)
{
// Delay for brute force.
await Task.Delay(2000);
await BuildTwoFactorResultAsync(user, twoFactorOrganization, context);
return;
await Core.Utilities.DistributedCacheExtensions.SetAsync(_distributedCache, cacheKey, twoFactorToken, _cacheEntryOptions);
}
}
else

View File

@@ -14,6 +14,7 @@ using IdentityModel;
using IdentityServer4.Extensions;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Caching.Distributed;
#nullable enable
@@ -42,11 +43,13 @@ public class CustomTokenRequestValidator : BaseRequestValidator<CustomTokenReque
IUserRepository userRepository,
IPolicyService policyService,
IDataProtectorTokenFactory<SsoEmail2faSessionTokenable> tokenDataFactory,
IFeatureService featureService)
IFeatureService featureService,
IDistributedCache distributedCache)
: base(userManager, deviceRepository, deviceService, userService, eventService,
organizationDuoWebTokenProvider, organizationRepository, organizationUserRepository,
applicationCacheService, mailService, logger, currentContext, globalSettings,
userRepository, policyService, tokenDataFactory, featureService, ssoConfigRepository)
userRepository, policyService, tokenDataFactory, featureService, ssoConfigRepository,
distributedCache)
{
_userManager = userManager;
}

View File

@@ -13,6 +13,7 @@ using Bit.Core.Utilities;
using IdentityServer4.Models;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Caching.Distributed;
namespace Bit.Identity.IdentityServer;
@@ -44,11 +45,12 @@ public class ResourceOwnerPasswordValidator : BaseRequestValidator<ResourceOwner
IPolicyService policyService,
IDataProtectorTokenFactory<SsoEmail2faSessionTokenable> tokenDataFactory,
IFeatureService featureService,
ISsoConfigRepository ssoConfigRepository)
ISsoConfigRepository ssoConfigRepository,
IDistributedCache distributedCache)
: base(userManager, deviceRepository, deviceService, userService, eventService,
organizationDuoWebTokenProvider, organizationRepository, organizationUserRepository,
applicationCacheService, mailService, logger, currentContext, globalSettings, userRepository, policyService,
tokenDataFactory, featureService, ssoConfigRepository)
tokenDataFactory, featureService, ssoConfigRepository, distributedCache)
{
_userManager = userManager;
_userService = userService;

View File

@@ -167,10 +167,11 @@
},
"Braintree": {
"type": "Transitive",
"resolved": "5.12.0",
"contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==",
"resolved": "5.19.0",
"contentHash": "B60wIX54g78nMsy5cJkvSfqs1VasYDXWFZQW0cUQ4QeW8Y5jPyBSaoxHwKC806lXUDaKC8kr5Y7Q6EdsBkPANQ==",
"dependencies": {
"Newtonsoft.Json": "9.0.1",
"Microsoft.CSharp": "4.7.0",
"Newtonsoft.Json": "13.0.1",
"System.Xml.XPath.XmlDocument": "4.3.0"
}
},
@@ -2610,71 +2611,71 @@
"core": {
"type": "Project",
"dependencies": {
"AWSSDK.SQS": "3.7.2.47",
"AWSSDK.SimpleEmail": "3.7.0.150",
"AspNetCoreRateLimit": "4.0.2",
"AspNetCoreRateLimit.Redis": "1.0.1",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "1.3.2",
"Azure.Messaging.ServiceBus": "7.15.0",
"Azure.Storage.Blobs": "12.14.1",
"Azure.Storage.Queues": "12.12.0",
"BitPay.Light": "1.0.1907",
"Braintree": "5.12.0",
"DnsClient": "1.7.0",
"Fido2.AspNet": "3.0.1",
"Handlebars.Net": "2.1.2",
"IdentityServer4": "4.1.2",
"IdentityServer4.AccessTokenValidation": "3.0.1",
"LaunchDarkly.ServerSdk": "7.0.0",
"MailKit": "3.2.0",
"Microsoft.AspNetCore.Authentication.JwtBearer": "6.0.4",
"Microsoft.Azure.Cosmos.Table": "1.0.8",
"Microsoft.Azure.NotificationHubs": "4.1.0",
"Microsoft.Data.SqlClient": "5.0.1",
"Microsoft.Extensions.Caching.StackExchangeRedis": "6.0.6",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1",
"Microsoft.Extensions.Configuration.UserSecrets": "6.0.1",
"Microsoft.Extensions.Identity.Stores": "6.0.4",
"Newtonsoft.Json": "13.0.1",
"Otp.NET": "1.2.2",
"Quartz": "3.4.0",
"SendGrid": "9.27.0",
"Sentry.Serilog": "3.16.0",
"Serilog.AspNetCore": "5.0.0",
"Serilog.Extensions.Logging": "3.1.0",
"Serilog.Extensions.Logging.File": "2.0.0",
"Serilog.Sinks.AzureCosmosDB": "2.0.0",
"Serilog.Sinks.SyslogMessages": "2.0.6",
"Stripe.net": "40.0.0",
"YubicoDotNetClient": "1.2.0"
"AWSSDK.SQS": "[3.7.2.47, )",
"AWSSDK.SimpleEmail": "[3.7.0.150, )",
"AspNetCoreRateLimit": "[4.0.2, )",
"AspNetCoreRateLimit.Redis": "[1.0.1, )",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.3.2, )",
"Azure.Messaging.ServiceBus": "[7.15.0, )",
"Azure.Storage.Blobs": "[12.14.1, )",
"Azure.Storage.Queues": "[12.12.0, )",
"BitPay.Light": "[1.0.1907, )",
"Braintree": "[5.19.0, )",
"DnsClient": "[1.7.0, )",
"Fido2.AspNet": "[3.0.1, )",
"Handlebars.Net": "[2.1.2, )",
"IdentityServer4": "[4.1.2, )",
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
"LaunchDarkly.ServerSdk": "[7.0.0, )",
"MailKit": "[3.2.0, )",
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
"Microsoft.Azure.Cosmos.Table": "[1.0.8, )",
"Microsoft.Azure.NotificationHubs": "[4.1.0, )",
"Microsoft.Data.SqlClient": "[5.0.1, )",
"Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )",
"Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )",
"Microsoft.Extensions.Identity.Stores": "[6.0.4, )",
"Newtonsoft.Json": "[13.0.1, )",
"Otp.NET": "[1.2.2, )",
"Quartz": "[3.4.0, )",
"SendGrid": "[9.27.0, )",
"Sentry.Serilog": "[3.16.0, )",
"Serilog.AspNetCore": "[5.0.0, )",
"Serilog.Extensions.Logging": "[3.1.0, )",
"Serilog.Extensions.Logging.File": "[2.0.0, )",
"Serilog.Sinks.AzureCosmosDB": "[2.0.0, )",
"Serilog.Sinks.SyslogMessages": "[2.0.6, )",
"Stripe.net": "[40.0.0, )",
"YubicoDotNetClient": "[1.2.0, )"
}
},
"infrastructure.dapper": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Dapper": "2.0.123"
"Core": "[2023.9.0, )",
"Dapper": "[2.0.123, )"
}
},
"infrastructure.entityframework": {
"type": "Project",
"dependencies": {
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
"Core": "2023.7.2",
"Microsoft.EntityFrameworkCore.Relational": "7.0.5",
"Microsoft.EntityFrameworkCore.SqlServer": "7.0.5",
"Microsoft.EntityFrameworkCore.Sqlite": "7.0.5",
"Npgsql.EntityFrameworkCore.PostgreSQL": "7.0.4",
"Pomelo.EntityFrameworkCore.MySql": "7.0.0",
"linq2db.EntityFrameworkCore": "7.5.0"
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
"Core": "[2023.9.0, )",
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
"Npgsql.EntityFrameworkCore.PostgreSQL": "[7.0.4, )",
"Pomelo.EntityFrameworkCore.MySql": "[7.0.0, )",
"linq2db.EntityFrameworkCore": "[7.5.0, )"
}
},
"sharedweb": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Infrastructure.Dapper": "2023.7.2",
"Infrastructure.EntityFramework": "2023.7.2"
"Core": "[2023.9.0, )",
"Infrastructure.Dapper": "[2023.9.0, )",
"Infrastructure.EntityFramework": "[2023.9.0, )"
}
}
}

View File

@@ -147,10 +147,11 @@
},
"Braintree": {
"type": "Transitive",
"resolved": "5.12.0",
"contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==",
"resolved": "5.19.0",
"contentHash": "B60wIX54g78nMsy5cJkvSfqs1VasYDXWFZQW0cUQ4QeW8Y5jPyBSaoxHwKC806lXUDaKC8kr5Y7Q6EdsBkPANQ==",
"dependencies": {
"Newtonsoft.Json": "9.0.1",
"Microsoft.CSharp": "4.7.0",
"Newtonsoft.Json": "13.0.1",
"System.Xml.XPath.XmlDocument": "4.3.0"
}
},
@@ -2430,43 +2431,43 @@
"core": {
"type": "Project",
"dependencies": {
"AWSSDK.SQS": "3.7.2.47",
"AWSSDK.SimpleEmail": "3.7.0.150",
"AspNetCoreRateLimit": "4.0.2",
"AspNetCoreRateLimit.Redis": "1.0.1",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "1.3.2",
"Azure.Messaging.ServiceBus": "7.15.0",
"Azure.Storage.Blobs": "12.14.1",
"Azure.Storage.Queues": "12.12.0",
"BitPay.Light": "1.0.1907",
"Braintree": "5.12.0",
"DnsClient": "1.7.0",
"Fido2.AspNet": "3.0.1",
"Handlebars.Net": "2.1.2",
"IdentityServer4": "4.1.2",
"IdentityServer4.AccessTokenValidation": "3.0.1",
"LaunchDarkly.ServerSdk": "7.0.0",
"MailKit": "3.2.0",
"Microsoft.AspNetCore.Authentication.JwtBearer": "6.0.4",
"Microsoft.Azure.Cosmos.Table": "1.0.8",
"Microsoft.Azure.NotificationHubs": "4.1.0",
"Microsoft.Data.SqlClient": "5.0.1",
"Microsoft.Extensions.Caching.StackExchangeRedis": "6.0.6",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1",
"Microsoft.Extensions.Configuration.UserSecrets": "6.0.1",
"Microsoft.Extensions.Identity.Stores": "6.0.4",
"Newtonsoft.Json": "13.0.1",
"Otp.NET": "1.2.2",
"Quartz": "3.4.0",
"SendGrid": "9.27.0",
"Sentry.Serilog": "3.16.0",
"Serilog.AspNetCore": "5.0.0",
"Serilog.Extensions.Logging": "3.1.0",
"Serilog.Extensions.Logging.File": "2.0.0",
"Serilog.Sinks.AzureCosmosDB": "2.0.0",
"Serilog.Sinks.SyslogMessages": "2.0.6",
"Stripe.net": "40.0.0",
"YubicoDotNetClient": "1.2.0"
"AWSSDK.SQS": "[3.7.2.47, )",
"AWSSDK.SimpleEmail": "[3.7.0.150, )",
"AspNetCoreRateLimit": "[4.0.2, )",
"AspNetCoreRateLimit.Redis": "[1.0.1, )",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.3.2, )",
"Azure.Messaging.ServiceBus": "[7.15.0, )",
"Azure.Storage.Blobs": "[12.14.1, )",
"Azure.Storage.Queues": "[12.12.0, )",
"BitPay.Light": "[1.0.1907, )",
"Braintree": "[5.19.0, )",
"DnsClient": "[1.7.0, )",
"Fido2.AspNet": "[3.0.1, )",
"Handlebars.Net": "[2.1.2, )",
"IdentityServer4": "[4.1.2, )",
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
"LaunchDarkly.ServerSdk": "[7.0.0, )",
"MailKit": "[3.2.0, )",
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
"Microsoft.Azure.Cosmos.Table": "[1.0.8, )",
"Microsoft.Azure.NotificationHubs": "[4.1.0, )",
"Microsoft.Data.SqlClient": "[5.0.1, )",
"Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )",
"Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )",
"Microsoft.Extensions.Identity.Stores": "[6.0.4, )",
"Newtonsoft.Json": "[13.0.1, )",
"Otp.NET": "[1.2.2, )",
"Quartz": "[3.4.0, )",
"SendGrid": "[9.27.0, )",
"Sentry.Serilog": "[3.16.0, )",
"Serilog.AspNetCore": "[5.0.0, )",
"Serilog.Extensions.Logging": "[3.1.0, )",
"Serilog.Extensions.Logging.File": "[2.0.0, )",
"Serilog.Sinks.AzureCosmosDB": "[2.0.0, )",
"Serilog.Sinks.SyslogMessages": "[2.0.6, )",
"Stripe.net": "[40.0.0, )",
"YubicoDotNetClient": "[1.2.0, )"
}
}
}

View File

@@ -144,27 +144,42 @@ public class OrganizationRepository : Repository<Core.Entities.Organization, Org
var dbContext = GetDatabaseContext(scope);
await dbContext.UserBumpAccountRevisionDateByOrganizationIdAsync(organization.Id);
var deleteCiphersTransaction = await dbContext.Database.BeginTransactionAsync();
dbContext.Ciphers.RemoveRange(
dbContext.Ciphers.Where(c => c.UserId == null && c.OrganizationId == organization.Id));
await dbContext.Ciphers.Where(c => c.UserId == null && c.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await deleteCiphersTransaction.CommitAsync();
var organizationDeleteTransaction = await dbContext.Database.BeginTransactionAsync();
dbContext.SsoUsers.RemoveRange(dbContext.SsoUsers.Where(su => su.OrganizationId == organization.Id));
dbContext.SsoConfigs.RemoveRange(dbContext.SsoConfigs.Where(sc => sc.OrganizationId == organization.Id));
var collectionUsers = from cu in dbContext.CollectionUsers
join ou in dbContext.OrganizationUsers on cu.OrganizationUserId equals ou.Id
where ou.OrganizationId == organization.Id
select cu;
dbContext.CollectionUsers.RemoveRange(collectionUsers);
dbContext.OrganizationUsers.RemoveRange(
dbContext.OrganizationUsers.Where(ou => ou.OrganizationId == organization.Id));
dbContext.ProviderOrganizations.RemoveRange(
dbContext.ProviderOrganizations.Where(po => po.OrganizationId == organization.Id));
await dbContext.SsoUsers.Where(su => su.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.SsoConfigs.Where(sc => sc.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.CollectionUsers.Where(cu => cu.OrganizationUser.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.UserProjectAccessPolicy.Where(ap => ap.OrganizationUser.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.UserServiceAccountAccessPolicy.Where(ap => ap.OrganizationUser.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.OrganizationUsers.Where(ou => ou.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.ProviderOrganizations.Where(po => po.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.GroupServiceAccountAccessPolicy.Where(ap => ap.GrantedServiceAccount.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.Project.Where(p => p.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.Secret.Where(s => s.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.ApiKeys.Where(ak => ak.ServiceAccount.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.ServiceAccount.Where(sa => sa.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
// The below section are 3 SPROCS in SQL Server but are only called by here
dbContext.OrganizationApiKeys.RemoveRange(
dbContext.OrganizationApiKeys.Where(oa => oa.OrganizationId == organization.Id));
dbContext.OrganizationConnections.RemoveRange(
dbContext.OrganizationConnections.Where(oc => oc.OrganizationId == organization.Id));
await dbContext.OrganizationApiKeys.Where(oa => oa.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.OrganizationConnections.Where(oc => oc.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
var sponsoringOrgs = await dbContext.OrganizationSponsorships
.Where(os => os.SponsoringOrganizationId == organization.Id)
.ToListAsync();

View File

@@ -93,6 +93,11 @@ public class OrganizationUserRepository : Repository<Core.Entities.OrganizationU
.Where(gu => gu.OrganizationUserId == organizationUserId);
dbContext.GroupUsers.RemoveRange(groupUsers);
dbContext.UserProjectAccessPolicy.RemoveRange(
dbContext.UserProjectAccessPolicy.Where(ap => ap.OrganizationUserId == organizationUserId));
dbContext.UserServiceAccountAccessPolicy.RemoveRange(
dbContext.UserServiceAccountAccessPolicy.Where(ap => ap.OrganizationUserId == organizationUserId));
var orgSponsorships = await dbContext.OrganizationSponsorships
.Where(os => os.SponsoringOrganizationUserId == organizationUserId)
.ToListAsync();
@@ -325,7 +330,7 @@ public class OrganizationUserRepository : Repository<Core.Entities.OrganizationU
var userIds = users.Select(u => u.Id);
var userIdEntities = dbContext.OrganizationUsers.Where(x => userIds.Contains(x.Id));
// Query groups/collections separately to avoid cartesian explosion
// Query groups/collections separately to avoid cartesian explosion
if (includeGroups)
{
groups = (await (from gu in dbContext.GroupUsers

View File

@@ -167,6 +167,10 @@ public class UserRepository : Repository<Core.Entities.User, User, Guid>, IUserR
where ou.UserId == user.Id
select gu;
dbContext.GroupUsers.RemoveRange(groupUsers);
dbContext.UserProjectAccessPolicy.RemoveRange(
dbContext.UserProjectAccessPolicy.Where(ap => ap.OrganizationUser.UserId == user.Id));
dbContext.UserServiceAccountAccessPolicy.RemoveRange(
dbContext.UserServiceAccountAccessPolicy.Where(ap => ap.OrganizationUser.UserId == user.Id));
dbContext.OrganizationUsers.RemoveRange(dbContext.OrganizationUsers.Where(ou => ou.UserId == user.Id));
dbContext.ProviderUsers.RemoveRange(dbContext.ProviderUsers.Where(pu => pu.UserId == user.Id));
dbContext.SsoUsers.RemoveRange(dbContext.SsoUsers.Where(su => su.UserId == user.Id));

View File

@@ -39,6 +39,12 @@ public class UserProjectAccessPolicyEntityTypeConfiguration : IEntityTypeConfigu
builder
.Property(e => e.GrantedProjectId)
.HasColumnName(nameof(UserProjectAccessPolicy.GrantedProjectId));
builder
.HasOne(e => e.GrantedProject)
.WithMany(e => e.UserAccessPolicies)
.HasForeignKey(nameof(UserProjectAccessPolicy.GrantedProjectId))
.OnDelete(DeleteBehavior.Cascade);
}
}
@@ -67,6 +73,18 @@ public class GroupProjectAccessPolicyEntityTypeConfiguration : IEntityTypeConfig
builder
.Property(e => e.GrantedProjectId)
.HasColumnName(nameof(GroupProjectAccessPolicy.GrantedProjectId));
builder
.HasOne(e => e.GrantedProject)
.WithMany(e => e.GroupAccessPolicies)
.HasForeignKey(nameof(GroupProjectAccessPolicy.GrantedProjectId))
.OnDelete(DeleteBehavior.Cascade);
builder
.HasOne(e => e.Group)
.WithMany()
.HasForeignKey(nameof(GroupProjectAccessPolicy.GroupId))
.OnDelete(DeleteBehavior.Cascade);
}
}
@@ -81,6 +99,12 @@ public class GroupServiceAccountAccessPolicyEntityTypeConfiguration : IEntityTyp
builder
.Property(e => e.GrantedServiceAccountId)
.HasColumnName(nameof(GroupServiceAccountAccessPolicy.GrantedServiceAccountId));
builder
.HasOne(e => e.Group)
.WithMany()
.HasForeignKey(nameof(GroupProjectAccessPolicy.GroupId))
.OnDelete(DeleteBehavior.Cascade);
}
}
@@ -95,5 +119,11 @@ public class ServiceAccountProjectAccessPolicyEntityTypeConfiguration : IEntityT
builder
.Property(e => e.GrantedProjectId)
.HasColumnName(nameof(ServiceAccountProjectAccessPolicy.GrantedProjectId));
builder
.HasOne(e => e.GrantedProject)
.WithMany(e => e.ServiceAccountAccessPolicies)
.HasForeignKey(nameof(ServiceAccountProjectAccessPolicy.GrantedProjectId))
.OnDelete(DeleteBehavior.Cascade);
}
}

View File

@@ -221,10 +221,11 @@
},
"Braintree": {
"type": "Transitive",
"resolved": "5.12.0",
"contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==",
"resolved": "5.19.0",
"contentHash": "B60wIX54g78nMsy5cJkvSfqs1VasYDXWFZQW0cUQ4QeW8Y5jPyBSaoxHwKC806lXUDaKC8kr5Y7Q6EdsBkPANQ==",
"dependencies": {
"Newtonsoft.Json": "9.0.1",
"Microsoft.CSharp": "4.7.0",
"Newtonsoft.Json": "13.0.1",
"System.Xml.XPath.XmlDocument": "4.3.0"
}
},
@@ -2590,43 +2591,43 @@
"core": {
"type": "Project",
"dependencies": {
"AWSSDK.SQS": "3.7.2.47",
"AWSSDK.SimpleEmail": "3.7.0.150",
"AspNetCoreRateLimit": "4.0.2",
"AspNetCoreRateLimit.Redis": "1.0.1",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "1.3.2",
"Azure.Messaging.ServiceBus": "7.15.0",
"Azure.Storage.Blobs": "12.14.1",
"Azure.Storage.Queues": "12.12.0",
"BitPay.Light": "1.0.1907",
"Braintree": "5.12.0",
"DnsClient": "1.7.0",
"Fido2.AspNet": "3.0.1",
"Handlebars.Net": "2.1.2",
"IdentityServer4": "4.1.2",
"IdentityServer4.AccessTokenValidation": "3.0.1",
"LaunchDarkly.ServerSdk": "7.0.0",
"MailKit": "3.2.0",
"Microsoft.AspNetCore.Authentication.JwtBearer": "6.0.4",
"Microsoft.Azure.Cosmos.Table": "1.0.8",
"Microsoft.Azure.NotificationHubs": "4.1.0",
"Microsoft.Data.SqlClient": "5.0.1",
"Microsoft.Extensions.Caching.StackExchangeRedis": "6.0.6",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1",
"Microsoft.Extensions.Configuration.UserSecrets": "6.0.1",
"Microsoft.Extensions.Identity.Stores": "6.0.4",
"Newtonsoft.Json": "13.0.1",
"Otp.NET": "1.2.2",
"Quartz": "3.4.0",
"SendGrid": "9.27.0",
"Sentry.Serilog": "3.16.0",
"Serilog.AspNetCore": "5.0.0",
"Serilog.Extensions.Logging": "3.1.0",
"Serilog.Extensions.Logging.File": "2.0.0",
"Serilog.Sinks.AzureCosmosDB": "2.0.0",
"Serilog.Sinks.SyslogMessages": "2.0.6",
"Stripe.net": "40.0.0",
"YubicoDotNetClient": "1.2.0"
"AWSSDK.SQS": "[3.7.2.47, )",
"AWSSDK.SimpleEmail": "[3.7.0.150, )",
"AspNetCoreRateLimit": "[4.0.2, )",
"AspNetCoreRateLimit.Redis": "[1.0.1, )",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.3.2, )",
"Azure.Messaging.ServiceBus": "[7.15.0, )",
"Azure.Storage.Blobs": "[12.14.1, )",
"Azure.Storage.Queues": "[12.12.0, )",
"BitPay.Light": "[1.0.1907, )",
"Braintree": "[5.19.0, )",
"DnsClient": "[1.7.0, )",
"Fido2.AspNet": "[3.0.1, )",
"Handlebars.Net": "[2.1.2, )",
"IdentityServer4": "[4.1.2, )",
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
"LaunchDarkly.ServerSdk": "[7.0.0, )",
"MailKit": "[3.2.0, )",
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
"Microsoft.Azure.Cosmos.Table": "[1.0.8, )",
"Microsoft.Azure.NotificationHubs": "[4.1.0, )",
"Microsoft.Data.SqlClient": "[5.0.1, )",
"Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )",
"Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )",
"Microsoft.Extensions.Identity.Stores": "[6.0.4, )",
"Newtonsoft.Json": "[13.0.1, )",
"Otp.NET": "[1.2.2, )",
"Quartz": "[3.4.0, )",
"SendGrid": "[9.27.0, )",
"Sentry.Serilog": "[3.16.0, )",
"Serilog.AspNetCore": "[5.0.0, )",
"Serilog.Extensions.Logging": "[3.1.0, )",
"Serilog.Extensions.Logging.File": "[2.0.0, )",
"Serilog.Sinks.AzureCosmosDB": "[2.0.0, )",
"Serilog.Sinks.SyslogMessages": "[2.0.6, )",
"Stripe.net": "[40.0.0, )",
"YubicoDotNetClient": "[1.2.0, )"
}
}
}

View File

@@ -8,7 +8,7 @@
<PropertyGroup Condition=" '$(RunConfiguration)' == 'Notifications-SelfHost' " />
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="6.0.4" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="6.0.4" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="6.0.22" />
</ItemGroup>
<ItemGroup>

View File

@@ -14,9 +14,9 @@
},
"Microsoft.AspNetCore.SignalR.StackExchangeRedis": {
"type": "Direct",
"requested": "[6.0.4, )",
"resolved": "6.0.4",
"contentHash": "E3Ihoz4xXHVyqx4ZidQAEbWbjD0bEOTsnDMuz7FoFyev0fLJCHWOiR6Y9E+8Qb/dmUDrfaLdZzKUSwtlHPGGgA==",
"requested": "[6.0.22, )",
"resolved": "6.0.22",
"contentHash": "qcwxQNBUIuiVCA8pJTPoxFXQOum0R3+Lh7bfHOQxgpcP3wNQoSRK8yqEEiv0E15vMLiboh88+Ujnu2Wzq66onQ==",
"dependencies": {
"MessagePack": "2.1.90",
"Microsoft.Extensions.Options": "6.0.0",
@@ -179,10 +179,11 @@
},
"Braintree": {
"type": "Transitive",
"resolved": "5.12.0",
"contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==",
"resolved": "5.19.0",
"contentHash": "B60wIX54g78nMsy5cJkvSfqs1VasYDXWFZQW0cUQ4QeW8Y5jPyBSaoxHwKC806lXUDaKC8kr5Y7Q6EdsBkPANQ==",
"dependencies": {
"Newtonsoft.Json": "9.0.1",
"Microsoft.CSharp": "4.7.0",
"Newtonsoft.Json": "13.0.1",
"System.Xml.XPath.XmlDocument": "4.3.0"
}
},
@@ -2638,71 +2639,71 @@
"core": {
"type": "Project",
"dependencies": {
"AWSSDK.SQS": "3.7.2.47",
"AWSSDK.SimpleEmail": "3.7.0.150",
"AspNetCoreRateLimit": "4.0.2",
"AspNetCoreRateLimit.Redis": "1.0.1",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "1.3.2",
"Azure.Messaging.ServiceBus": "7.15.0",
"Azure.Storage.Blobs": "12.14.1",
"Azure.Storage.Queues": "12.12.0",
"BitPay.Light": "1.0.1907",
"Braintree": "5.12.0",
"DnsClient": "1.7.0",
"Fido2.AspNet": "3.0.1",
"Handlebars.Net": "2.1.2",
"IdentityServer4": "4.1.2",
"IdentityServer4.AccessTokenValidation": "3.0.1",
"LaunchDarkly.ServerSdk": "7.0.0",
"MailKit": "3.2.0",
"Microsoft.AspNetCore.Authentication.JwtBearer": "6.0.4",
"Microsoft.Azure.Cosmos.Table": "1.0.8",
"Microsoft.Azure.NotificationHubs": "4.1.0",
"Microsoft.Data.SqlClient": "5.0.1",
"Microsoft.Extensions.Caching.StackExchangeRedis": "6.0.6",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1",
"Microsoft.Extensions.Configuration.UserSecrets": "6.0.1",
"Microsoft.Extensions.Identity.Stores": "6.0.4",
"Newtonsoft.Json": "13.0.1",
"Otp.NET": "1.2.2",
"Quartz": "3.4.0",
"SendGrid": "9.27.0",
"Sentry.Serilog": "3.16.0",
"Serilog.AspNetCore": "5.0.0",
"Serilog.Extensions.Logging": "3.1.0",
"Serilog.Extensions.Logging.File": "2.0.0",
"Serilog.Sinks.AzureCosmosDB": "2.0.0",
"Serilog.Sinks.SyslogMessages": "2.0.6",
"Stripe.net": "40.0.0",
"YubicoDotNetClient": "1.2.0"
"AWSSDK.SQS": "[3.7.2.47, )",
"AWSSDK.SimpleEmail": "[3.7.0.150, )",
"AspNetCoreRateLimit": "[4.0.2, )",
"AspNetCoreRateLimit.Redis": "[1.0.1, )",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.3.2, )",
"Azure.Messaging.ServiceBus": "[7.15.0, )",
"Azure.Storage.Blobs": "[12.14.1, )",
"Azure.Storage.Queues": "[12.12.0, )",
"BitPay.Light": "[1.0.1907, )",
"Braintree": "[5.19.0, )",
"DnsClient": "[1.7.0, )",
"Fido2.AspNet": "[3.0.1, )",
"Handlebars.Net": "[2.1.2, )",
"IdentityServer4": "[4.1.2, )",
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
"LaunchDarkly.ServerSdk": "[7.0.0, )",
"MailKit": "[3.2.0, )",
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
"Microsoft.Azure.Cosmos.Table": "[1.0.8, )",
"Microsoft.Azure.NotificationHubs": "[4.1.0, )",
"Microsoft.Data.SqlClient": "[5.0.1, )",
"Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )",
"Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )",
"Microsoft.Extensions.Identity.Stores": "[6.0.4, )",
"Newtonsoft.Json": "[13.0.1, )",
"Otp.NET": "[1.2.2, )",
"Quartz": "[3.4.0, )",
"SendGrid": "[9.27.0, )",
"Sentry.Serilog": "[3.16.0, )",
"Serilog.AspNetCore": "[5.0.0, )",
"Serilog.Extensions.Logging": "[3.1.0, )",
"Serilog.Extensions.Logging.File": "[2.0.0, )",
"Serilog.Sinks.AzureCosmosDB": "[2.0.0, )",
"Serilog.Sinks.SyslogMessages": "[2.0.6, )",
"Stripe.net": "[40.0.0, )",
"YubicoDotNetClient": "[1.2.0, )"
}
},
"infrastructure.dapper": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Dapper": "2.0.123"
"Core": "[2023.9.0, )",
"Dapper": "[2.0.123, )"
}
},
"infrastructure.entityframework": {
"type": "Project",
"dependencies": {
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
"Core": "2023.7.2",
"Microsoft.EntityFrameworkCore.Relational": "7.0.5",
"Microsoft.EntityFrameworkCore.SqlServer": "7.0.5",
"Microsoft.EntityFrameworkCore.Sqlite": "7.0.5",
"Npgsql.EntityFrameworkCore.PostgreSQL": "7.0.4",
"Pomelo.EntityFrameworkCore.MySql": "7.0.0",
"linq2db.EntityFrameworkCore": "7.5.0"
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
"Core": "[2023.9.0, )",
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
"Npgsql.EntityFrameworkCore.PostgreSQL": "[7.0.4, )",
"Pomelo.EntityFrameworkCore.MySql": "[7.0.0, )",
"linq2db.EntityFrameworkCore": "[7.5.0, )"
}
},
"sharedweb": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Infrastructure.Dapper": "2023.7.2",
"Infrastructure.EntityFramework": "2023.7.2"
"Core": "[2023.9.0, )",
"Infrastructure.Dapper": "[2023.9.0, )",
"Infrastructure.EntityFramework": "[2023.9.0, )"
}
}
}

View File

@@ -158,10 +158,11 @@
},
"Braintree": {
"type": "Transitive",
"resolved": "5.12.0",
"contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==",
"resolved": "5.19.0",
"contentHash": "B60wIX54g78nMsy5cJkvSfqs1VasYDXWFZQW0cUQ4QeW8Y5jPyBSaoxHwKC806lXUDaKC8kr5Y7Q6EdsBkPANQ==",
"dependencies": {
"Newtonsoft.Json": "9.0.1",
"Microsoft.CSharp": "4.7.0",
"Newtonsoft.Json": "13.0.1",
"System.Xml.XPath.XmlDocument": "4.3.0"
}
},
@@ -2588,63 +2589,63 @@
"core": {
"type": "Project",
"dependencies": {
"AWSSDK.SQS": "3.7.2.47",
"AWSSDK.SimpleEmail": "3.7.0.150",
"AspNetCoreRateLimit": "4.0.2",
"AspNetCoreRateLimit.Redis": "1.0.1",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "1.3.2",
"Azure.Messaging.ServiceBus": "7.15.0",
"Azure.Storage.Blobs": "12.14.1",
"Azure.Storage.Queues": "12.12.0",
"BitPay.Light": "1.0.1907",
"Braintree": "5.12.0",
"DnsClient": "1.7.0",
"Fido2.AspNet": "3.0.1",
"Handlebars.Net": "2.1.2",
"IdentityServer4": "4.1.2",
"IdentityServer4.AccessTokenValidation": "3.0.1",
"LaunchDarkly.ServerSdk": "7.0.0",
"MailKit": "3.2.0",
"Microsoft.AspNetCore.Authentication.JwtBearer": "6.0.4",
"Microsoft.Azure.Cosmos.Table": "1.0.8",
"Microsoft.Azure.NotificationHubs": "4.1.0",
"Microsoft.Data.SqlClient": "5.0.1",
"Microsoft.Extensions.Caching.StackExchangeRedis": "6.0.6",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1",
"Microsoft.Extensions.Configuration.UserSecrets": "6.0.1",
"Microsoft.Extensions.Identity.Stores": "6.0.4",
"Newtonsoft.Json": "13.0.1",
"Otp.NET": "1.2.2",
"Quartz": "3.4.0",
"SendGrid": "9.27.0",
"Sentry.Serilog": "3.16.0",
"Serilog.AspNetCore": "5.0.0",
"Serilog.Extensions.Logging": "3.1.0",
"Serilog.Extensions.Logging.File": "2.0.0",
"Serilog.Sinks.AzureCosmosDB": "2.0.0",
"Serilog.Sinks.SyslogMessages": "2.0.6",
"Stripe.net": "40.0.0",
"YubicoDotNetClient": "1.2.0"
"AWSSDK.SQS": "[3.7.2.47, )",
"AWSSDK.SimpleEmail": "[3.7.0.150, )",
"AspNetCoreRateLimit": "[4.0.2, )",
"AspNetCoreRateLimit.Redis": "[1.0.1, )",
"Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.3.2, )",
"Azure.Messaging.ServiceBus": "[7.15.0, )",
"Azure.Storage.Blobs": "[12.14.1, )",
"Azure.Storage.Queues": "[12.12.0, )",
"BitPay.Light": "[1.0.1907, )",
"Braintree": "[5.19.0, )",
"DnsClient": "[1.7.0, )",
"Fido2.AspNet": "[3.0.1, )",
"Handlebars.Net": "[2.1.2, )",
"IdentityServer4": "[4.1.2, )",
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
"LaunchDarkly.ServerSdk": "[7.0.0, )",
"MailKit": "[3.2.0, )",
"Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )",
"Microsoft.Azure.Cosmos.Table": "[1.0.8, )",
"Microsoft.Azure.NotificationHubs": "[4.1.0, )",
"Microsoft.Data.SqlClient": "[5.0.1, )",
"Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )",
"Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )",
"Microsoft.Extensions.Identity.Stores": "[6.0.4, )",
"Newtonsoft.Json": "[13.0.1, )",
"Otp.NET": "[1.2.2, )",
"Quartz": "[3.4.0, )",
"SendGrid": "[9.27.0, )",
"Sentry.Serilog": "[3.16.0, )",
"Serilog.AspNetCore": "[5.0.0, )",
"Serilog.Extensions.Logging": "[3.1.0, )",
"Serilog.Extensions.Logging.File": "[2.0.0, )",
"Serilog.Sinks.AzureCosmosDB": "[2.0.0, )",
"Serilog.Sinks.SyslogMessages": "[2.0.6, )",
"Stripe.net": "[40.0.0, )",
"YubicoDotNetClient": "[1.2.0, )"
}
},
"infrastructure.dapper": {
"type": "Project",
"dependencies": {
"Core": "2023.7.2",
"Dapper": "2.0.123"
"Core": "[2023.9.0, )",
"Dapper": "[2.0.123, )"
}
},
"infrastructure.entityframework": {
"type": "Project",
"dependencies": {
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
"Core": "2023.7.2",
"Microsoft.EntityFrameworkCore.Relational": "7.0.5",
"Microsoft.EntityFrameworkCore.SqlServer": "7.0.5",
"Microsoft.EntityFrameworkCore.Sqlite": "7.0.5",
"Npgsql.EntityFrameworkCore.PostgreSQL": "7.0.4",
"Pomelo.EntityFrameworkCore.MySql": "7.0.0",
"linq2db.EntityFrameworkCore": "7.5.0"
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
"Core": "[2023.9.0, )",
"Microsoft.EntityFrameworkCore.Relational": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.SqlServer": "[7.0.5, )",
"Microsoft.EntityFrameworkCore.Sqlite": "[7.0.5, )",
"Npgsql.EntityFrameworkCore.PostgreSQL": "[7.0.4, )",
"Pomelo.EntityFrameworkCore.MySql": "[7.0.0, )",
"linq2db.EntityFrameworkCore": "[7.5.0, )"
}
}
}