mirror of
https://github.com/bitwarden/server
synced 2025-12-27 21:53:24 +00:00
Merge remote-tracking branch 'origin/master' into feature/sm-billing
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using Bit.Core;
|
||||
using Bit.Core.Jobs;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Settings;
|
||||
using Quartz;
|
||||
|
||||
namespace Bit.Admin.Auth.Jobs;
|
||||
@@ -8,20 +9,26 @@ namespace Bit.Admin.Auth.Jobs;
|
||||
public class DeleteAuthRequestsJob : BaseJob
|
||||
{
|
||||
private readonly IAuthRequestRepository _authRepo;
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
|
||||
public DeleteAuthRequestsJob(
|
||||
IAuthRequestRepository authrepo,
|
||||
IGlobalSettings globalSettings,
|
||||
ILogger<DeleteAuthRequestsJob> logger)
|
||||
: base(logger)
|
||||
{
|
||||
_authRepo = authrepo;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
protected async override Task ExecuteJobAsync(IJobExecutionContext context)
|
||||
{
|
||||
_logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: DeleteAuthRequestsJob: Start");
|
||||
var count = await _authRepo.DeleteExpiredAsync();
|
||||
_logger.LogInformation(Constants.BypassFiltersEventId, $"{count} records deleted from AuthRequests.");
|
||||
var count = await _authRepo.DeleteExpiredAsync(
|
||||
_globalSettings.PasswordlessAuth.UserRequestExpiration,
|
||||
_globalSettings.PasswordlessAuth.AdminRequestExpiration,
|
||||
_globalSettings.PasswordlessAuth.AfterAdminApprovalExpiration);
|
||||
_logger.LogInformation(Constants.BypassFiltersEventId, "{Count} records deleted from AuthRequests.", count);
|
||||
_logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: DeleteAuthRequestsJob: End");
|
||||
}
|
||||
}
|
||||
|
||||
20
src/Admin/package-lock.json
generated
20
src/Admin/package-lock.json
generated
@@ -17,8 +17,8 @@
|
||||
"jquery": "3.5.1",
|
||||
"merge-stream": "2.0.0",
|
||||
"popper.js": "1.16.1",
|
||||
"sass": "^1.49.7",
|
||||
"toastr": "^2.1.4"
|
||||
"sass": "1.49.7",
|
||||
"toastr": "2.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
@@ -3925,9 +3925,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/sass/node_modules/anymatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"normalize-path": "^3.0.0",
|
||||
@@ -4694,7 +4694,7 @@
|
||||
"node_modules/toastr": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/toastr/-/toastr-2.1.4.tgz",
|
||||
"integrity": "sha1-i0O+ZPudDEFIcURvLbjoyk6V8YE=",
|
||||
"integrity": "sha512-LIy77F5n+sz4tefMmFOntcJ6HL0Fv3k1TDnNmFZ0bU/GcvIIfy6eG2v7zQmMiYgaalAiUv75ttFrPn5s0gyqlA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"jquery": ">=1.12.0"
|
||||
@@ -8168,9 +8168,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"anymatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"normalize-path": "^3.0.0",
|
||||
@@ -8774,7 +8774,7 @@
|
||||
"toastr": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/toastr/-/toastr-2.1.4.tgz",
|
||||
"integrity": "sha1-i0O+ZPudDEFIcURvLbjoyk6V8YE=",
|
||||
"integrity": "sha512-LIy77F5n+sz4tefMmFOntcJ6HL0Fv3k1TDnNmFZ0bU/GcvIIfy6eG2v7zQmMiYgaalAiUv75ttFrPn5s0gyqlA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"jquery": ">=1.12.0"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"jquery": "3.5.1",
|
||||
"merge-stream": "2.0.0",
|
||||
"popper.js": "1.16.1",
|
||||
"sass": "^1.49.7",
|
||||
"toastr": "^2.1.4"
|
||||
"sass": "1.49.7",
|
||||
"toastr": "2.1.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2834,7 +2834,7 @@
|
||||
"commercial.core": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3"
|
||||
"Core": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"core": {
|
||||
@@ -2882,7 +2882,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2890,7 +2890,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2902,7 +2902,7 @@
|
||||
"migrator": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.Extensions.Logging": "6.0.0",
|
||||
"dbup-sqlserver": "5.0.8"
|
||||
}
|
||||
@@ -2910,30 +2910,30 @@
|
||||
"mysqlmigrations": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"postgresmigrations": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"sqlitemigrations": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ using Bit.Core.Models.Business;
|
||||
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
|
||||
using Bit.Core.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.SecretsManager.Commands.EnableAccessSecretsManager.Interfaces;
|
||||
using Bit.Core.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -19,6 +20,7 @@ namespace Bit.Api.Controllers;
|
||||
[Authorize("Application")]
|
||||
public class OrganizationUsersController : Controller
|
||||
{
|
||||
private readonly IEnableAccessSecretsManagerCommand _enableAccessSecretsManagerCommand;
|
||||
private readonly IOrganizationRepository _organizationRepository;
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
private readonly IOrganizationService _organizationService;
|
||||
@@ -29,6 +31,7 @@ public class OrganizationUsersController : Controller
|
||||
private readonly ICurrentContext _currentContext;
|
||||
|
||||
public OrganizationUsersController(
|
||||
IEnableAccessSecretsManagerCommand enableAccessSecretsManagerCommand,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
IOrganizationService organizationService,
|
||||
@@ -38,6 +41,7 @@ public class OrganizationUsersController : Controller
|
||||
IPolicyRepository policyRepository,
|
||||
ICurrentContext currentContext)
|
||||
{
|
||||
_enableAccessSecretsManagerCommand = enableAccessSecretsManagerCommand;
|
||||
_organizationRepository = organizationRepository;
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
_organizationService = organizationService;
|
||||
@@ -420,6 +424,29 @@ public class OrganizationUsersController : Controller
|
||||
return await RestoreOrRevokeUsersAsync(orgId, model, (orgId, orgUserIds, restoringUserId) => _organizationService.RestoreUsersAsync(orgId, orgUserIds, restoringUserId, _userService));
|
||||
}
|
||||
|
||||
[HttpPatch("enable-secrets-manager")]
|
||||
[HttpPut("enable-secrets-manager")]
|
||||
public async Task<ListResponseModel<OrganizationUserBulkResponseModel>> BulkEnableSecretsManagerAsync(Guid orgId,
|
||||
[FromBody] OrganizationUserBulkRequestModel model)
|
||||
{
|
||||
if (!await _currentContext.ManageUsers(orgId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var orgUsers = (await _organizationUserRepository.GetManyAsync(model.Ids))
|
||||
.Where(ou => ou.OrganizationId == orgId).ToList();
|
||||
if (orgUsers.Count == 0)
|
||||
{
|
||||
throw new BadRequestException("Users invalid.");
|
||||
}
|
||||
|
||||
var results = await _enableAccessSecretsManagerCommand.EnableUsersAsync(orgUsers);
|
||||
|
||||
return new ListResponseModel<OrganizationUserBulkResponseModel>(results.Select(r =>
|
||||
new OrganizationUserBulkResponseModel(r.organizationUser.Id, r.error)));
|
||||
}
|
||||
|
||||
private async Task RestoreOrRevokeUserAsync(
|
||||
Guid orgId,
|
||||
Guid id,
|
||||
|
||||
@@ -28,6 +28,7 @@ public class ConfigResponseModel : ResponseModel
|
||||
GitHash = AssemblyHelpers.GetGitHash();
|
||||
Environment = new EnvironmentConfigResponseModel
|
||||
{
|
||||
CloudRegion = globalSettings.BaseServiceUri.CloudRegion,
|
||||
Vault = globalSettings.BaseServiceUri.Vault,
|
||||
Api = globalSettings.BaseServiceUri.Api,
|
||||
Identity = globalSettings.BaseServiceUri.Identity,
|
||||
@@ -46,6 +47,7 @@ public class ServerConfigResponseModel
|
||||
|
||||
public class EnvironmentConfigResponseModel
|
||||
{
|
||||
public string CloudRegion { get; set; }
|
||||
public string Vault { get; set; }
|
||||
public string Api { get; set; }
|
||||
public string Identity { get; set; }
|
||||
|
||||
@@ -73,9 +73,8 @@ public class ProjectsController : Controller
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var userId = _userService.GetProperUserId(User).Value;
|
||||
var result = await _createProjectCommand.CreateAsync(project, userId);
|
||||
var result = await _createProjectCommand.CreateAsync(project, userId, _currentContext.ClientType);
|
||||
|
||||
// Creating a project means you have read & write permission.
|
||||
return new ProjectResponseModel(result, true, true);
|
||||
|
||||
@@ -136,7 +136,10 @@ public class Startup
|
||||
services.AddCoreLocalizationServices();
|
||||
|
||||
//health check
|
||||
services.AddHealthChecks(globalSettings);
|
||||
if (!globalSettings.SelfHosted)
|
||||
{
|
||||
services.AddHealthChecks(globalSettings);
|
||||
}
|
||||
|
||||
#if OSS
|
||||
services.AddOosServices();
|
||||
@@ -215,12 +218,15 @@ public class Startup
|
||||
{
|
||||
endpoints.MapDefaultControllerRoute();
|
||||
|
||||
endpoints.MapHealthChecks("/healthz");
|
||||
|
||||
endpoints.MapHealthChecks("/healthz/extended", new HealthCheckOptions
|
||||
if (!globalSettings.SelfHosted)
|
||||
{
|
||||
ResponseWriter = HealthCheckServiceExtensions.WriteResponse
|
||||
});
|
||||
endpoints.MapHealthChecks("/healthz");
|
||||
|
||||
endpoints.MapHealthChecks("/healthz/extended", new HealthCheckOptions
|
||||
{
|
||||
ResponseWriter = HealthCheckServiceExtensions.WriteResponse
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Add Swagger
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Bit.Core.IdentityServer;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.SharedWeb.Health;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
@@ -80,35 +81,35 @@ public static class ServiceCollectionExtensions
|
||||
|
||||
builder.AddUrlGroup(identityUri, "identity");
|
||||
|
||||
if (!string.IsNullOrEmpty(globalSettings.SqlServer.ConnectionString))
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.SqlServer.ConnectionString))
|
||||
{
|
||||
builder.AddSqlServer(globalSettings.SqlServer.ConnectionString);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(globalSettings.Redis.ConnectionString))
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.Redis.ConnectionString))
|
||||
{
|
||||
builder.AddRedis(globalSettings.Redis.ConnectionString);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(globalSettings.Storage.ConnectionString))
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.Storage.ConnectionString))
|
||||
{
|
||||
builder.AddAzureQueueStorage(globalSettings.Storage.ConnectionString, name: "storage_queue")
|
||||
.AddAzureQueueStorage(globalSettings.Events.ConnectionString, name: "events_queue");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(globalSettings.Notifications.ConnectionString))
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.Notifications.ConnectionString))
|
||||
{
|
||||
builder.AddAzureQueueStorage(globalSettings.Notifications.ConnectionString,
|
||||
name: "notifications_queue");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(globalSettings.ServiceBus.ConnectionString))
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.ServiceBus.ConnectionString))
|
||||
{
|
||||
builder.AddAzureServiceBusTopic(_ => globalSettings.ServiceBus.ConnectionString,
|
||||
_ => globalSettings.ServiceBus.ApplicationCacheTopicName, name: "service_bus");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(globalSettings.Mail.SendGridApiKey))
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.Mail.SendGridApiKey))
|
||||
{
|
||||
builder.AddSendGrid(globalSettings.Mail.SendGridApiKey);
|
||||
}
|
||||
|
||||
@@ -2907,85 +2907,85 @@
|
||||
"commercial.core": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.5.0, )"
|
||||
"Core": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"commercial.infrastructure.entityframework": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.5.0, )",
|
||||
"Infrastructure.EntityFramework": "[2023.5.0, )"
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"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.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.Azure.ServiceBus": "[5.2.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.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.Azure.ServiceBus": "5.2.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.5.0, )",
|
||||
"Dapper": "[2.0.123, )"
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
"infrastructure.entityframework": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.5.0, )",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "[6.0.12, )",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "[6.0.12, )",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "[6.0.12, )",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "[6.0.8, )",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "[6.0.2, )",
|
||||
"linq2db.EntityFrameworkCore": "[6.11.0, )"
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "6.0.8",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "6.0.2",
|
||||
"linq2db.EntityFrameworkCore": "6.11.0"
|
||||
}
|
||||
},
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.5.0, )",
|
||||
"Infrastructure.Dapper": "[2023.5.0, )",
|
||||
"Infrastructure.EntityFramework": "[2023.5.0, )"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2786,7 +2786,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2794,7 +2794,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2806,9 +2806,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Bit.Core.Repositories;
|
||||
|
||||
public interface IAuthRequestRepository : IRepository<AuthRequest, Guid>
|
||||
{
|
||||
Task<int> DeleteExpiredAsync();
|
||||
Task<int> DeleteExpiredAsync(TimeSpan userRequestExpiration, TimeSpan adminRequestExpiration, TimeSpan afterAdminApprovalExpiration);
|
||||
Task<ICollection<AuthRequest>> GetManyByUserIdAsync(Guid userId);
|
||||
Task<ICollection<OrganizationAdminAuthRequest>> GetManyPendingByOrganizationIdAsync(Guid organizationId);
|
||||
Task<ICollection<OrganizationAdminAuthRequest>> GetManyAdminApprovalRequestsByManyIdsAsync(Guid organizationId, IEnumerable<Guid> ids);
|
||||
|
||||
@@ -3,4 +3,7 @@
|
||||
public interface IPasswordlessAuthSettings
|
||||
{
|
||||
bool KnownDevicesOnly { get; set; }
|
||||
TimeSpan UserRequestExpiration { get; set; }
|
||||
TimeSpan AdminRequestExpiration { get; set; }
|
||||
TimeSpan AfterAdminApprovalExpiration { get; set; }
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterpri
|
||||
using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Cloud;
|
||||
using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces;
|
||||
using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.SelfHosted;
|
||||
using Bit.Core.SecretsManager.Commands.EnableAccessSecretsManager;
|
||||
using Bit.Core.SecretsManager.Commands.EnableAccessSecretsManager.Interfaces;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Core.Tokens;
|
||||
@@ -29,6 +31,7 @@ public static class OrganizationServiceCollectionExtensions
|
||||
public static void AddOrganizationServices(this IServiceCollection services, IGlobalSettings globalSettings)
|
||||
{
|
||||
services.AddScoped<IOrganizationService, OrganizationService>();
|
||||
services.AddScoped<IEnableAccessSecretsManagerCommand, EnableAccessSecretsManagerCommand>();
|
||||
services.AddTokenizers();
|
||||
services.AddOrganizationGroupCommands();
|
||||
services.AddOrganizationConnectionCommands();
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.SecretsManager.Commands.EnableAccessSecretsManager.Interfaces;
|
||||
|
||||
namespace Bit.Core.SecretsManager.Commands.EnableAccessSecretsManager;
|
||||
|
||||
public class EnableAccessSecretsManagerCommand : IEnableAccessSecretsManagerCommand
|
||||
{
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
|
||||
public EnableAccessSecretsManagerCommand(IOrganizationUserRepository organizationUserRepository)
|
||||
{
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
}
|
||||
|
||||
public async Task<List<(OrganizationUser organizationUser, string error)>> EnableUsersAsync(
|
||||
IEnumerable<OrganizationUser> organizationUsers)
|
||||
{
|
||||
var results = new List<(OrganizationUser organizationUser, string error)>();
|
||||
var usersToEnable = new List<OrganizationUser>();
|
||||
|
||||
foreach (var orgUser in organizationUsers)
|
||||
{
|
||||
if (orgUser.AccessSecretsManager)
|
||||
{
|
||||
results.Add((orgUser, "User already has access to Secrets Manager"));
|
||||
}
|
||||
else
|
||||
{
|
||||
orgUser.AccessSecretsManager = true;
|
||||
usersToEnable.Add(orgUser);
|
||||
results.Add((orgUser, ""));
|
||||
}
|
||||
}
|
||||
|
||||
if (usersToEnable.Any())
|
||||
{
|
||||
await _organizationUserRepository.ReplaceManyAsync(usersToEnable);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Bit.Core.Entities;
|
||||
|
||||
namespace Bit.Core.SecretsManager.Commands.EnableAccessSecretsManager.Interfaces;
|
||||
|
||||
public interface IEnableAccessSecretsManagerCommand
|
||||
{
|
||||
Task<List<(OrganizationUser organizationUser, string error)>> EnableUsersAsync(
|
||||
IEnumerable<OrganizationUser> organizationUsers);
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
using Bit.Core.SecretsManager.Entities;
|
||||
using Bit.Core.Identity;
|
||||
using Bit.Core.SecretsManager.Entities;
|
||||
|
||||
namespace Bit.Core.SecretsManager.Commands.Projects.Interfaces;
|
||||
|
||||
public interface ICreateProjectCommand
|
||||
{
|
||||
Task<Project> CreateAsync(Project project, Guid userId);
|
||||
Task<Project> CreateAsync(Project project, Guid userId, ClientType clientType);
|
||||
}
|
||||
|
||||
@@ -143,6 +143,7 @@ public class GlobalSettings : IGlobalSettings
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
public string CloudRegion { get; set; }
|
||||
public string Vault { get; set; }
|
||||
public string VaultWithHash => $"{Vault}/#";
|
||||
|
||||
@@ -534,6 +535,9 @@ public class GlobalSettings : IGlobalSettings
|
||||
public class PasswordlessAuthSettings : IPasswordlessAuthSettings
|
||||
{
|
||||
public bool KnownDevicesOnly { get; set; } = true;
|
||||
public TimeSpan UserRequestExpiration { get; set; } = TimeSpan.FromMinutes(15);
|
||||
public TimeSpan AdminRequestExpiration { get; set; } = TimeSpan.FromDays(7);
|
||||
public TimeSpan AfterAdminApprovalExpiration { get; set; } = TimeSpan.FromHours(12);
|
||||
}
|
||||
|
||||
public class DomainVerificationSettings : IDomainVerificationSettings
|
||||
|
||||
@@ -3,6 +3,7 @@ namespace Bit.Core.Settings;
|
||||
|
||||
public interface IBaseServiceUriSettings
|
||||
{
|
||||
string CloudRegion { get; set; }
|
||||
string Vault { get; set; }
|
||||
string VaultWithHash { get; }
|
||||
string Api { get; set; }
|
||||
|
||||
@@ -2786,7 +2786,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2794,7 +2794,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2806,9 +2806,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2786,7 +2786,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2794,7 +2794,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2806,9 +2806,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2796,7 +2796,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2804,7 +2804,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2816,9 +2816,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2808,7 +2808,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2816,7 +2816,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2828,9 +2828,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,13 +19,19 @@ public class AuthRequestRepository : Repository<AuthRequest, Guid>, IAuthRequest
|
||||
: base(connectionString, readOnlyConnectionString)
|
||||
{ }
|
||||
|
||||
public async Task<int> DeleteExpiredAsync()
|
||||
public async Task<int> DeleteExpiredAsync(
|
||||
TimeSpan userRequestExpiration, TimeSpan adminRequestExpiration, TimeSpan afterAdminApprovalExpiration)
|
||||
{
|
||||
using (var connection = new SqlConnection(ConnectionString))
|
||||
{
|
||||
return await connection.ExecuteAsync(
|
||||
$"[{Schema}].[AuthRequest_DeleteIfExpired]",
|
||||
null,
|
||||
new
|
||||
{
|
||||
UserExpirationSeconds = (int)userRequestExpiration.TotalSeconds,
|
||||
AdminExpirationSeconds = (int)adminRequestExpiration.TotalSeconds,
|
||||
AdminApprovalExpirationSeconds = (int)afterAdminApprovalExpiration.TotalSeconds,
|
||||
},
|
||||
commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,15 +15,20 @@ public class AuthRequestRepository : Repository<Core.Auth.Entities.AuthRequest,
|
||||
public AuthRequestRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
|
||||
: base(serviceScopeFactory, mapper, (DatabaseContext context) => context.AuthRequests)
|
||||
{ }
|
||||
public async Task<int> DeleteExpiredAsync()
|
||||
public async Task<int> DeleteExpiredAsync(
|
||||
TimeSpan userRequestExpiration, TimeSpan adminRequestExpiration, TimeSpan afterAdminApprovalExpiration)
|
||||
{
|
||||
|
||||
using (var scope = ServiceScopeFactory.CreateScope())
|
||||
{
|
||||
var dbContext = GetDatabaseContext(scope);
|
||||
var expiredRequests = await dbContext.AuthRequests.Where(a => a.CreationDate < DateTime.Now.AddMinutes(-15)).ToListAsync();
|
||||
var expiredRequests = await dbContext.AuthRequests
|
||||
.Where(a => (a.Type != AuthRequestType.AdminApproval && a.CreationDate.AddSeconds(userRequestExpiration.TotalSeconds) < DateTime.UtcNow)
|
||||
|| (a.Type == AuthRequestType.AdminApproval && a.Approved != true && a.CreationDate.AddSeconds(adminRequestExpiration.TotalSeconds) < DateTime.UtcNow)
|
||||
|| (a.Type == AuthRequestType.AdminApproval && a.Approved == true && a.ResponseDate.Value.AddSeconds(afterAdminApprovalExpiration.TotalSeconds) < DateTime.UtcNow))
|
||||
.ToListAsync();
|
||||
dbContext.AuthRequests.RemoveRange(expiredRequests);
|
||||
await dbContext.SaveChangesAsync();
|
||||
return 1;
|
||||
return await dbContext.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ public class UserCipherDetailsQuery : IQuery<CipherDetails>
|
||||
|
||||
where ou.AccessAll || cu.CollectionId != null || g.AccessAll || cg.CollectionId != null
|
||||
|
||||
select new { c, ou, o, cc, cu, gu, g, cg }.c;
|
||||
select c;
|
||||
|
||||
var query2 = from c in dbContext.Ciphers
|
||||
where c.UserId == _userId
|
||||
@@ -79,14 +79,23 @@ public class UserCipherDetailsQuery : IQuery<CipherDetails>
|
||||
|
||||
private static Guid? GetFolderId(Guid? userId, Cipher cipher)
|
||||
{
|
||||
if (userId.HasValue && !string.IsNullOrWhiteSpace(cipher.Folders))
|
||||
try
|
||||
{
|
||||
var folders = JsonSerializer.Deserialize<Dictionary<Guid, Guid>>(cipher.Folders);
|
||||
if (folders.TryGetValue(userId.Value, out var folder))
|
||||
if (userId.HasValue && !string.IsNullOrWhiteSpace(cipher.Folders))
|
||||
{
|
||||
return folder;
|
||||
var folders = JsonSerializer.Deserialize<Dictionary<Guid, Guid>>(cipher.Folders);
|
||||
if (folders.TryGetValue(userId.Value, out var folder))
|
||||
{
|
||||
return folder;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Some Folders might be in an invalid format like: '{ "", "<ValidGuid>" }'
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using AutoMapper;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using AutoMapper;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Core.Vault.Enums;
|
||||
@@ -13,8 +15,8 @@ using Bit.Infrastructure.EntityFramework.Vault.Repositories.Queries;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NS = Newtonsoft.Json;
|
||||
using NSL = Newtonsoft.Json.Linq;
|
||||
using User = Bit.Core.Entities.User;
|
||||
|
||||
namespace Bit.Infrastructure.EntityFramework.Vault.Repositories;
|
||||
@@ -198,9 +200,9 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
{
|
||||
var dbContext = GetDatabaseContext(scope);
|
||||
var cipher = await dbContext.Ciphers.FindAsync(cipherId);
|
||||
var attachmentsJson = JObject.Parse(cipher.Attachments);
|
||||
var attachmentsJson = NSL.JObject.Parse(cipher.Attachments);
|
||||
attachmentsJson.Remove(attachmentId);
|
||||
cipher.Attachments = JsonConvert.SerializeObject(attachmentsJson);
|
||||
cipher.Attachments = NS.JsonConvert.SerializeObject(attachmentsJson);
|
||||
await dbContext.SaveChangesAsync();
|
||||
|
||||
if (cipher.OrganizationId.HasValue)
|
||||
@@ -396,8 +398,8 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
await idsToMove.ForEachAsync(cipher =>
|
||||
{
|
||||
var foldersJson = string.IsNullOrWhiteSpace(cipher.Folders) ?
|
||||
new JObject() :
|
||||
JObject.Parse(cipher.Folders);
|
||||
new NSL.JObject() :
|
||||
NSL.JObject.Parse(cipher.Folders);
|
||||
|
||||
if (folderId.HasValue)
|
||||
{
|
||||
@@ -409,7 +411,7 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
foldersJson.Remove(userId.ToString());
|
||||
}
|
||||
dbContext.Attach(cipher);
|
||||
cipher.Folders = JsonConvert.SerializeObject(foldersJson);
|
||||
cipher.Folders = NS.JsonConvert.SerializeObject(foldersJson);
|
||||
});
|
||||
await dbContext.UserBumpAccountRevisionDateAsync(userId);
|
||||
await dbContext.SaveChangesAsync();
|
||||
@@ -418,27 +420,27 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
|
||||
public async Task ReplaceAsync(CipherDetails cipher)
|
||||
{
|
||||
cipher.UserId = cipher.OrganizationId.HasValue ?
|
||||
null :
|
||||
cipher.UserId;
|
||||
using (var scope = ServiceScopeFactory.CreateScope())
|
||||
{
|
||||
var dbContext = GetDatabaseContext(scope);
|
||||
var entity = await dbContext.Ciphers.FindAsync(cipher.Id);
|
||||
if (entity != null)
|
||||
{
|
||||
var userIdKey = $"\"{cipher.UserId}\"";
|
||||
if (cipher.Favorite)
|
||||
{
|
||||
if (cipher.Favorites == null)
|
||||
{
|
||||
cipher.Favorites = $"{{{userIdKey}:true}}";
|
||||
var jsonObject = new JsonObject(new[]
|
||||
{
|
||||
new KeyValuePair<string, JsonNode>(cipher.UserId.Value.ToString(), true),
|
||||
});
|
||||
cipher.Favorites = JsonSerializer.Serialize(jsonObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
var favorites = CoreHelpers.LoadClassFromJsonData<Dictionary<Guid, bool>>(cipher.Favorites);
|
||||
favorites.Add(cipher.UserId.Value, true);
|
||||
cipher.Favorites = JsonConvert.SerializeObject(favorites);
|
||||
cipher.Favorites = JsonSerializer.Serialize(favorites);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -447,32 +449,45 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
{
|
||||
var favorites = CoreHelpers.LoadClassFromJsonData<Dictionary<Guid, bool>>(cipher.Favorites);
|
||||
favorites.Remove(cipher.UserId.Value);
|
||||
cipher.Favorites = JsonConvert.SerializeObject(favorites);
|
||||
cipher.Favorites = JsonSerializer.Serialize(favorites);
|
||||
}
|
||||
}
|
||||
if (cipher.FolderId.HasValue)
|
||||
{
|
||||
if (cipher.Folders == null)
|
||||
{
|
||||
cipher.Folders = $"{{{userIdKey}:\"{cipher.FolderId}\"}}";
|
||||
var jsonObject = new JsonObject(new[]
|
||||
{
|
||||
new KeyValuePair<string, JsonNode>(cipher.UserId.Value.ToString(), cipher.FolderId),
|
||||
});
|
||||
cipher.Folders = JsonSerializer.Serialize(jsonObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
var folders = CoreHelpers.LoadClassFromJsonData<Dictionary<Guid, Guid>>(cipher.Folders);
|
||||
folders.Add(cipher.UserId.Value, cipher.FolderId.Value);
|
||||
cipher.Folders = JsonConvert.SerializeObject(folders);
|
||||
cipher.Folders = JsonSerializer.Serialize(folders);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cipher.Folders != null && cipher.Folders.Contains(cipher.UserId.Value.ToString()))
|
||||
{
|
||||
var folders = CoreHelpers.LoadClassFromJsonData<Dictionary<Guid, bool>>(cipher.Favorites);
|
||||
var folders = CoreHelpers.LoadClassFromJsonData<Dictionary<Guid, Guid>>(cipher.Folders);
|
||||
folders.Remove(cipher.UserId.Value);
|
||||
cipher.Favorites = JsonConvert.SerializeObject(folders);
|
||||
cipher.Folders = JsonSerializer.Serialize(folders);
|
||||
}
|
||||
}
|
||||
var mappedEntity = Mapper.Map<Cipher>((Core.Vault.Entities.Cipher)cipher);
|
||||
|
||||
// Check if this cipher is a part of an organization, and if so do
|
||||
// not save the UserId into the database. This must be done after we
|
||||
// set the user specific data like Folders and Favorites because
|
||||
// the UserId key is used for that
|
||||
cipher.UserId = cipher.OrganizationId.HasValue ?
|
||||
null :
|
||||
cipher.UserId;
|
||||
|
||||
var mappedEntity = Mapper.Map<Cipher>(cipher);
|
||||
dbContext.Entry(entity).CurrentValues.SetValues(mappedEntity);
|
||||
|
||||
if (cipher.OrganizationId.HasValue)
|
||||
@@ -701,10 +716,10 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
var cipher = await dbContext.Ciphers.FindAsync(attachment.Id);
|
||||
var attachments = string.IsNullOrWhiteSpace(cipher.Attachments) ?
|
||||
new Dictionary<string, CipherAttachment.MetaData>() :
|
||||
JsonConvert.DeserializeObject<Dictionary<string, CipherAttachment.MetaData>>(cipher.Attachments);
|
||||
var metaData = JsonConvert.DeserializeObject<CipherAttachment.MetaData>(attachment.AttachmentData);
|
||||
NS.JsonConvert.DeserializeObject<Dictionary<string, CipherAttachment.MetaData>>(cipher.Attachments);
|
||||
var metaData = NS.JsonConvert.DeserializeObject<CipherAttachment.MetaData>(attachment.AttachmentData);
|
||||
attachments[attachment.AttachmentId] = metaData;
|
||||
cipher.Attachments = JsonConvert.SerializeObject(attachments);
|
||||
cipher.Attachments = NS.JsonConvert.SerializeObject(attachments);
|
||||
await dbContext.SaveChangesAsync();
|
||||
|
||||
if (attachment.OrganizationId.HasValue)
|
||||
@@ -744,7 +759,7 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
var dbContext = GetDatabaseContext(scope);
|
||||
var cipher = await dbContext.Ciphers.FindAsync(id);
|
||||
|
||||
var foldersJson = JObject.Parse(cipher.Folders);
|
||||
var foldersJson = NSL.JObject.Parse(cipher.Folders);
|
||||
if (foldersJson == null && folderId.HasValue)
|
||||
{
|
||||
foldersJson.Add(userId.ToString(), folderId.Value);
|
||||
@@ -758,7 +773,7 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
foldersJson.Remove(userId.ToString());
|
||||
}
|
||||
|
||||
var favoritesJson = JObject.Parse(cipher.Favorites);
|
||||
var favoritesJson = NSL.JObject.Parse(cipher.Favorites);
|
||||
if (favorite)
|
||||
{
|
||||
favoritesJson.Add(userId.ToString(), favorite);
|
||||
|
||||
@@ -2836,7 +2836,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2844,7 +2844,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2856,9 +2856,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2786,7 +2786,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2794,7 +2794,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
|
||||
@@ -1,6 +1,19 @@
|
||||
CREATE PROCEDURE [dbo].[AuthRequest_DeleteIfExpired]
|
||||
-- UserExpirationSeconds to 15 minutes (15 * 60)
|
||||
-- AdminExpirationSeconds to 7 days (7 * 24 * 60 * 60)
|
||||
-- AdminApprovalExpirationSeconds to 12 hour (12 * 60 * 60)
|
||||
|
||||
CREATE PROCEDURE [dbo].[AuthRequest_DeleteIfExpired]
|
||||
@UserExpirationSeconds INT = 900,
|
||||
@AdminExpirationSeconds INT = 604800,
|
||||
@AdminApprovalExpirationSeconds INT = 43200
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT OFF
|
||||
DELETE FROM [dbo].[AuthRequest] WHERE [CreationDate] < DATEADD(minute, -15, GETUTCDATE());
|
||||
DELETE FROM [dbo].[AuthRequest]
|
||||
-- User requests expire after 15 minutes (by default) of their creation
|
||||
WHERE ([Type] != 2 AND DATEADD(second, @UserExpirationSeconds, [CreationDate]) < GETUTCDATE())
|
||||
-- Admin requests expire after 7 days (by default) of their creation if they have not been approved
|
||||
OR ([Type] = 2 AND ([Approved] IS NULL OR [Approved] = 0) AND DATEADD(second, @AdminExpirationSeconds,[CreationDate]) < GETUTCDATE())
|
||||
-- Admin requests expire after 12 hours (by default) of their approval
|
||||
OR ([Type] = 2 AND [Approved] = 1 AND DATEADD(second, @AdminApprovalExpirationSeconds, [ResponseDate]) < GETUTCDATE());
|
||||
END
|
||||
|
||||
Reference in New Issue
Block a user