diff --git a/bitwarden_license/src/Portal/Controllers/SsoController.cs b/bitwarden_license/src/Portal/Controllers/SsoController.cs index 7757a11abd..f21f601eb4 100644 --- a/bitwarden_license/src/Portal/Controllers/SsoController.cs +++ b/bitwarden_license/src/Portal/Controllers/SsoController.cs @@ -1,7 +1,7 @@ using System.Threading.Tasks; -using Bit.Core; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using Bit.Portal.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/bitwarden_license/src/Portal/Models/SsoConfigDataViewModel.cs b/bitwarden_license/src/Portal/Models/SsoConfigDataViewModel.cs index e90321445d..f53afd20f8 100644 --- a/bitwarden_license/src/Portal/Models/SsoConfigDataViewModel.cs +++ b/bitwarden_license/src/Portal/Models/SsoConfigDataViewModel.cs @@ -2,10 +2,10 @@ using System.ComponentModel.DataAnnotations; using System.Collections.Generic; using Bit.Core.Services; -using Bit.Core; using Bit.Core.Models.Data; using Bit.Core.Enums; using Bit.Core.Sso; +using Bit.Core.Settings; using U2F.Core.Utils; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; diff --git a/bitwarden_license/src/Portal/Models/SsoConfigEditViewModel.cs b/bitwarden_license/src/Portal/Models/SsoConfigEditViewModel.cs index 9e384061da..b6a4223a2b 100644 --- a/bitwarden_license/src/Portal/Models/SsoConfigEditViewModel.cs +++ b/bitwarden_license/src/Portal/Models/SsoConfigEditViewModel.cs @@ -3,11 +3,11 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text.Json; -using Bit.Core; using Bit.Core.Enums; using Bit.Core.Models.Data; using Bit.Core.Models.Table; using Bit.Core.Services; +using Bit.Core.Settings; using Bit.Core.Sso; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.AspNetCore.Mvc.Rendering; diff --git a/bitwarden_license/src/Portal/Startup.cs b/bitwarden_license/src/Portal/Startup.cs index 5aa693a231..670eb51942 100644 --- a/bitwarden_license/src/Portal/Startup.cs +++ b/bitwarden_license/src/Portal/Startup.cs @@ -1,5 +1,6 @@ using Bit.Core; using Bit.Core.Context; +using Bit.Core.Settings; using Bit.Core.Utilities; using Bit.Portal.Utilities; using Microsoft.AspNetCore.Builder; diff --git a/bitwarden_license/src/Portal/Utilities/EnterprisePortalCurrentContextMiddleware.cs b/bitwarden_license/src/Portal/Utilities/EnterprisePortalCurrentContextMiddleware.cs index 51d3b74bad..c84417cf92 100644 --- a/bitwarden_license/src/Portal/Utilities/EnterprisePortalCurrentContextMiddleware.cs +++ b/bitwarden_license/src/Portal/Utilities/EnterprisePortalCurrentContextMiddleware.cs @@ -1,4 +1,5 @@ using Bit.Core; +using Bit.Core.Settings; using Microsoft.AspNetCore.Http; using System.Threading.Tasks; diff --git a/bitwarden_license/src/Sso/Startup.cs b/bitwarden_license/src/Sso/Startup.cs index 06ebae65da..5678dace21 100644 --- a/bitwarden_license/src/Sso/Startup.cs +++ b/bitwarden_license/src/Sso/Startup.cs @@ -1,6 +1,7 @@ using System; using Bit.Core; using Bit.Core.Context; +using Bit.Core.Settings; using Bit.Core.Utilities; using Bit.Sso.Utilities; using IdentityServer4.Extensions; diff --git a/bitwarden_license/src/Sso/Utilities/DiscoveryResponseGenerator.cs b/bitwarden_license/src/Sso/Utilities/DiscoveryResponseGenerator.cs index 357c800f9f..2aecd6f13f 100644 --- a/bitwarden_license/src/Sso/Utilities/DiscoveryResponseGenerator.cs +++ b/bitwarden_license/src/Sso/Utilities/DiscoveryResponseGenerator.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Bit.Core; +using Bit.Core.Settings; using Bit.Core.Utilities; using IdentityServer4.Configuration; using IdentityServer4.Services; diff --git a/bitwarden_license/src/Sso/Utilities/DynamicAuthenticationSchemeProvider.cs b/bitwarden_license/src/Sso/Utilities/DynamicAuthenticationSchemeProvider.cs index 22d69b8ac7..623e2dee37 100644 --- a/bitwarden_license/src/Sso/Utilities/DynamicAuthenticationSchemeProvider.cs +++ b/bitwarden_license/src/Sso/Utilities/DynamicAuthenticationSchemeProvider.cs @@ -9,8 +9,8 @@ using Bit.Core.Enums; using Bit.Core.Models.Data; using Bit.Core.Models.Table; using Bit.Core.Repositories; -using Bit.Core.Sso; using Bit.Core.Utilities; +using Bit.Core.Settings; using Bit.Sso.Models; using Bit.Sso.Utilities; using IdentityModel; diff --git a/bitwarden_license/src/Sso/Utilities/ServiceCollectionExtensions.cs b/bitwarden_license/src/Sso/Utilities/ServiceCollectionExtensions.cs index 12a438bb1e..008be4feae 100644 --- a/bitwarden_license/src/Sso/Utilities/ServiceCollectionExtensions.cs +++ b/bitwarden_license/src/Sso/Utilities/ServiceCollectionExtensions.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; -using Bit.Core; using Bit.Core.Business.Sso; using Bit.Core.IdentityServer; using Bit.Core.Utilities; +using Bit.Core.Settings; using Bit.Sso.Models; using IdentityServer4.Models; using IdentityServer4.ResponseHandling; diff --git a/src/Admin/Controllers/HomeController.cs b/src/Admin/Controllers/HomeController.cs index dc8f615da8..8a129c6a23 100644 --- a/src/Admin/Controllers/HomeController.cs +++ b/src/Admin/Controllers/HomeController.cs @@ -3,7 +3,7 @@ using System.Diagnostics; using Microsoft.AspNetCore.Mvc; using Bit.Admin.Models; using Microsoft.AspNetCore.Authorization; -using Bit.Core; +using Bit.Core.Settings; using System.Net.Http; using System.Threading.Tasks; using Newtonsoft.Json.Linq; diff --git a/src/Admin/Controllers/LogsController.cs b/src/Admin/Controllers/LogsController.cs index b33dc48ab4..5ba80365a8 100644 --- a/src/Admin/Controllers/LogsController.cs +++ b/src/Admin/Controllers/LogsController.cs @@ -2,7 +2,7 @@ using System.Linq; using System.Threading.Tasks; using Bit.Admin.Models; -using Bit.Core; +using Bit.Core.Settings; using Bit.Core.Utilities; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/src/Admin/Controllers/OrganizationsController.cs b/src/Admin/Controllers/OrganizationsController.cs index 2014fc000d..e8a817c9cb 100644 --- a/src/Admin/Controllers/OrganizationsController.cs +++ b/src/Admin/Controllers/OrganizationsController.cs @@ -6,9 +6,9 @@ using System.Threading.Tasks; using Bit.Admin.Models; using System.Collections.Generic; using Bit.Core.Models.Table; -using Bit.Core; using Bit.Core.Utilities; using Bit.Core.Services; +using Bit.Core.Settings; namespace Bit.Admin.Controllers { diff --git a/src/Admin/Controllers/ToolsController.cs b/src/Admin/Controllers/ToolsController.cs index 49082f0d37..95497fecf1 100644 --- a/src/Admin/Controllers/ToolsController.cs +++ b/src/Admin/Controllers/ToolsController.cs @@ -9,6 +9,7 @@ using Bit.Core; using Bit.Core.Models.Table; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using Bit.Core.Utilities; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; diff --git a/src/Admin/Controllers/UsersController.cs b/src/Admin/Controllers/UsersController.cs index 19043030cd..08f2ae7651 100644 --- a/src/Admin/Controllers/UsersController.cs +++ b/src/Admin/Controllers/UsersController.cs @@ -6,9 +6,9 @@ using System.Threading.Tasks; using Bit.Admin.Models; using System.Collections.Generic; using Bit.Core.Models.Table; -using Bit.Core; using Bit.Core.Utilities; using Bit.Core.Services; +using Bit.Core.Settings; namespace Bit.Admin.Controllers { diff --git a/src/Admin/HostedServices/AmazonSqsBlockIpHostedService.cs b/src/Admin/HostedServices/AmazonSqsBlockIpHostedService.cs index bf037d1434..3211008bca 100644 --- a/src/Admin/HostedServices/AmazonSqsBlockIpHostedService.cs +++ b/src/Admin/HostedServices/AmazonSqsBlockIpHostedService.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using Amazon; using Amazon.SQS; using Amazon.SQS.Model; -using Bit.Core; +using Bit.Core.Settings; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; diff --git a/src/Admin/HostedServices/AzureQueueBlockIpHostedService.cs b/src/Admin/HostedServices/AzureQueueBlockIpHostedService.cs index 57ca20d464..f7e11ba4a1 100644 --- a/src/Admin/HostedServices/AzureQueueBlockIpHostedService.cs +++ b/src/Admin/HostedServices/AzureQueueBlockIpHostedService.cs @@ -2,7 +2,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Bit.Core; +using Bit.Core.Settings; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Azure.Storage.Queues; diff --git a/src/Admin/HostedServices/BlockIpHostedService.cs b/src/Admin/HostedServices/BlockIpHostedService.cs index 22f6ea0575..09dcac3529 100644 --- a/src/Admin/HostedServices/BlockIpHostedService.cs +++ b/src/Admin/HostedServices/BlockIpHostedService.cs @@ -4,7 +4,7 @@ using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; -using Bit.Core; +using Bit.Core.Settings; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; diff --git a/src/Admin/HostedServices/DatabaseMigrationHostedService.cs b/src/Admin/HostedServices/DatabaseMigrationHostedService.cs index d40adcbfbf..4c3cb2610d 100644 --- a/src/Admin/HostedServices/DatabaseMigrationHostedService.cs +++ b/src/Admin/HostedServices/DatabaseMigrationHostedService.cs @@ -2,8 +2,8 @@ using System.Data.SqlClient; using System.Threading; using System.Threading.Tasks; -using Bit.Core; using Bit.Core.Jobs; +using Bit.Core.Settings; using Bit.Migrator; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; diff --git a/src/Admin/Jobs/AliveJob.cs b/src/Admin/Jobs/AliveJob.cs index cd7ca344b1..65b19c3f1d 100644 --- a/src/Admin/Jobs/AliveJob.cs +++ b/src/Admin/Jobs/AliveJob.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Bit.Core; using Bit.Core.Jobs; +using Bit.Core.Settings; using Microsoft.Extensions.Logging; using Quartz; diff --git a/src/Admin/Jobs/JobsHostedService.cs b/src/Admin/Jobs/JobsHostedService.cs index eee24f52b8..72bf1d395e 100644 --- a/src/Admin/Jobs/JobsHostedService.cs +++ b/src/Admin/Jobs/JobsHostedService.cs @@ -3,8 +3,8 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; -using Bit.Core; using Bit.Core.Jobs; +using Bit.Core.Settings; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Quartz; diff --git a/src/Admin/Models/HomeModel.cs b/src/Admin/Models/HomeModel.cs index d0c1d6bf29..b5887e4025 100644 --- a/src/Admin/Models/HomeModel.cs +++ b/src/Admin/Models/HomeModel.cs @@ -1,5 +1,5 @@ using System; -using Bit.Core; +using Bit.Core.Settings; namespace Bit.Admin.Models { diff --git a/src/Admin/Models/OrganizationEditModel.cs b/src/Admin/Models/OrganizationEditModel.cs index 7f32f86e68..5fe5e80fc1 100644 --- a/src/Admin/Models/OrganizationEditModel.cs +++ b/src/Admin/Models/OrganizationEditModel.cs @@ -1,12 +1,12 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using Bit.Core; using Bit.Core.Enums; using Bit.Core.Models.Business; using Bit.Core.Models.Data; using Bit.Core.Models.Table; using Bit.Core.Utilities; +using Bit.Core.Settings; namespace Bit.Admin.Models { diff --git a/src/Admin/Models/UserEditModel.cs b/src/Admin/Models/UserEditModel.cs index 036ad31976..624e0cb8c7 100644 --- a/src/Admin/Models/UserEditModel.cs +++ b/src/Admin/Models/UserEditModel.cs @@ -1,10 +1,10 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using Bit.Core; using Bit.Core.Models.Business; using Bit.Core.Models.Table; using Bit.Core.Utilities; +using Bit.Core.Settings; namespace Bit.Admin.Models { diff --git a/src/Admin/Startup.cs b/src/Admin/Startup.cs index 6d141c8b17..3802745862 100644 --- a/src/Admin/Startup.cs +++ b/src/Admin/Startup.cs @@ -1,8 +1,8 @@ using System; using System.Globalization; -using Bit.Core; using Bit.Core.Context; using Bit.Core.Identity; +using Bit.Core.Settings; using Bit.Core.Utilities; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; diff --git a/src/Admin/Views/Shared/_Layout.cshtml b/src/Admin/Views/Shared/_Layout.cshtml index cf56fafa65..635ab4bc43 100644 --- a/src/Admin/Views/Shared/_Layout.cshtml +++ b/src/Admin/Views/Shared/_Layout.cshtml @@ -1,5 +1,5 @@ @inject SignInManager SignInManager -@inject Bit.Core.GlobalSettings GlobalSettings +@inject Bit.Core.Settings.GlobalSettings GlobalSettings diff --git a/src/Api/Controllers/AccountsController.cs b/src/Api/Controllers/AccountsController.cs index 9dd1dc6598..dac1a70b59 100644 --- a/src/Api/Controllers/AccountsController.cs +++ b/src/Api/Controllers/AccountsController.cs @@ -9,6 +9,7 @@ using Bit.Core.Models.Data; using Bit.Core.Models.Table; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using Bit.Core.Utilities; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/src/Api/Controllers/CiphersController.cs b/src/Api/Controllers/CiphersController.cs index 713ef65956..27ee078d95 100644 --- a/src/Api/Controllers/CiphersController.cs +++ b/src/Api/Controllers/CiphersController.cs @@ -7,12 +7,12 @@ using Microsoft.AspNetCore.Authorization; using Bit.Core.Models.Api; using Bit.Core.Exceptions; using Bit.Core.Services; -using Bit.Core; using Bit.Core.Context; using Bit.Api.Utilities; -using Bit.Core.Utilities; using System.Collections.Generic; using Bit.Core.Models.Table; +using Bit.Core.Settings; + namespace Bit.Api.Controllers { @@ -24,6 +24,7 @@ namespace Bit.Api.Controllers private readonly ICollectionCipherRepository _collectionCipherRepository; private readonly ICipherService _cipherService; private readonly IUserService _userService; + private readonly IAttachmentStorageService _attachmentStorageService; private readonly ICurrentContext _currentContext; private readonly GlobalSettings _globalSettings; @@ -32,6 +33,7 @@ namespace Bit.Api.Controllers ICollectionCipherRepository collectionCipherRepository, ICipherService cipherService, IUserService userService, + IAttachmentStorageService attachmentStorageService, ICurrentContext currentContext, GlobalSettings globalSettings) { @@ -39,6 +41,7 @@ namespace Bit.Api.Controllers _collectionCipherRepository = collectionCipherRepository; _cipherService = cipherService; _userService = userService; + _attachmentStorageService = attachmentStorageService; _currentContext = currentContext; _globalSettings = globalSettings; } @@ -608,6 +611,27 @@ namespace Bit.Api.Controllers return new CipherMiniResponseModel(cipher, _globalSettings, cipher.OrganizationUseTotp); } + [HttpGet("{id}/attachment/{attachmentId}")] + public async Task GetAttachmentData(string id, string attachmentId) + { + var userId = _userService.GetProperUserId(User).Value; + var cipher = await _cipherRepository.GetByIdAsync(new Guid(id), userId); + var attachments = cipher.GetAttachments(); + + if (!attachments.ContainsKey(attachmentId)) + { + throw new NotFoundException(); + } + + var data = attachments[attachmentId]; + var response = new AttachmentResponseModel(attachmentId, data, cipher, _globalSettings) + { + Url = await _attachmentStorageService.GetAttachmentDownloadUrlAsync(cipher, data) + }; + + return response; + } + [HttpPost("{id}/attachment/{attachmentId}/share")] [RequestSizeLimit(105_906_176)] [DisableFormValueModelBinding] diff --git a/src/Api/Controllers/HibpController.cs b/src/Api/Controllers/HibpController.cs index ba00493a06..5616c0ac39 100644 --- a/src/Api/Controllers/HibpController.cs +++ b/src/Api/Controllers/HibpController.cs @@ -5,12 +5,12 @@ using Microsoft.AspNetCore.Authorization; using System.Net.Http; using System.Security.Cryptography; using Bit.Core.Services; -using Bit.Core; using Bit.Core.Context; using System.Net; using Bit.Core.Exceptions; using System.Linq; using Bit.Core.Utilities; +using Bit.Core.Settings; namespace Bit.Api.Controllers { diff --git a/src/Api/Controllers/MiscController.cs b/src/Api/Controllers/MiscController.cs index 9d17a16378..c3ee2efa7b 100644 --- a/src/Api/Controllers/MiscController.cs +++ b/src/Api/Controllers/MiscController.cs @@ -4,7 +4,7 @@ using Bit.Core.Models.Api; using System.Threading.Tasks; using Bit.Core.Utilities; using Microsoft.AspNetCore.Authorization; -using Bit.Core; +using Bit.Core.Settings; using Stripe; using System.Linq; using System.Collections.Generic; diff --git a/src/Api/Controllers/OrganizationsController.cs b/src/Api/Controllers/OrganizationsController.cs index 5afa994a1b..f4af7d6813 100644 --- a/src/Api/Controllers/OrganizationsController.cs +++ b/src/Api/Controllers/OrganizationsController.cs @@ -8,11 +8,11 @@ using Bit.Core.Enums; using Bit.Core.Models.Api; using Bit.Core.Exceptions; using Bit.Core.Services; -using Bit.Core; using Bit.Core.Context; using Bit.Api.Utilities; using Bit.Core.Models.Business; using Bit.Core.Utilities; +using Bit.Core.Settings; namespace Bit.Api.Controllers { diff --git a/src/Api/Controllers/PoliciesController.cs b/src/Api/Controllers/PoliciesController.cs index 405837f7d1..f6ebbf606b 100644 --- a/src/Api/Controllers/PoliciesController.cs +++ b/src/Api/Controllers/PoliciesController.cs @@ -7,10 +7,10 @@ using Microsoft.AspNetCore.Authorization; using Bit.Core.Models.Api; using Bit.Core.Exceptions; using Bit.Core.Services; -using Bit.Core; using Bit.Core.Context; using Bit.Core.Enums; using Bit.Core.Utilities; +using Bit.Core.Settings; using Microsoft.AspNetCore.DataProtection; namespace Bit.Api.Controllers diff --git a/src/Api/Controllers/PushController.cs b/src/Api/Controllers/PushController.cs index d7ee5e6d24..1e26fff848 100644 --- a/src/Api/Controllers/PushController.cs +++ b/src/Api/Controllers/PushController.cs @@ -10,6 +10,7 @@ using System.Linq; using Microsoft.AspNetCore.Hosting; using Bit.Api.Utilities; using Bit.Core.Utilities; +using Bit.Core.Settings; using Microsoft.Extensions.Hosting; namespace Bit.Api.Controllers diff --git a/src/Api/Controllers/SendsController.cs b/src/Api/Controllers/SendsController.cs index bff880058f..51c01c698d 100644 --- a/src/Api/Controllers/SendsController.cs +++ b/src/Api/Controllers/SendsController.cs @@ -7,10 +7,10 @@ using Microsoft.AspNetCore.Authorization; using Bit.Core.Models.Api; using Bit.Core.Exceptions; using Bit.Core.Services; -using Bit.Core; using Bit.Api.Utilities; using Bit.Core.Models.Table; using Bit.Core.Utilities; +using Bit.Core.Settings; namespace Bit.Api.Controllers { diff --git a/src/Api/Controllers/SyncController.cs b/src/Api/Controllers/SyncController.cs index 259aad21da..5dbcd372af 100644 --- a/src/Api/Controllers/SyncController.cs +++ b/src/Api/Controllers/SyncController.cs @@ -5,13 +5,13 @@ using Microsoft.AspNetCore.Mvc; using Bit.Core.Models.Api; using Bit.Core.Services; using Bit.Core.Repositories; -using Bit.Core; using Bit.Core.Enums; using Bit.Core.Exceptions; using System.Linq; using Bit.Core.Models.Table; using System.Collections.Generic; using Bit.Core.Models.Data; +using Bit.Core.Settings; namespace Bit.Api.Controllers { diff --git a/src/Api/Controllers/TwoFactorController.cs b/src/Api/Controllers/TwoFactorController.cs index e9b93feaa2..5f59be9f03 100644 --- a/src/Api/Controllers/TwoFactorController.cs +++ b/src/Api/Controllers/TwoFactorController.cs @@ -9,11 +9,11 @@ using Microsoft.AspNetCore.Identity; using Bit.Core.Models.Table; using Bit.Core.Enums; using System.Linq; -using Bit.Core; using Bit.Core.Context; using Bit.Core.Repositories; using Bit.Core.Utilities; using Bit.Core.Utilities.Duo; +using Bit.Core.Settings; namespace Bit.Api.Controllers { diff --git a/src/Api/Jobs/JobsHostedService.cs b/src/Api/Jobs/JobsHostedService.cs index aba60a55b4..06d1d4dad9 100644 --- a/src/Api/Jobs/JobsHostedService.cs +++ b/src/Api/Jobs/JobsHostedService.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Bit.Core; using Bit.Core.Jobs; +using Bit.Core.Settings; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Quartz; diff --git a/src/Api/Public/Controllers/OrganizationController.cs b/src/Api/Public/Controllers/OrganizationController.cs index c2ec15878e..03d3f002ad 100644 --- a/src/Api/Public/Controllers/OrganizationController.cs +++ b/src/Api/Public/Controllers/OrganizationController.cs @@ -1,11 +1,11 @@ using System.Linq; using System.Net; using System.Threading.Tasks; -using Bit.Core; using Bit.Core.Context; using Bit.Core.Exceptions; using Bit.Core.Models.Api.Public; using Bit.Core.Services; +using Bit.Core.Settings; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/src/Api/Startup.cs b/src/Api/Startup.cs index b7b05ab046..3f298430b8 100644 --- a/src/Api/Startup.cs +++ b/src/Api/Startup.cs @@ -7,6 +7,7 @@ using Bit.Api.Utilities; using Bit.Core; using Bit.Core.Context; using Bit.Core.Identity; +using Bit.Core.Settings; using Newtonsoft.Json.Serialization; using AspNetCoreRateLimit; using Stripe; diff --git a/src/Api/Utilities/ServiceCollectionExtensions.cs b/src/Api/Utilities/ServiceCollectionExtensions.cs index 57a016125b..6ca0cf0666 100644 --- a/src/Api/Utilities/ServiceCollectionExtensions.cs +++ b/src/Api/Utilities/ServiceCollectionExtensions.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.IO; -using Bit.Core; +using Bit.Core.Settings; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; diff --git a/src/Billing/Controllers/FreshdeskController.cs b/src/Billing/Controllers/FreshdeskController.cs index 6314815c9c..2a3ec38e4c 100644 --- a/src/Billing/Controllers/FreshdeskController.cs +++ b/src/Billing/Controllers/FreshdeskController.cs @@ -12,7 +12,8 @@ using System.Reflection; using System.Text; using System.Threading.Tasks; using System.ComponentModel.DataAnnotations; -using Bit.Core; + +using Bit.Core.Settings; namespace Bit.Billing.Controllers { diff --git a/src/Billing/Controllers/StripeController.cs b/src/Billing/Controllers/StripeController.cs index ddf3c06265..e90c6c0650 100644 --- a/src/Billing/Controllers/StripeController.cs +++ b/src/Billing/Controllers/StripeController.cs @@ -1,9 +1,9 @@ -using Bit.Core; -using Bit.Core.Enums; +using Bit.Core.Enums; using Bit.Core.Models.Business; using Bit.Core.Models.Table; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using Bit.Core.Utilities; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; diff --git a/src/Billing/Jobs/JobsHostedService.cs b/src/Billing/Jobs/JobsHostedService.cs index f02515b30f..9954a0dd03 100644 --- a/src/Billing/Jobs/JobsHostedService.cs +++ b/src/Billing/Jobs/JobsHostedService.cs @@ -3,8 +3,8 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; -using Bit.Core; using Bit.Core.Jobs; +using Bit.Core.Settings; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Quartz; diff --git a/src/Billing/Startup.cs b/src/Billing/Startup.cs index 484bfdc355..f50c169af8 100644 --- a/src/Billing/Startup.cs +++ b/src/Billing/Startup.cs @@ -3,8 +3,8 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Bit.Core; using Bit.Core.Context; +using Bit.Core.Settings; using Stripe; using Bit.Core.Utilities; using Microsoft.AspNetCore.Http; diff --git a/src/Core/Context/CurrentContext.cs b/src/Core/Context/CurrentContext.cs index 9a688d9002..6033224e24 100644 --- a/src/Core/Context/CurrentContext.cs +++ b/src/Core/Context/CurrentContext.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using System.Security.Claims; using Bit.Core.Utilities; using Bit.Core.Models.Data; +using Bit.Core.Settings; namespace Bit.Core.Context { diff --git a/src/Core/Context/ICurrentContext.cs b/src/Core/Context/ICurrentContext.cs index 72455e271f..f9e10b1624 100644 --- a/src/Core/Context/ICurrentContext.cs +++ b/src/Core/Context/ICurrentContext.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Bit.Core.Enums; using Bit.Core.Models.Table; using Bit.Core.Repositories; +using Bit.Core.Settings; using Microsoft.AspNetCore.Http; namespace Bit.Core.Context diff --git a/src/Core/HostedServices/ApplicationCacheHostedService.cs b/src/Core/HostedServices/ApplicationCacheHostedService.cs index d6b9bbe866..20117f6be4 100644 --- a/src/Core/HostedServices/ApplicationCacheHostedService.cs +++ b/src/Core/HostedServices/ApplicationCacheHostedService.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Bit.Core.Enums; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using Bit.Core.Utilities; using Microsoft.Azure.ServiceBus; using Microsoft.Azure.ServiceBus.Management; diff --git a/src/Core/Identity/DuoWebTokenProvider.cs b/src/Core/Identity/DuoWebTokenProvider.cs index d2b1c4dde4..3dc1a37a2b 100644 --- a/src/Core/Identity/DuoWebTokenProvider.cs +++ b/src/Core/Identity/DuoWebTokenProvider.cs @@ -7,6 +7,7 @@ using Bit.Core.Models; using System; using Microsoft.Extensions.DependencyInjection; using Bit.Core.Services; +using Bit.Core.Settings; namespace Bit.Core.Identity { diff --git a/src/Core/Identity/OrganizationDuoWebTokenProvider.cs b/src/Core/Identity/OrganizationDuoWebTokenProvider.cs index 74ecfccd09..2153c0023d 100644 --- a/src/Core/Identity/OrganizationDuoWebTokenProvider.cs +++ b/src/Core/Identity/OrganizationDuoWebTokenProvider.cs @@ -3,6 +3,7 @@ using Bit.Core.Models.Table; using Bit.Core.Enums; using Bit.Core.Utilities.Duo; using Bit.Core.Models; +using Bit.Core.Settings; namespace Bit.Core.Identity { diff --git a/src/Core/Identity/U2fTokenProvider.cs b/src/Core/Identity/U2fTokenProvider.cs index 93162bc742..b289c8be0a 100644 --- a/src/Core/Identity/U2fTokenProvider.cs +++ b/src/Core/Identity/U2fTokenProvider.cs @@ -13,6 +13,7 @@ using U2F.Core.Exceptions; using U2F.Core.Utils; using System; using Bit.Core.Services; +using Bit.Core.Settings; using Microsoft.Extensions.DependencyInjection; namespace Bit.Core.Identity diff --git a/src/Core/Identity/UserStore.cs b/src/Core/Identity/UserStore.cs index a1125a19eb..0aa7ffcc23 100644 --- a/src/Core/Identity/UserStore.cs +++ b/src/Core/Identity/UserStore.cs @@ -6,6 +6,7 @@ using Bit.Core.Models.Table; using Bit.Core.Repositories; using Bit.Core.Services; using Bit.Core.Context; +using Bit.Core.Settings; using Microsoft.Extensions.DependencyInjection; namespace Bit.Core.Identity diff --git a/src/Core/Identity/YubicoOtpTokenProvider.cs b/src/Core/Identity/YubicoOtpTokenProvider.cs index 2aaaf484cb..249db48728 100644 --- a/src/Core/Identity/YubicoOtpTokenProvider.cs +++ b/src/Core/Identity/YubicoOtpTokenProvider.cs @@ -5,6 +5,7 @@ using Bit.Core.Enums; using YubicoDotNetClient; using System.Linq; using Bit.Core.Services; +using Bit.Core.Settings; using System; using Microsoft.Extensions.DependencyInjection; diff --git a/src/Core/IdentityServer/ApiClient.cs b/src/Core/IdentityServer/ApiClient.cs index db859de4bb..c950d3e50a 100644 --- a/src/Core/IdentityServer/ApiClient.cs +++ b/src/Core/IdentityServer/ApiClient.cs @@ -1,6 +1,7 @@ using IdentityServer4.Models; using System.Collections.Generic; using System.Linq; +using Bit.Core.Settings; namespace Bit.Core.IdentityServer { diff --git a/src/Core/IdentityServer/BaseRequestValidator.cs b/src/Core/IdentityServer/BaseRequestValidator.cs index 8920674c84..4eede6aed7 100644 --- a/src/Core/IdentityServer/BaseRequestValidator.cs +++ b/src/Core/IdentityServer/BaseRequestValidator.cs @@ -18,6 +18,7 @@ using System.Reflection; using Microsoft.Extensions.Logging; using Bit.Core.Models.Api; using Bit.Core.Context; +using Bit.Core.Settings; namespace Bit.Core.IdentityServer { diff --git a/src/Core/IdentityServer/ClientStore.cs b/src/Core/IdentityServer/ClientStore.cs index 7e8d72b13f..7bac1d9173 100644 --- a/src/Core/IdentityServer/ClientStore.cs +++ b/src/Core/IdentityServer/ClientStore.cs @@ -9,6 +9,7 @@ using IdentityModel; using Bit.Core.Utilities; using System.Security.Claims; using Bit.Core.Services; +using Bit.Core.Settings; using Bit.Core.Context; using System.Collections.ObjectModel; diff --git a/src/Core/IdentityServer/ConfigureOpenIdConnectDistributedOptions.cs b/src/Core/IdentityServer/ConfigureOpenIdConnectDistributedOptions.cs index ae10004fa8..50fa1dcfb9 100644 --- a/src/Core/IdentityServer/ConfigureOpenIdConnectDistributedOptions.cs +++ b/src/Core/IdentityServer/ConfigureOpenIdConnectDistributedOptions.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Caching.Redis; using Microsoft.Extensions.Options; +using Bit.Core.Settings; namespace Bit.Core.IdentityServer { diff --git a/src/Core/IdentityServer/CustomTokenRequestValidator.cs b/src/Core/IdentityServer/CustomTokenRequestValidator.cs index a113d5af88..e1cf85ae75 100644 --- a/src/Core/IdentityServer/CustomTokenRequestValidator.cs +++ b/src/Core/IdentityServer/CustomTokenRequestValidator.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Security.Claims; using System.Threading.Tasks; using Bit.Core.Services; +using Bit.Core.Settings; using Bit.Core.Context; using System.Linq; using Bit.Core.Identity; diff --git a/src/Core/IdentityServer/OidcIdentityClient.cs b/src/Core/IdentityServer/OidcIdentityClient.cs index 4e0aa438ce..fafe46ae89 100644 --- a/src/Core/IdentityServer/OidcIdentityClient.cs +++ b/src/Core/IdentityServer/OidcIdentityClient.cs @@ -1,6 +1,7 @@ using IdentityServer4; using IdentityServer4.Models; using System.Collections.Generic; +using Bit.Core.Settings; namespace Bit.Core.IdentityServer { diff --git a/src/Core/IdentityServer/ProfileService.cs b/src/Core/IdentityServer/ProfileService.cs index ac69fc0935..97b7672d40 100644 --- a/src/Core/IdentityServer/ProfileService.cs +++ b/src/Core/IdentityServer/ProfileService.cs @@ -10,6 +10,7 @@ using System; using IdentityModel; using Bit.Core.Utilities; using Bit.Core.Context; +using Bit.Core.Settings; namespace Bit.Core.IdentityServer { diff --git a/src/Core/IdentityServer/ResourceOwnerPasswordValidator.cs b/src/Core/IdentityServer/ResourceOwnerPasswordValidator.cs index 72c47e747c..7cea0585a8 100644 --- a/src/Core/IdentityServer/ResourceOwnerPasswordValidator.cs +++ b/src/Core/IdentityServer/ResourceOwnerPasswordValidator.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Bit.Core.Services; using Bit.Core.Identity; using Bit.Core.Context; +using Bit.Core.Settings; using Microsoft.Extensions.Logging; namespace Bit.Core.IdentityServer diff --git a/src/Core/IdentityServer/StaticClientStore.cs b/src/Core/IdentityServer/StaticClientStore.cs index 28c554f4f0..408673a088 100644 --- a/src/Core/IdentityServer/StaticClientStore.cs +++ b/src/Core/IdentityServer/StaticClientStore.cs @@ -1,6 +1,7 @@ using IdentityServer4.Models; using System.Collections.Generic; using System.Linq; +using Bit.Core.Settings; namespace Bit.Core.IdentityServer { diff --git a/src/Core/IdentityServer/VaultCorsPolicyService.cs b/src/Core/IdentityServer/VaultCorsPolicyService.cs index eaa19474a2..ba964939b9 100644 --- a/src/Core/IdentityServer/VaultCorsPolicyService.cs +++ b/src/Core/IdentityServer/VaultCorsPolicyService.cs @@ -1,6 +1,7 @@ using Bit.Core.Utilities; using IdentityServer4.Services; using System.Threading.Tasks; +using Bit.Core.Settings; namespace Bit.Core.IdentityServer { diff --git a/src/Core/Jobs/BaseJobsHostedService.cs b/src/Core/Jobs/BaseJobsHostedService.cs index 07d22f370e..64c4233ef0 100644 --- a/src/Core/Jobs/BaseJobsHostedService.cs +++ b/src/Core/Jobs/BaseJobsHostedService.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging; using Quartz; using Quartz.Impl; using Quartz.Impl.Matchers; +using Bit.Core.Settings; namespace Bit.Core.Jobs { diff --git a/src/Core/Models/Api/Request/Accounts/PremiumRequestModel.cs b/src/Core/Models/Api/Request/Accounts/PremiumRequestModel.cs index 910f56167e..dc2233bf7e 100644 --- a/src/Core/Models/Api/Request/Accounts/PremiumRequestModel.cs +++ b/src/Core/Models/Api/Request/Accounts/PremiumRequestModel.cs @@ -2,6 +2,8 @@ using System.ComponentModel.DataAnnotations; using System.Collections.Generic; using Bit.Core.Enums; +using Bit.Core.Settings; + namespace Bit.Core.Models.Api { diff --git a/src/Core/Models/Api/Request/BitPayInvoiceRequestModel.cs b/src/Core/Models/Api/Request/BitPayInvoiceRequestModel.cs index 8587e3871e..e0b6e6340d 100644 --- a/src/Core/Models/Api/Request/BitPayInvoiceRequestModel.cs +++ b/src/Core/Models/Api/Request/BitPayInvoiceRequestModel.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using Bit.Core.Settings; namespace Bit.Core.Models.Api { diff --git a/src/Core/Models/Api/Request/Organizations/OrganizationUpdateRequestModel.cs b/src/Core/Models/Api/Request/Organizations/OrganizationUpdateRequestModel.cs index 4aa510f5c1..531a33d451 100644 --- a/src/Core/Models/Api/Request/Organizations/OrganizationUpdateRequestModel.cs +++ b/src/Core/Models/Api/Request/Organizations/OrganizationUpdateRequestModel.cs @@ -1,5 +1,6 @@ using Bit.Core.Models.Data; using Bit.Core.Models.Table; +using Bit.Core.Settings; using System.ComponentModel.DataAnnotations; namespace Bit.Core.Models.Api diff --git a/src/Core/Models/Api/Response/AttachmentResponseModel.cs b/src/Core/Models/Api/Response/AttachmentResponseModel.cs index d10d96845c..4843609ff9 100644 --- a/src/Core/Models/Api/Response/AttachmentResponseModel.cs +++ b/src/Core/Models/Api/Response/AttachmentResponseModel.cs @@ -2,6 +2,7 @@ using Bit.Core.Models.Table; using System.Collections.Generic; using System.Linq; +using Bit.Core.Settings; namespace Bit.Core.Models.Api { diff --git a/src/Core/Models/Api/Response/CipherResponseModel.cs b/src/Core/Models/Api/Response/CipherResponseModel.cs index 95457d5ed3..9d7e718fc2 100644 --- a/src/Core/Models/Api/Response/CipherResponseModel.cs +++ b/src/Core/Models/Api/Response/CipherResponseModel.cs @@ -5,6 +5,7 @@ using Bit.Core.Models.Table; using System.Linq; using Newtonsoft.Json; using Bit.Core.Models.Data; +using Bit.Core.Settings; namespace Bit.Core.Models.Api { diff --git a/src/Core/Models/Api/Response/EmergencyAccessResponseModel.cs b/src/Core/Models/Api/Response/EmergencyAccessResponseModel.cs index 4545f82616..b9200b9d23 100644 --- a/src/Core/Models/Api/Response/EmergencyAccessResponseModel.cs +++ b/src/Core/Models/Api/Response/EmergencyAccessResponseModel.cs @@ -4,6 +4,7 @@ using System.Linq; using Bit.Core.Enums; using Bit.Core.Models.Data; using Bit.Core.Models.Table; +using Bit.Core.Settings; using Core.Models.Data; namespace Bit.Core.Models.Api.Response diff --git a/src/Core/Models/Api/Response/SendAccessResponseModel.cs b/src/Core/Models/Api/Response/SendAccessResponseModel.cs index a83500551d..bdcd2cc484 100644 --- a/src/Core/Models/Api/Response/SendAccessResponseModel.cs +++ b/src/Core/Models/Api/Response/SendAccessResponseModel.cs @@ -3,6 +3,7 @@ using Bit.Core.Enums; using Bit.Core.Models.Data; using Bit.Core.Models.Table; using Bit.Core.Utilities; +using Bit.Core.Settings; using Newtonsoft.Json; namespace Bit.Core.Models.Api diff --git a/src/Core/Models/Api/Response/SendResponseModel.cs b/src/Core/Models/Api/Response/SendResponseModel.cs index 91f093d30b..d23ee3af9e 100644 --- a/src/Core/Models/Api/Response/SendResponseModel.cs +++ b/src/Core/Models/Api/Response/SendResponseModel.cs @@ -3,6 +3,7 @@ using Bit.Core.Enums; using Bit.Core.Models.Data; using Bit.Core.Models.Table; using Bit.Core.Utilities; +using Bit.Core.Settings; using Newtonsoft.Json; namespace Bit.Core.Models.Api diff --git a/src/Core/Models/Api/Response/SyncResponseModel.cs b/src/Core/Models/Api/Response/SyncResponseModel.cs index 32c7674ade..c4d93729a5 100644 --- a/src/Core/Models/Api/Response/SyncResponseModel.cs +++ b/src/Core/Models/Api/Response/SyncResponseModel.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Bit.Core.Models.Data; using Bit.Core.Models.Table; +using Bit.Core.Settings; using Core.Models.Data; namespace Bit.Core.Models.Api diff --git a/src/Core/Models/Api/SendFileModel.cs b/src/Core/Models/Api/SendFileModel.cs index c37a598cc5..df64e8d36f 100644 --- a/src/Core/Models/Api/SendFileModel.cs +++ b/src/Core/Models/Api/SendFileModel.cs @@ -1,5 +1,6 @@ using Bit.Core.Models.Data; using Bit.Core.Utilities; +using Bit.Core.Settings; namespace Bit.Core.Models.Api { diff --git a/src/Core/Models/Business/OrganizationLicense.cs b/src/Core/Models/Business/OrganizationLicense.cs index 45efb6f60f..f425ec540e 100644 --- a/src/Core/Models/Business/OrganizationLicense.cs +++ b/src/Core/Models/Business/OrganizationLicense.cs @@ -1,6 +1,7 @@ using Bit.Core.Enums; using Bit.Core.Models.Table; using Bit.Core.Services; +using Bit.Core.Settings; using Newtonsoft.Json; using System; using System.Linq; diff --git a/src/Core/Models/Data/CipherAttachment.cs b/src/Core/Models/Data/CipherAttachment.cs index 03e671fa49..ea6788e05b 100644 --- a/src/Core/Models/Data/CipherAttachment.cs +++ b/src/Core/Models/Data/CipherAttachment.cs @@ -32,6 +32,12 @@ namespace Bit.Core.Models.Data public string FileName { get; set; } public string Key { get; set; } + + public string ContainerName { get; set; } = "attachments"; + + // This is stored alongside metadata as an identifier. It does not need repeating in serialization + [JsonIgnore] + public string AttachmentId { get; set; } } } } diff --git a/src/Core/Models/Data/EventMessage.cs b/src/Core/Models/Data/EventMessage.cs index 8ba5ec2037..e6f979e2d9 100644 --- a/src/Core/Models/Data/EventMessage.cs +++ b/src/Core/Models/Data/EventMessage.cs @@ -1,6 +1,7 @@ using System; using Bit.Core.Enums; using Bit.Core.Context; +using Bit.Core.Settings; namespace Bit.Core.Models.Data { diff --git a/src/Core/Models/Table/Cipher.cs b/src/Core/Models/Table/Cipher.cs index 0efa76e7f8..0eb3c6bf32 100644 --- a/src/Core/Models/Table/Cipher.cs +++ b/src/Core/Models/Table/Cipher.cs @@ -42,6 +42,10 @@ namespace Bit.Core.Models.Table try { _attachmentData = JsonConvert.DeserializeObject>(Attachments); + foreach (var kvp in _attachmentData) + { + kvp.Value.AttachmentId = kvp.Key; + } return _attachmentData; } catch diff --git a/src/Core/Repositories/PostgreSql/UserRepository.cs b/src/Core/Repositories/PostgreSql/UserRepository.cs index 02df0938e5..57a35ffb57 100644 --- a/src/Core/Repositories/PostgreSql/UserRepository.cs +++ b/src/Core/Repositories/PostgreSql/UserRepository.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading.Tasks; using Bit.Core.Models.Data; using Bit.Core.Models.Table; +using Bit.Core.Settings; using Dapper; using Npgsql; diff --git a/src/Core/Repositories/SqlServer/CipherRepository.cs b/src/Core/Repositories/SqlServer/CipherRepository.cs index 9307dc1e28..f7123a8363 100644 --- a/src/Core/Repositories/SqlServer/CipherRepository.cs +++ b/src/Core/Repositories/SqlServer/CipherRepository.cs @@ -10,6 +10,7 @@ using Core.Models.Data; using Bit.Core.Utilities; using Newtonsoft.Json; using Bit.Core.Models.Data; +using Bit.Core.Settings; namespace Bit.Core.Repositories.SqlServer { diff --git a/src/Core/Repositories/SqlServer/CollectionCipherRepository.cs b/src/Core/Repositories/SqlServer/CollectionCipherRepository.cs index 4711955604..34e9620280 100644 --- a/src/Core/Repositories/SqlServer/CollectionCipherRepository.cs +++ b/src/Core/Repositories/SqlServer/CollectionCipherRepository.cs @@ -7,6 +7,7 @@ using System.Data; using Dapper; using System.Linq; using Bit.Core.Utilities; +using Bit.Core.Settings; namespace Bit.Core.Repositories.SqlServer { diff --git a/src/Core/Repositories/SqlServer/CollectionRepository.cs b/src/Core/Repositories/SqlServer/CollectionRepository.cs index 0e9b944458..e774dbaec1 100644 --- a/src/Core/Repositories/SqlServer/CollectionRepository.cs +++ b/src/Core/Repositories/SqlServer/CollectionRepository.cs @@ -9,6 +9,7 @@ using System.Linq; using Newtonsoft.Json; using Bit.Core.Utilities; using Bit.Core.Models.Data; +using Bit.Core.Settings; namespace Bit.Core.Repositories.SqlServer { diff --git a/src/Core/Repositories/SqlServer/DeviceRepository.cs b/src/Core/Repositories/SqlServer/DeviceRepository.cs index 9301fe0711..9838dbebcc 100644 --- a/src/Core/Repositories/SqlServer/DeviceRepository.cs +++ b/src/Core/Repositories/SqlServer/DeviceRepository.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Data.SqlClient; using System.Threading.Tasks; using Bit.Core.Models.Table; +using Bit.Core.Settings; using System.Data; using Dapper; diff --git a/src/Core/Repositories/SqlServer/EmergencyAccessRepository.cs b/src/Core/Repositories/SqlServer/EmergencyAccessRepository.cs index 289ccf3635..e35b8a9f44 100644 --- a/src/Core/Repositories/SqlServer/EmergencyAccessRepository.cs +++ b/src/Core/Repositories/SqlServer/EmergencyAccessRepository.cs @@ -7,6 +7,7 @@ using Dapper; using System.Linq; using System.Collections.Generic; using Bit.Core.Models.Data; +using Bit.Core.Settings; namespace Bit.Core.Repositories.SqlServer { diff --git a/src/Core/Repositories/SqlServer/EventRepository.cs b/src/Core/Repositories/SqlServer/EventRepository.cs index 98e232f299..24ffd6d929 100644 --- a/src/Core/Repositories/SqlServer/EventRepository.cs +++ b/src/Core/Repositories/SqlServer/EventRepository.cs @@ -3,6 +3,7 @@ using Bit.Core.Models.Table; using System.Threading.Tasks; using System.Collections.Generic; using Bit.Core.Models.Data; +using Bit.Core.Settings; using System.Data.SqlClient; using System.Linq; using System.Data; diff --git a/src/Core/Repositories/SqlServer/FolderRepository.cs b/src/Core/Repositories/SqlServer/FolderRepository.cs index 835e9e6e39..74634dfc6d 100644 --- a/src/Core/Repositories/SqlServer/FolderRepository.cs +++ b/src/Core/Repositories/SqlServer/FolderRepository.cs @@ -1,5 +1,6 @@ using System; using Bit.Core.Models.Table; +using Bit.Core.Settings; using System.Threading.Tasks; using System.Collections.Generic; using System.Data; diff --git a/src/Core/Repositories/SqlServer/GrantRepository.cs b/src/Core/Repositories/SqlServer/GrantRepository.cs index 39b71bb675..b725b1a02c 100644 --- a/src/Core/Repositories/SqlServer/GrantRepository.cs +++ b/src/Core/Repositories/SqlServer/GrantRepository.cs @@ -4,6 +4,7 @@ using System.Data.SqlClient; using System.Linq; using System.Threading.Tasks; using Bit.Core.Models.Table; +using Bit.Core.Settings; using Dapper; namespace Bit.Core.Repositories.SqlServer diff --git a/src/Core/Repositories/SqlServer/GroupRepository.cs b/src/Core/Repositories/SqlServer/GroupRepository.cs index c0b328c925..7d128c88a3 100644 --- a/src/Core/Repositories/SqlServer/GroupRepository.cs +++ b/src/Core/Repositories/SqlServer/GroupRepository.cs @@ -9,6 +9,7 @@ using System.Linq; using Newtonsoft.Json; using Bit.Core.Utilities; using Bit.Core.Models.Data; +using Bit.Core.Settings; namespace Bit.Core.Repositories.SqlServer { diff --git a/src/Core/Repositories/SqlServer/InstallationRepository.cs b/src/Core/Repositories/SqlServer/InstallationRepository.cs index ed86b0bcc3..2cd8ad83f6 100644 --- a/src/Core/Repositories/SqlServer/InstallationRepository.cs +++ b/src/Core/Repositories/SqlServer/InstallationRepository.cs @@ -1,5 +1,6 @@ using System; using Bit.Core.Models.Table; +using Bit.Core.Settings; namespace Bit.Core.Repositories.SqlServer { diff --git a/src/Core/Repositories/SqlServer/MaintenanceRepository.cs b/src/Core/Repositories/SqlServer/MaintenanceRepository.cs index fd0c2154d6..dec3444ecb 100644 --- a/src/Core/Repositories/SqlServer/MaintenanceRepository.cs +++ b/src/Core/Repositories/SqlServer/MaintenanceRepository.cs @@ -2,6 +2,7 @@ using System.Data.SqlClient; using System.Threading.Tasks; using Dapper; +using Bit.Core.Settings; namespace Bit.Core.Repositories.SqlServer { diff --git a/src/Core/Repositories/SqlServer/OrganizationRepository.cs b/src/Core/Repositories/SqlServer/OrganizationRepository.cs index 83dd3ef316..84c882ad91 100644 --- a/src/Core/Repositories/SqlServer/OrganizationRepository.cs +++ b/src/Core/Repositories/SqlServer/OrganizationRepository.cs @@ -7,6 +7,7 @@ using Dapper; using System.Linq; using System.Collections.Generic; using Bit.Core.Models.Data; +using Bit.Core.Settings; namespace Bit.Core.Repositories.SqlServer { diff --git a/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs b/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs index 1fa94027af..83d43991f5 100644 --- a/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs +++ b/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs @@ -9,6 +9,7 @@ using Bit.Core.Models.Data; using System.Collections.Generic; using Bit.Core.Enums; using Bit.Core.Utilities; +using Bit.Core.Settings; using Newtonsoft.Json; namespace Bit.Core.Repositories.SqlServer diff --git a/src/Core/Repositories/SqlServer/PolicyRepository.cs b/src/Core/Repositories/SqlServer/PolicyRepository.cs index 245656bb81..acde732cc7 100644 --- a/src/Core/Repositories/SqlServer/PolicyRepository.cs +++ b/src/Core/Repositories/SqlServer/PolicyRepository.cs @@ -7,6 +7,7 @@ using System.Data; using Dapper; using System.Linq; using Bit.Core.Enums; +using Bit.Core.Settings; namespace Bit.Core.Repositories.SqlServer { diff --git a/src/Core/Repositories/SqlServer/SendRepository.cs b/src/Core/Repositories/SqlServer/SendRepository.cs index 6300ff7f35..7e61f60407 100644 --- a/src/Core/Repositories/SqlServer/SendRepository.cs +++ b/src/Core/Repositories/SqlServer/SendRepository.cs @@ -1,5 +1,6 @@ using System; using Bit.Core.Models.Table; +using Bit.Core.Settings; using System.Threading.Tasks; using System.Collections.Generic; using System.Data; diff --git a/src/Core/Repositories/SqlServer/SsoConfigRepository.cs b/src/Core/Repositories/SqlServer/SsoConfigRepository.cs index 50084297fc..a9319774b4 100644 --- a/src/Core/Repositories/SqlServer/SsoConfigRepository.cs +++ b/src/Core/Repositories/SqlServer/SsoConfigRepository.cs @@ -1,5 +1,6 @@ using System; using Bit.Core.Models.Table; +using Bit.Core.Settings; using System.Threading.Tasks; using System.Data.SqlClient; using System.Data; diff --git a/src/Core/Repositories/SqlServer/SsoUserRepository.cs b/src/Core/Repositories/SqlServer/SsoUserRepository.cs index 5aff5a78a1..8ce559355a 100644 --- a/src/Core/Repositories/SqlServer/SsoUserRepository.cs +++ b/src/Core/Repositories/SqlServer/SsoUserRepository.cs @@ -1,4 +1,5 @@ using Bit.Core.Models.Table; +using Bit.Core.Settings; using Dapper; using System; using System.Threading.Tasks; diff --git a/src/Core/Repositories/SqlServer/TaxRateRepository.cs b/src/Core/Repositories/SqlServer/TaxRateRepository.cs index c9e03bf67d..552b7dd2e4 100644 --- a/src/Core/Repositories/SqlServer/TaxRateRepository.cs +++ b/src/Core/Repositories/SqlServer/TaxRateRepository.cs @@ -1,4 +1,5 @@ using Bit.Core.Models.Table; +using Bit.Core.Settings; using System.Threading.Tasks; using System.Collections.Generic; using System.Data; diff --git a/src/Core/Repositories/SqlServer/TransactionRepository.cs b/src/Core/Repositories/SqlServer/TransactionRepository.cs index 90ba4af2fc..4f0828758d 100644 --- a/src/Core/Repositories/SqlServer/TransactionRepository.cs +++ b/src/Core/Repositories/SqlServer/TransactionRepository.cs @@ -7,6 +7,7 @@ using System.Data; using System.Data.SqlClient; using System.Linq; using Bit.Core.Enums; +using Bit.Core.Settings; namespace Bit.Core.Repositories.SqlServer { diff --git a/src/Core/Repositories/SqlServer/U2fRepository.cs b/src/Core/Repositories/SqlServer/U2fRepository.cs index 3d8ea7f69b..591a299137 100644 --- a/src/Core/Repositories/SqlServer/U2fRepository.cs +++ b/src/Core/Repositories/SqlServer/U2fRepository.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Data.SqlClient; using System.Threading.Tasks; using Bit.Core.Models.Table; +using Bit.Core.Settings; using System.Data; using Dapper; diff --git a/src/Core/Repositories/SqlServer/UserRepository.cs b/src/Core/Repositories/SqlServer/UserRepository.cs index e02c11e59e..6ccbe5a71b 100644 --- a/src/Core/Repositories/SqlServer/UserRepository.cs +++ b/src/Core/Repositories/SqlServer/UserRepository.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading.Tasks; using Bit.Core.Models.Data; using Bit.Core.Models.Table; +using Bit.Core.Settings; using Dapper; namespace Bit.Core.Repositories.SqlServer diff --git a/src/Core/Repositories/TableStorage/EventRepository.cs b/src/Core/Repositories/TableStorage/EventRepository.cs index 49d87d2c6d..f7c168a3a8 100644 --- a/src/Core/Repositories/TableStorage/EventRepository.cs +++ b/src/Core/Repositories/TableStorage/EventRepository.cs @@ -6,6 +6,7 @@ using Bit.Core.Models.Data; using Bit.Core.Models.Table; using Bit.Core.Utilities; using Microsoft.Azure.Cosmos.Table; +using Bit.Core.Settings; namespace Bit.Core.Repositories.TableStorage { diff --git a/src/Core/Repositories/TableStorage/InstallationDeviceRepository.cs b/src/Core/Repositories/TableStorage/InstallationDeviceRepository.cs index 0e7ea6c09c..81b1632735 100644 --- a/src/Core/Repositories/TableStorage/InstallationDeviceRepository.cs +++ b/src/Core/Repositories/TableStorage/InstallationDeviceRepository.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Net; using System.Threading.Tasks; using Bit.Core.Models.Data; +using Bit.Core.Settings; using Microsoft.Azure.Cosmos.Table; namespace Bit.Core.Repositories.TableStorage diff --git a/src/Core/Repositories/TableStorage/MetaDataRepository.cs b/src/Core/Repositories/TableStorage/MetaDataRepository.cs index 4c083b93f9..64f3cd23fd 100644 --- a/src/Core/Repositories/TableStorage/MetaDataRepository.cs +++ b/src/Core/Repositories/TableStorage/MetaDataRepository.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Net; using System.Threading.Tasks; using Bit.Core.Models.Data; +using Bit.Core.Settings; using Microsoft.Azure.Cosmos.Table; namespace Bit.Core.Repositories.TableStorage diff --git a/src/Core/Services/IAttachmentStorageService.cs b/src/Core/Services/IAttachmentStorageService.cs index cd5183b8ed..6dbe0b4fe3 100644 --- a/src/Core/Services/IAttachmentStorageService.cs +++ b/src/Core/Services/IAttachmentStorageService.cs @@ -1,4 +1,5 @@ -using Bit.Core.Models.Table; +using Bit.Core.Models.Data; +using Bit.Core.Models.Table; using System; using System.IO; using System.Threading.Tasks; @@ -7,14 +8,15 @@ namespace Bit.Core.Services { public interface IAttachmentStorageService { - Task UploadNewAttachmentAsync(Stream stream, Cipher cipher, string attachmentId); - Task UploadShareAttachmentAsync(Stream stream, Guid cipherId, Guid organizationId, string attachmentId); - Task StartShareAttachmentAsync(Guid cipherId, Guid organizationId, string attachmentId); - Task RollbackShareAttachmentAsync(Guid cipherId, Guid organizationId, string attachmentId); + Task UploadNewAttachmentAsync(Stream stream, Cipher cipher, CipherAttachment.MetaData attachment); + Task UploadShareAttachmentAsync(Stream stream, Guid cipherId, Guid organizationId, CipherAttachment.MetaData attachment); + Task StartShareAttachmentAsync(Guid cipherId, Guid organizationId, CipherAttachment.MetaData attachmentData); + Task RollbackShareAttachmentAsync(Guid cipherId, Guid organizationId, CipherAttachment.MetaData attachmentData, string originalContainer); Task CleanupAsync(Guid cipherId); - Task DeleteAttachmentAsync(Guid cipherId, string attachmentId); + Task DeleteAttachmentAsync(Guid cipherId, CipherAttachment.MetaData attachment); Task DeleteAttachmentsForCipherAsync(Guid cipherId); Task DeleteAttachmentsForOrganizationAsync(Guid organizationId); Task DeleteAttachmentsForUserAsync(Guid userId); + Task GetAttachmentDownloadUrlAsync(Cipher cipher, CipherAttachment.MetaData attachmentData); } } diff --git a/src/Core/Services/Implementations/AmazonSesMailDeliveryService.cs b/src/Core/Services/Implementations/AmazonSesMailDeliveryService.cs index c4222d3c83..75d98c633c 100644 --- a/src/Core/Services/Implementations/AmazonSesMailDeliveryService.cs +++ b/src/Core/Services/Implementations/AmazonSesMailDeliveryService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Bit.Core.Models.Mail; +using Bit.Core.Settings; using System.Linq; using Amazon.SimpleEmail; using Amazon; diff --git a/src/Core/Services/Implementations/AmazonSqsBlockIpService.cs b/src/Core/Services/Implementations/AmazonSqsBlockIpService.cs index 6a6fe6dfda..f1ba51ca73 100644 --- a/src/Core/Services/Implementations/AmazonSqsBlockIpService.cs +++ b/src/Core/Services/Implementations/AmazonSqsBlockIpService.cs @@ -2,6 +2,7 @@ using System; using Amazon.SQS; using Amazon; +using Bit.Core.Settings; namespace Bit.Core.Services { diff --git a/src/Core/Services/Implementations/AppleIapService.cs b/src/Core/Services/Implementations/AppleIapService.cs index 8f460c0a4e..23a3dc0c34 100644 --- a/src/Core/Services/Implementations/AppleIapService.cs +++ b/src/Core/Services/Implementations/AppleIapService.cs @@ -5,6 +5,7 @@ using System.Net.Http; using System.Threading.Tasks; using Bit.Billing.Models; using Bit.Core.Repositories; +using Bit.Core.Settings; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; diff --git a/src/Core/Services/Implementations/AzureAttachmentStorageService.cs b/src/Core/Services/Implementations/AzureAttachmentStorageService.cs index 5ad473566f..f84454f270 100644 --- a/src/Core/Services/Implementations/AzureAttachmentStorageService.cs +++ b/src/Core/Services/Implementations/AzureAttachmentStorageService.cs @@ -1,18 +1,22 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Microsoft.Azure.Storage; using Microsoft.Azure.Storage.Blob; using System.IO; using System; +using Bit.Core.Models.Data; using Bit.Core.Models.Table; +using Bit.Core.Settings; +using System.Collections.Generic; namespace Bit.Core.Services { public class AzureAttachmentStorageService : IAttachmentStorageService { - private const string AttchmentContainerName = "attachments"; - + private const string _defaultContainerName = "attachments"; + private readonly static string[] _attachmentContainerName = { "attachments", "attachments-v2" }; + private static readonly TimeSpan downloadLinkLiveTime = TimeSpan.FromMinutes(1); private readonly CloudBlobClient _blobClient; - private CloudBlobContainer _attachmentsContainer; + private readonly Dictionary _attachmentContainers = new Dictionary(); public AzureAttachmentStorageService( GlobalSettings globalSettings) @@ -21,10 +25,24 @@ namespace Bit.Core.Services _blobClient = storageAccount.CreateCloudBlobClient(); } - public async Task UploadNewAttachmentAsync(Stream stream, Cipher cipher, string attachmentId) + public async Task GetAttachmentDownloadUrlAsync(Cipher cipher, CipherAttachment.MetaData attachmentData) { - await InitAsync(); - var blob = _attachmentsContainer.GetBlockBlobReference($"{cipher.Id}/{attachmentId}"); + await InitAsync(attachmentData.ContainerName); + var blob = _attachmentContainers[attachmentData.ContainerName].GetBlockBlobReference($"{cipher.Id}/{attachmentData.AttachmentId}"); + var accessPolicy = new SharedAccessBlobPolicy() + { + SharedAccessExpiryTime = DateTime.UtcNow.Add(downloadLinkLiveTime), + Permissions = SharedAccessBlobPermissions.Read + }; + + return blob.Uri + blob.GetSharedAccessSignature(accessPolicy); + } + + public async Task UploadNewAttachmentAsync(Stream stream, Cipher cipher, CipherAttachment.MetaData attachment) + { + attachment.ContainerName = _defaultContainerName; + await InitAsync(_defaultContainerName); + var blob = _attachmentContainers[_defaultContainerName].GetBlockBlobReference($"{cipher.Id}/{attachment.AttachmentId}"); blob.Metadata.Add("cipherId", cipher.Id.ToString()); if (cipher.UserId.HasValue) { @@ -34,36 +52,38 @@ namespace Bit.Core.Services { blob.Metadata.Add("organizationId", cipher.OrganizationId.Value.ToString()); } - blob.Properties.ContentDisposition = $"attachment; filename=\"{attachmentId}\""; + blob.Properties.ContentDisposition = $"attachment; filename=\"{attachment.AttachmentId}\""; await blob.UploadFromStreamAsync(stream); } - public async Task UploadShareAttachmentAsync(Stream stream, Guid cipherId, Guid organizationId, string attachmentId) + public async Task UploadShareAttachmentAsync(Stream stream, Guid cipherId, Guid organizationId, CipherAttachment.MetaData attachmentData) { - await InitAsync(); - var blob = _attachmentsContainer.GetBlockBlobReference($"temp/{cipherId}/{organizationId}/{attachmentId}"); + attachmentData.ContainerName = _defaultContainerName; + await InitAsync(_defaultContainerName); + var blob = _attachmentContainers[_defaultContainerName].GetBlockBlobReference($"temp/{cipherId}/{organizationId}/{attachmentData.AttachmentId}"); blob.Metadata.Add("cipherId", cipherId.ToString()); blob.Metadata.Add("organizationId", organizationId.ToString()); - blob.Properties.ContentDisposition = $"attachment; filename=\"{attachmentId}\""; + blob.Properties.ContentDisposition = $"attachment; filename=\"{attachmentData.AttachmentId}\""; await blob.UploadFromStreamAsync(stream); } - public async Task StartShareAttachmentAsync(Guid cipherId, Guid organizationId, string attachmentId) + public async Task StartShareAttachmentAsync(Guid cipherId, Guid organizationId, CipherAttachment.MetaData data) { - await InitAsync(); - var source = _attachmentsContainer.GetBlockBlobReference($"temp/{cipherId}/{organizationId}/{attachmentId}"); + await InitAsync(data.ContainerName); + var source = _attachmentContainers[data.ContainerName].GetBlockBlobReference($"temp/{cipherId}/{organizationId}/{data.AttachmentId}"); if (!(await source.ExistsAsync())) { return; } - var dest = _attachmentsContainer.GetBlockBlobReference($"{cipherId}/{attachmentId}"); + await InitAsync(_defaultContainerName); + var dest = _attachmentContainers[_defaultContainerName].GetBlockBlobReference($"{cipherId}/{data.AttachmentId}"); if (!(await dest.ExistsAsync())) { return; } - var original = _attachmentsContainer.GetBlockBlobReference($"temp/{cipherId}/{attachmentId}"); + var original = _attachmentContainers[_defaultContainerName].GetBlockBlobReference($"temp/{cipherId}/{data.AttachmentId}"); await original.DeleteIfExistsAsync(); await original.StartCopyAsync(dest); @@ -71,98 +91,88 @@ namespace Bit.Core.Services await dest.StartCopyAsync(source); } - public async Task RollbackShareAttachmentAsync(Guid cipherId, Guid organizationId, string attachmentId) + public async Task RollbackShareAttachmentAsync(Guid cipherId, Guid organizationId, CipherAttachment.MetaData attachmentData, string originalContainer) { - await InitAsync(); - var source = _attachmentsContainer.GetBlockBlobReference($"temp/{cipherId}/{organizationId}/{attachmentId}"); + await InitAsync(attachmentData.ContainerName); + var source = _attachmentContainers[attachmentData.ContainerName].GetBlockBlobReference($"temp/{cipherId}/{organizationId}/{attachmentData.AttachmentId}"); await source.DeleteIfExistsAsync(); - var original = _attachmentsContainer.GetBlockBlobReference($"temp/{cipherId}/{attachmentId}"); + await InitAsync(originalContainer); + var original = _attachmentContainers[originalContainer].GetBlockBlobReference($"temp/{cipherId}/{attachmentData.AttachmentId}"); if (!(await original.ExistsAsync())) { return; } - var dest = _attachmentsContainer.GetBlockBlobReference($"{cipherId}/{attachmentId}"); + var dest = _attachmentContainers[originalContainer].GetBlockBlobReference($"{cipherId}/{attachmentData.AttachmentId}"); await dest.DeleteIfExistsAsync(); await dest.StartCopyAsync(original); await original.DeleteIfExistsAsync(); } - public async Task DeleteAttachmentAsync(Guid cipherId, string attachmentId) + public async Task DeleteAttachmentAsync(Guid cipherId, CipherAttachment.MetaData attachment) { - await InitAsync(); - var blobName = $"{cipherId}/{attachmentId}"; - var blob = _attachmentsContainer.GetBlockBlobReference(blobName); + await InitAsync(attachment.ContainerName); + var blobName = $"{cipherId}/{attachment.AttachmentId}"; + var blob = _attachmentContainers[attachment.ContainerName].GetBlockBlobReference(blobName); await blob.DeleteIfExistsAsync(); } - public async Task CleanupAsync(Guid cipherId) + private async Task DeleteAttachmentsForPathAsync(string path) { - await InitAsync(); - var segment = await _attachmentsContainer.ListBlobsSegmentedAsync($"temp/{cipherId}", true, - BlobListingDetails.None, 100, null, null, null); - - while (true) + foreach (var container in _attachmentContainerName) { - foreach (var blob in segment.Results) + await InitAsync(container); + var segment = await _attachmentContainers[container].ListBlobsSegmentedAsync(path, true, BlobListingDetails.None, 100, null, null, null); + + while (true) { - if (blob is CloudBlockBlob blockBlob) + foreach (var blob in segment.Results) { - await blockBlob.DeleteIfExistsAsync(); + if (blob is CloudBlockBlob blockBlob) + { + await blockBlob.DeleteIfExistsAsync(); + } } - } - if (segment.ContinuationToken == null) - { - break; - } + if (segment.ContinuationToken == null) + { + break; + } - segment = await _attachmentsContainer.ListBlobsSegmentedAsync(segment.ContinuationToken); + segment = await _attachmentContainers[container].ListBlobsSegmentedAsync(segment.ContinuationToken); + } } } - public async Task DeleteAttachmentsForCipherAsync(Guid cipherId) - { - await InitAsync(); - var segment = await _attachmentsContainer.ListBlobsSegmentedAsync(cipherId.ToString(), true, - BlobListingDetails.None, 100, null, null, null); - while (true) - { - foreach (var blob in segment.Results) - { - if (blob is CloudBlockBlob blockBlob) - { - await blockBlob.DeleteIfExistsAsync(); - } - } + public async Task CleanupAsync(Guid cipherId) => await DeleteAttachmentsForPathAsync($"temp/{cipherId}"); - if (segment.ContinuationToken == null) - { - break; - } - - segment = await _attachmentsContainer.ListBlobsSegmentedAsync(segment.ContinuationToken); - } - } + public async Task DeleteAttachmentsForCipherAsync(Guid cipherId) => await DeleteAttachmentsForPathAsync(cipherId.ToString()); public async Task DeleteAttachmentsForOrganizationAsync(Guid organizationId) { - await InitAsync(); + await InitAsync(_defaultContainerName); } public async Task DeleteAttachmentsForUserAsync(Guid userId) { - await InitAsync(); + await InitAsync(_defaultContainerName); } - private async Task InitAsync() + private async Task InitAsync(string containerName) { - if (_attachmentsContainer == null) + if (!_attachmentContainers.ContainsKey(containerName) || _attachmentContainers[containerName] == null) { - _attachmentsContainer = _blobClient.GetContainerReference(AttchmentContainerName); - await _attachmentsContainer.CreateIfNotExistsAsync(BlobContainerPublicAccessType.Blob, null, null); + _attachmentContainers[containerName] = _blobClient.GetContainerReference(containerName); + if (containerName == "attachments") + { + await _attachmentContainers[containerName].CreateIfNotExistsAsync(BlobContainerPublicAccessType.Blob, null, null); + } + else + { + await _attachmentContainers[containerName].CreateIfNotExistsAsync(BlobContainerPublicAccessType.Off, null, null); + } } } } diff --git a/src/Core/Services/Implementations/AzureQueueBlockIpService.cs b/src/Core/Services/Implementations/AzureQueueBlockIpService.cs index bceb6594ad..8baa67344b 100644 --- a/src/Core/Services/Implementations/AzureQueueBlockIpService.cs +++ b/src/Core/Services/Implementations/AzureQueueBlockIpService.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using System; using Azure.Storage.Queues; +using Bit.Core.Settings; namespace Bit.Core.Services { diff --git a/src/Core/Services/Implementations/AzureQueueEventWriteService.cs b/src/Core/Services/Implementations/AzureQueueEventWriteService.cs index 51be0c7571..fee106c1a6 100644 --- a/src/Core/Services/Implementations/AzureQueueEventWriteService.cs +++ b/src/Core/Services/Implementations/AzureQueueEventWriteService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Azure.Storage.Queues; using Newtonsoft.Json; using Bit.Core.Models.Data; +using Bit.Core.Settings; namespace Bit.Core.Services { diff --git a/src/Core/Services/Implementations/AzureQueuePushNotificationService.cs b/src/Core/Services/Implementations/AzureQueuePushNotificationService.cs index 390d91cade..90137a6b47 100644 --- a/src/Core/Services/Implementations/AzureQueuePushNotificationService.cs +++ b/src/Core/Services/Implementations/AzureQueuePushNotificationService.cs @@ -1,10 +1,11 @@ using System; using System.Threading.Tasks; using Bit.Core.Context; -using Bit.Core.Models.Table; using Bit.Core.Enums; -using Newtonsoft.Json; using Bit.Core.Models; +using Bit.Core.Models.Table; +using Bit.Core.Settings; +using Newtonsoft.Json; using Azure.Storage.Queues; using Microsoft.AspNetCore.Http; using System.Collections.Generic; diff --git a/src/Core/Services/Implementations/AzureQueueReferenceEventService.cs b/src/Core/Services/Implementations/AzureQueueReferenceEventService.cs index 98427080d4..740126868f 100644 --- a/src/Core/Services/Implementations/AzureQueueReferenceEventService.cs +++ b/src/Core/Services/Implementations/AzureQueueReferenceEventService.cs @@ -3,6 +3,7 @@ using System.Text; using System.Threading.Tasks; using Azure.Storage.Queues; using Bit.Core.Models.Business; +using Bit.Core.Settings; using Newtonsoft.Json; namespace Bit.Core.Services diff --git a/src/Core/Services/Implementations/AzureSendFileStorageService.cs b/src/Core/Services/Implementations/AzureSendFileStorageService.cs index 4fdc6b2e77..43691d6b3d 100644 --- a/src/Core/Services/Implementations/AzureSendFileStorageService.cs +++ b/src/Core/Services/Implementations/AzureSendFileStorageService.cs @@ -4,6 +4,7 @@ using Microsoft.Azure.Storage.Blob; using System.IO; using System; using Bit.Core.Models.Table; +using Bit.Core.Settings; namespace Bit.Core.Services { diff --git a/src/Core/Services/Implementations/CipherService.cs b/src/Core/Services/Implementations/CipherService.cs index 2ed38537c2..2ea499913b 100644 --- a/src/Core/Services/Implementations/CipherService.cs +++ b/src/Core/Services/Implementations/CipherService.cs @@ -11,6 +11,7 @@ using Newtonsoft.Json; using System.IO; using Bit.Core.Enums; using Bit.Core.Utilities; +using Bit.Core.Settings; namespace Bit.Core.Services { @@ -216,17 +217,18 @@ namespace Bit.Core.Services } var attachmentId = Utilities.CoreHelpers.SecureRandomString(32, upper: false, special: false); - await _attachmentStorageService.UploadNewAttachmentAsync(stream, cipher, attachmentId); + var data = new CipherAttachment.MetaData + { + AttachmentId = attachmentId, + FileName = fileName, + Key = key, + Size = stream.Length + }; + + await _attachmentStorageService.UploadNewAttachmentAsync(stream, cipher, data); try { - var data = new CipherAttachment.MetaData - { - FileName = fileName, - Key = key, - Size = stream.Length - }; - var attachment = new CipherAttachment { Id = cipher.Id, @@ -243,7 +245,7 @@ namespace Bit.Core.Services catch { // Clean up since this is not transactional - await _attachmentStorageService.DeleteAttachmentAsync(cipher.Id, attachmentId); + await _attachmentStorageService.DeleteAttachmentAsync(cipher.Id, data); throw; } @@ -283,8 +285,26 @@ namespace Bit.Core.Services throw new BadRequestException("Not enough storage available for this organization."); } + var attachments = cipher.GetAttachments(); + if (!attachments.ContainsKey(attachmentId)) + { + throw new BadRequestException($"Cipher does not own specified attachment"); + } + await _attachmentStorageService.UploadShareAttachmentAsync(stream, cipher.Id, organizationId, - attachmentId); + attachments[attachmentId]); + + // Previous call may alter metadata + var updatedAttachment = new CipherAttachment + { + Id = cipher.Id, + UserId = cipher.UserId, + OrganizationId = cipher.OrganizationId, + AttachmentId = attachmentId, + AttachmentData = JsonConvert.SerializeObject(attachments[attachmentId]) + }; + + await _cipherRepository.UpdateAttachmentAsync(updatedAttachment); } catch { @@ -350,9 +370,10 @@ namespace Bit.Core.Services throw new NotFoundException(); } + var data = cipher.GetAttachments()[attachmentId]; await _cipherRepository.DeleteAttachmentAsync(cipher.Id, attachmentId); cipher.DeleteAttachment(attachmentId); - await _attachmentStorageService.DeleteAttachmentAsync(cipher.Id, attachmentId); + await _attachmentStorageService.DeleteAttachmentAsync(cipher.Id, data); await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_AttachmentDeleted); // push @@ -421,6 +442,7 @@ namespace Bit.Core.Services var hasOldAttachments = attachments?.Any(a => a.Key == null) ?? false; var updatedCipher = false; var migratedAttachments = false; + var originalAttachments = CoreHelpers.CloneObject(attachments); try { @@ -471,7 +493,7 @@ namespace Bit.Core.Services foreach (var attachment in attachments.Where(a => a.Key == null)) { await _attachmentStorageService.StartShareAttachmentAsync(cipher.Id, organizationId, - attachment.Key); + attachment.Value); migratedAttachments = true; } @@ -504,7 +526,7 @@ namespace Bit.Core.Services foreach (var attachment in attachments.Where(a => a.Key == null)) { await _attachmentStorageService.RollbackShareAttachmentAsync(cipher.Id, organizationId, - attachment.Key); + attachment.Value, originalAttachments[attachment.Key].ContainerName); } await _attachmentStorageService.CleanupAsync(cipher.Id); diff --git a/src/Core/Services/Implementations/EmergencyAccessService.cs b/src/Core/Services/Implementations/EmergencyAccessService.cs index c05cea2f38..8cef3f6d76 100644 --- a/src/Core/Services/Implementations/EmergencyAccessService.cs +++ b/src/Core/Services/Implementations/EmergencyAccessService.cs @@ -10,6 +10,7 @@ using Bit.Core.Models.Data; using Bit.Core.Models.Table; using Bit.Core.Repositories; using Bit.Core.Utilities; +using Bit.Core.Settings; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Identity; diff --git a/src/Core/Services/Implementations/EventService.cs b/src/Core/Services/Implementations/EventService.cs index a1ea1cd29e..2c9be7ca1a 100644 --- a/src/Core/Services/Implementations/EventService.cs +++ b/src/Core/Services/Implementations/EventService.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Collections.Generic; using Bit.Core.Models.Table; using Bit.Core.Context; +using Bit.Core.Settings; namespace Bit.Core.Services { diff --git a/src/Core/Services/Implementations/HandlebarsMailService.cs b/src/Core/Services/Implementations/HandlebarsMailService.cs index 322c47b3c7..72ed4dba78 100644 --- a/src/Core/Services/Implementations/HandlebarsMailService.cs +++ b/src/Core/Services/Implementations/HandlebarsMailService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Bit.Core.Models.Table; using Bit.Core.Models.Mail; +using Bit.Core.Settings; using System.IO; using System.Net; using Bit.Core.Utilities; diff --git a/src/Core/Services/Implementations/InMemoryServiceBusApplicationCacheService.cs b/src/Core/Services/Implementations/InMemoryServiceBusApplicationCacheService.cs index ebf1e2f158..5df132d268 100644 --- a/src/Core/Services/Implementations/InMemoryServiceBusApplicationCacheService.cs +++ b/src/Core/Services/Implementations/InMemoryServiceBusApplicationCacheService.cs @@ -4,6 +4,7 @@ using Bit.Core.Enums; using Bit.Core.Models.Table; using Bit.Core.Repositories; using Bit.Core.Utilities; +using Bit.Core.Settings; using Microsoft.Azure.ServiceBus; namespace Bit.Core.Services diff --git a/src/Core/Services/Implementations/LicensingService.cs b/src/Core/Services/Implementations/LicensingService.cs index f663989e63..06a75fe333 100644 --- a/src/Core/Services/Implementations/LicensingService.cs +++ b/src/Core/Services/Implementations/LicensingService.cs @@ -2,6 +2,7 @@ using Bit.Core.Models.Table; using Bit.Core.Repositories; using Bit.Core.Utilities; +using Bit.Core.Settings; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Azure.Storage; diff --git a/src/Core/Services/Implementations/LocalAttachmentStorageService.cs b/src/Core/Services/Implementations/LocalAttachmentStorageService.cs index 7eb9eaf257..d02c62db6b 100644 --- a/src/Core/Services/Implementations/LocalAttachmentStorageService.cs +++ b/src/Core/Services/Implementations/LocalAttachmentStorageService.cs @@ -2,63 +2,73 @@ using System.IO; using System; using Bit.Core.Models.Table; +using Bit.Core.Models.Data; +using Bit.Core.Settings; namespace Bit.Core.Services { public class LocalAttachmentStorageService : IAttachmentStorageService { + private readonly string _baseAttachmentUrl; private readonly string _baseDirPath; private readonly string _baseTempDirPath; public LocalAttachmentStorageService( - GlobalSettings globalSettings) + IGlobalSettings globalSettings) { _baseDirPath = globalSettings.Attachment.BaseDirectory; _baseTempDirPath = $"{_baseDirPath}/temp"; + _baseAttachmentUrl = globalSettings.Attachment.BaseUrl; } - public async Task UploadNewAttachmentAsync(Stream stream, Cipher cipher, string attachmentId) + public async Task GetAttachmentDownloadUrlAsync(Cipher cipher, CipherAttachment.MetaData attachmentData) { await InitAsync(); - var cipherDirPath = $"{_baseDirPath}/{cipher.Id}"; + return $"{_baseAttachmentUrl}/{cipher.Id}/{attachmentData.AttachmentId}"; + } + + public async Task UploadNewAttachmentAsync(Stream stream, Cipher cipher, CipherAttachment.MetaData attachmentData) + { + await InitAsync(); + var cipherDirPath = CipherDirectoryPath(cipher.Id, temp: false); CreateDirectoryIfNotExists(cipherDirPath); - using (var fs = File.Create($"{cipherDirPath}/{attachmentId}")) + using (var fs = File.Create(AttachmentFilePath(cipherDirPath, attachmentData.AttachmentId))) { stream.Seek(0, SeekOrigin.Begin); await stream.CopyToAsync(fs); } } - public async Task UploadShareAttachmentAsync(Stream stream, Guid cipherId, Guid organizationId, string attachmentId) + public async Task UploadShareAttachmentAsync(Stream stream, Guid cipherId, Guid organizationId, CipherAttachment.MetaData attachmentData) { await InitAsync(); - var tempCipherOrgDirPath = $"{_baseTempDirPath}/{cipherId}/{organizationId}"; + var tempCipherOrgDirPath = OrganizationDirectoryPath(cipherId, organizationId, temp: true); CreateDirectoryIfNotExists(tempCipherOrgDirPath); - using (var fs = File.Create($"{tempCipherOrgDirPath}/{attachmentId}")) + using (var fs = File.Create(AttachmentFilePath(tempCipherOrgDirPath, attachmentData.AttachmentId))) { stream.Seek(0, SeekOrigin.Begin); await stream.CopyToAsync(fs); } } - public async Task StartShareAttachmentAsync(Guid cipherId, Guid organizationId, string attachmentId) + public async Task StartShareAttachmentAsync(Guid cipherId, Guid organizationId, CipherAttachment.MetaData attachmentData) { await InitAsync(); - var sourceFilePath = $"{_baseTempDirPath}/{cipherId}/{organizationId}/{attachmentId}"; + var sourceFilePath = AttachmentFilePath(attachmentData.AttachmentId, cipherId, organizationId, temp: true); if (!File.Exists(sourceFilePath)) { return; } - var destFilePath = $"{_baseDirPath}/{cipherId}/{attachmentId}"; + var destFilePath = AttachmentFilePath(attachmentData.AttachmentId, cipherId, temp: false); if (!File.Exists(destFilePath)) { return; } - var originalFilePath = $"{_baseTempDirPath}/{cipherId}/{attachmentId}"; + var originalFilePath = AttachmentFilePath(attachmentData.AttachmentId, cipherId, temp: true); DeleteFileIfExists(originalFilePath); File.Move(destFilePath, originalFilePath); @@ -67,40 +77,40 @@ namespace Bit.Core.Services File.Move(sourceFilePath, destFilePath); } - public async Task RollbackShareAttachmentAsync(Guid cipherId, Guid organizationId, string attachmentId) + public async Task RollbackShareAttachmentAsync(Guid cipherId, Guid organizationId, CipherAttachment.MetaData attachmentData, string originalContainer) { await InitAsync(); - DeleteFileIfExists($"{_baseTempDirPath}/{cipherId}/{organizationId}/{attachmentId}"); + DeleteFileIfExists(AttachmentFilePath(attachmentData.AttachmentId, cipherId, organizationId, temp: true)); - var originalFilePath = $"{_baseTempDirPath}/{cipherId}/{attachmentId}"; + var originalFilePath = AttachmentFilePath(attachmentData.AttachmentId, cipherId, temp: true); if (!File.Exists(originalFilePath)) { return; } - var destFilePath = $"{_baseDirPath}/{cipherId}/{attachmentId}"; + var destFilePath = AttachmentFilePath(attachmentData.AttachmentId, cipherId, temp: false); DeleteFileIfExists(destFilePath); File.Move(originalFilePath, destFilePath); DeleteFileIfExists(originalFilePath); } - public async Task DeleteAttachmentAsync(Guid cipherId, string attachmentId) + public async Task DeleteAttachmentAsync(Guid cipherId, CipherAttachment.MetaData attachmentData) { await InitAsync(); - DeleteFileIfExists($"{_baseDirPath}/{cipherId}/{attachmentId}"); + DeleteFileIfExists(AttachmentFilePath(attachmentData.AttachmentId, cipherId, temp: false)); } public async Task CleanupAsync(Guid cipherId) { await InitAsync(); - DeleteDirectoryIfExists($"{_baseTempDirPath}/{cipherId}"); + DeleteDirectoryIfExists(CipherDirectoryPath(cipherId, temp: true)); } public async Task DeleteAttachmentsForCipherAsync(Guid cipherId) { await InitAsync(); - DeleteDirectoryIfExists($"{_baseDirPath}/{cipherId}"); + DeleteDirectoryIfExists(CipherDirectoryPath(cipherId, temp: false)); } public async Task DeleteAttachmentsForOrganizationAsync(Guid organizationId) @@ -151,5 +161,18 @@ namespace Bit.Core.Services return Task.FromResult(0); } + + private string CipherDirectoryPath(Guid cipherId, bool temp = false) => + Path.Combine(temp ? _baseTempDirPath : _baseDirPath, cipherId.ToString()); + private string OrganizationDirectoryPath(Guid cipherId, Guid organizationId, bool temp = false) => + Path.Combine(temp ? _baseTempDirPath : _baseDirPath, cipherId.ToString(), organizationId.ToString()); + + private string AttachmentFilePath(string dir, string attachmentId) => Path.Combine(dir, attachmentId); + private string AttachmentFilePath(string attachmentId, Guid cipherId, Guid? organizationId = null, + bool temp = false) => + organizationId.HasValue ? + AttachmentFilePath(OrganizationDirectoryPath(cipherId, organizationId.Value, temp), attachmentId) : + AttachmentFilePath(CipherDirectoryPath(cipherId, temp), attachmentId); + } } diff --git a/src/Core/Services/Implementations/LocalSendStorageService.cs b/src/Core/Services/Implementations/LocalSendStorageService.cs index 4f481532f8..038d106543 100644 --- a/src/Core/Services/Implementations/LocalSendStorageService.cs +++ b/src/Core/Services/Implementations/LocalSendStorageService.cs @@ -2,6 +2,7 @@ using System.IO; using System; using Bit.Core.Models.Table; +using Bit.Core.Settings; namespace Bit.Core.Services { diff --git a/src/Core/Services/Implementations/MailKitSmtpMailDeliveryService.cs b/src/Core/Services/Implementations/MailKitSmtpMailDeliveryService.cs index 4a1716da89..990b00e847 100644 --- a/src/Core/Services/Implementations/MailKitSmtpMailDeliveryService.cs +++ b/src/Core/Services/Implementations/MailKitSmtpMailDeliveryService.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using Bit.Core.Utilities; +using Bit.Core.Settings; using MailKit.Net.Smtp; using Microsoft.Extensions.Logging; using MimeKit; diff --git a/src/Core/Services/Implementations/MultiServicePushNotificationService.cs b/src/Core/Services/Implementations/MultiServicePushNotificationService.cs index ffc46564c1..64b2106ccc 100644 --- a/src/Core/Services/Implementations/MultiServicePushNotificationService.cs +++ b/src/Core/Services/Implementations/MultiServicePushNotificationService.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Http; using Bit.Core.Utilities; using Microsoft.Extensions.Logging; using Bit.Core.Repositories; +using Bit.Core.Settings; namespace Bit.Core.Services { diff --git a/src/Core/Services/Implementations/NotificationHubPushNotificationService.cs b/src/Core/Services/Implementations/NotificationHubPushNotificationService.cs index 4228aa76c0..dd2ea1eb4d 100644 --- a/src/Core/Services/Implementations/NotificationHubPushNotificationService.cs +++ b/src/Core/Services/Implementations/NotificationHubPushNotificationService.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Http; using Bit.Core.Models; using Bit.Core.Models.Data; using Bit.Core.Repositories; +using Bit.Core.Settings; namespace Bit.Core.Services { diff --git a/src/Core/Services/Implementations/NotificationHubPushRegistrationService.cs b/src/Core/Services/Implementations/NotificationHubPushRegistrationService.cs index ff95cd5ad0..7b8cbdbd45 100644 --- a/src/Core/Services/Implementations/NotificationHubPushRegistrationService.cs +++ b/src/Core/Services/Implementations/NotificationHubPushRegistrationService.cs @@ -6,6 +6,7 @@ using System.Linq; using System; using Bit.Core.Models.Data; using Bit.Core.Repositories; +using Bit.Core.Settings; namespace Bit.Core.Services { diff --git a/src/Core/Services/Implementations/NotificationsApiPushNotificationService.cs b/src/Core/Services/Implementations/NotificationsApiPushNotificationService.cs index ef27aee231..2790179b4a 100644 --- a/src/Core/Services/Implementations/NotificationsApiPushNotificationService.cs +++ b/src/Core/Services/Implementations/NotificationsApiPushNotificationService.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Bit.Core.Context; using Bit.Core.Models.Table; using Bit.Core.Enums; +using Bit.Core.Settings; using Newtonsoft.Json; using Bit.Core.Models; using Microsoft.AspNetCore.Http; diff --git a/src/Core/Services/Implementations/OrganizationService.cs b/src/Core/Services/Implementations/OrganizationService.cs index 3795f4eb09..5321fc6ad0 100644 --- a/src/Core/Services/Implementations/OrganizationService.cs +++ b/src/Core/Services/Implementations/OrganizationService.cs @@ -11,6 +11,7 @@ using Microsoft.AspNetCore.DataProtection; using Stripe; using Bit.Core.Enums; using Bit.Core.Models.Data; +using Bit.Core.Settings; using System.IO; using Newtonsoft.Json; using System.Text.Json; diff --git a/src/Core/Services/Implementations/RelayPushNotificationService.cs b/src/Core/Services/Implementations/RelayPushNotificationService.cs index 966962147f..2ff284d2d0 100644 --- a/src/Core/Services/Implementations/RelayPushNotificationService.cs +++ b/src/Core/Services/Implementations/RelayPushNotificationService.cs @@ -10,6 +10,7 @@ using Bit.Core.Models.Api; using Microsoft.Extensions.Logging; using System.Collections.Generic; using Bit.Core.Repositories; +using Bit.Core.Settings; namespace Bit.Core.Services { diff --git a/src/Core/Services/Implementations/RelayPushRegistrationService.cs b/src/Core/Services/Implementations/RelayPushRegistrationService.cs index dbe160e921..4961a20bb6 100644 --- a/src/Core/Services/Implementations/RelayPushRegistrationService.cs +++ b/src/Core/Services/Implementations/RelayPushRegistrationService.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using System.Net.Http; using Bit.Core.Models.Api; using Bit.Core.Enums; +using Bit.Core.Settings; using System.Linq; using Microsoft.Extensions.Logging; diff --git a/src/Core/Services/Implementations/SendService.cs b/src/Core/Services/Implementations/SendService.cs index 4bab0f2b4b..2959261716 100644 --- a/src/Core/Services/Implementations/SendService.cs +++ b/src/Core/Services/Implementations/SendService.cs @@ -8,6 +8,7 @@ using Bit.Core.Exceptions; using Bit.Core.Models.Data; using Bit.Core.Models.Table; using Bit.Core.Repositories; +using Bit.Core.Settings; using Microsoft.AspNetCore.Identity; using Newtonsoft.Json; diff --git a/src/Core/Services/Implementations/StripePaymentService.cs b/src/Core/Services/Implementations/StripePaymentService.cs index b088b0ecd9..00044e606f 100644 --- a/src/Core/Services/Implementations/StripePaymentService.cs +++ b/src/Core/Services/Implementations/StripePaymentService.cs @@ -5,11 +5,12 @@ using Stripe; using System.Collections.Generic; using Bit.Core.Exceptions; using System.Linq; +using Bit.Billing.Models; using Bit.Core.Models.Business; using Bit.Core.Enums; using Bit.Core.Repositories; +using Bit.Core.Settings; using Microsoft.Extensions.Logging; -using Bit.Billing.Models; using StripeTaxRate = Stripe.TaxRate; using TaxRate = Bit.Core.Models.Table.TaxRate; diff --git a/src/Core/Services/Implementations/UserService.cs b/src/Core/Services/Implementations/UserService.cs index 2c05196466..d5bc06e085 100644 --- a/src/Core/Services/Implementations/UserService.cs +++ b/src/Core/Services/Implementations/UserService.cs @@ -17,6 +17,7 @@ using U2F.Core.Utils; using Bit.Core.Context; using Bit.Core.Exceptions; using Bit.Core.Utilities; +using Bit.Core.Settings; using System.IO; using Newtonsoft.Json; using Microsoft.AspNetCore.DataProtection; diff --git a/src/Core/Services/NoopImplementations/NoopAttachmentStorageService.cs b/src/Core/Services/NoopImplementations/NoopAttachmentStorageService.cs index 29f7819793..795fc6e9fd 100644 --- a/src/Core/Services/NoopImplementations/NoopAttachmentStorageService.cs +++ b/src/Core/Services/NoopImplementations/NoopAttachmentStorageService.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Threading.Tasks; +using Bit.Core.Models.Data; using Bit.Core.Models.Table; namespace Bit.Core.Services @@ -12,7 +13,7 @@ namespace Bit.Core.Services return Task.FromResult(0); } - public Task DeleteAttachmentAsync(Guid cipherId, string attachmentId) + public Task DeleteAttachmentAsync(Guid cipherId, CipherAttachment.MetaData attachmentData) { return Task.FromResult(0); } @@ -32,24 +33,30 @@ namespace Bit.Core.Services return Task.FromResult(0); } - public Task RollbackShareAttachmentAsync(Guid cipherId, Guid organizationId, string attachmentId) + public Task RollbackShareAttachmentAsync(Guid cipherId, Guid organizationId, CipherAttachment.MetaData attachmentData, string originalContainer) { return Task.FromResult(0); } - public Task StartShareAttachmentAsync(Guid cipherId, Guid organizationId, string attachmentId) + public Task StartShareAttachmentAsync(Guid cipherId, Guid organizationId, CipherAttachment.MetaData attachmentData) { return Task.FromResult(0); } - public Task UploadNewAttachmentAsync(Stream stream, Cipher cipher, string attachmentId) + public Task UploadNewAttachmentAsync(Stream stream, Cipher cipher, CipherAttachment.MetaData attachmentData) { return Task.FromResult(0); } - public Task UploadShareAttachmentAsync(Stream stream, Guid cipherId, Guid organizationId, string attachmentId) + public Task UploadShareAttachmentAsync(Stream stream, Guid cipherId, Guid organizationId, CipherAttachment.MetaData attachmentData) { return Task.FromResult(0); } + + public Task GetAttachmentDownloadUrlAsync(Cipher cipher, CipherAttachment.MetaData attachmentData) + { + return Task.FromResult((string)null); + } + } } diff --git a/src/Core/Services/NoopImplementations/NoopLicensingService.cs b/src/Core/Services/NoopImplementations/NoopLicensingService.cs index 1c645c68d7..65f8790274 100644 --- a/src/Core/Services/NoopImplementations/NoopLicensingService.cs +++ b/src/Core/Services/NoopImplementations/NoopLicensingService.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Hosting; using System; using Bit.Core.Models.Business; +using Bit.Core.Settings; using System.Threading.Tasks; using Microsoft.Extensions.Hosting; diff --git a/src/Core/GlobalSettings.cs b/src/Core/Settings/GlobalSettings.cs similarity index 97% rename from src/Core/GlobalSettings.cs rename to src/Core/Settings/GlobalSettings.cs index da2c59a77e..280728ab8d 100644 --- a/src/Core/GlobalSettings.cs +++ b/src/Core/Settings/GlobalSettings.cs @@ -1,9 +1,9 @@ using System; using Bit.Core.Enums; -namespace Bit.Core +namespace Bit.Core.Settings { - public class GlobalSettings + public class GlobalSettings : IGlobalSettings { public bool SelfHosted { get; set; } public virtual string KnownProxies { get; set; } @@ -29,7 +29,7 @@ namespace Bit.Core public virtual ConnectionStringSettings Storage { get; set; } = new ConnectionStringSettings(); public virtual ConnectionStringSettings Events { get; set; } = new ConnectionStringSettings(); public virtual NotificationsSettings Notifications { get; set; } = new NotificationsSettings(); - public virtual FileStorageSettings Attachment { get; set; } = new FileStorageSettings(); + public virtual IFileStorageSettings Attachment { get; set; } = new FileStorageSettings(); public virtual FileStorageSettings Send { get; set; } = new FileStorageSettings(); public virtual IdentityServerSettings IdentityServer { get; set; } = new IdentityServerSettings(); public virtual DataProtectionSettings DataProtection { get; set; } = new DataProtectionSettings(); @@ -112,7 +112,7 @@ namespace Bit.Core } } - public class FileStorageSettings + public class FileStorageSettings : IFileStorageSettings { private string _connectionString; diff --git a/src/Core/Settings/IFileStorageSettings.cs b/src/Core/Settings/IFileStorageSettings.cs new file mode 100644 index 0000000000..a243b265aa --- /dev/null +++ b/src/Core/Settings/IFileStorageSettings.cs @@ -0,0 +1,9 @@ +namespace Bit.Core.Settings +{ + public interface IFileStorageSettings + { + string ConnectionString { get; set; } + string BaseDirectory { get; set; } + string BaseUrl { get; set; } + } +} diff --git a/src/Core/Settings/IGlobalSettings.cs b/src/Core/Settings/IGlobalSettings.cs new file mode 100644 index 0000000000..122258b1a6 --- /dev/null +++ b/src/Core/Settings/IGlobalSettings.cs @@ -0,0 +1,8 @@ +namespace Bit.Core.Settings +{ + public interface IGlobalSettings + { + // This interface exists for testing. Add settings here as needed for testing + IFileStorageSettings Attachment { get; set; } + } +} diff --git a/src/Core/Utilities/BitPayClient.cs b/src/Core/Utilities/BitPayClient.cs index 452df0a203..a46e562099 100644 --- a/src/Core/Utilities/BitPayClient.cs +++ b/src/Core/Utilities/BitPayClient.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Bit.Core.Settings; namespace Bit.Core.Utilities { diff --git a/src/Core/Utilities/CoreHelpers.cs b/src/Core/Utilities/CoreHelpers.cs index 6aab6b7b02..17cfd3775a 100644 --- a/src/Core/Utilities/CoreHelpers.cs +++ b/src/Core/Utilities/CoreHelpers.cs @@ -14,6 +14,7 @@ using Dapper; using System.Globalization; using System.Web; using Microsoft.AspNetCore.DataProtection; +using Bit.Core.Settings; using Bit.Core.Enums; using Bit.Core.Context; using System.Threading.Tasks; diff --git a/src/Core/Utilities/CurrentContextMiddleware.cs b/src/Core/Utilities/CurrentContextMiddleware.cs index 6149ef2577..268f646750 100644 --- a/src/Core/Utilities/CurrentContextMiddleware.cs +++ b/src/Core/Utilities/CurrentContextMiddleware.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Http; using System.Threading.Tasks; using Bit.Core.Context; +using Bit.Core.Settings; namespace Bit.Core.Utilities { diff --git a/src/Core/Utilities/LoggerFactoryExtensions.cs b/src/Core/Utilities/LoggerFactoryExtensions.cs index 2d685dfd39..0298766bba 100644 --- a/src/Core/Utilities/LoggerFactoryExtensions.cs +++ b/src/Core/Utilities/LoggerFactoryExtensions.cs @@ -9,6 +9,7 @@ using Serilog.Sinks.Syslog; using System; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; +using Bit.Core.Settings; namespace Bit.Core.Utilities { diff --git a/src/Core/Utilities/SelfHostedAttribute.cs b/src/Core/Utilities/SelfHostedAttribute.cs index 3c6ff74436..41300e8e14 100644 --- a/src/Core/Utilities/SelfHostedAttribute.cs +++ b/src/Core/Utilities/SelfHostedAttribute.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.DependencyInjection; using Bit.Core.Exceptions; +using Bit.Core.Settings; namespace Bit.Core.Utilities { diff --git a/src/Core/Utilities/ServiceCollectionExtensions.cs b/src/Core/Utilities/ServiceCollectionExtensions.cs index c43a13861b..04511e248c 100644 --- a/src/Core/Utilities/ServiceCollectionExtensions.cs +++ b/src/Core/Utilities/ServiceCollectionExtensions.cs @@ -13,6 +13,7 @@ using Bit.Core.Models.Table; using Bit.Core.Repositories; using Bit.Core.Resources; using Bit.Core.Services; +using Bit.Core.Settings; using Bit.Core.Utilities; using IdentityModel; using IdentityServer4.AccessTokenValidation; @@ -422,6 +423,7 @@ namespace Bit.Core.Utilities var globalSettings = new GlobalSettings(); ConfigurationBinder.Bind(configuration.GetSection("GlobalSettings"), globalSettings); services.AddSingleton(s => globalSettings); + services.AddSingleton(); return globalSettings; } diff --git a/src/Events/Startup.cs b/src/Events/Startup.cs index 86cc26d945..c4f07b8436 100644 --- a/src/Events/Startup.cs +++ b/src/Events/Startup.cs @@ -1,7 +1,7 @@ using System.Globalization; -using Bit.Core; using Bit.Core.Context; using Bit.Core.Services; +using Bit.Core.Settings; using Bit.Core.Utilities; using IdentityModel; using Microsoft.AspNetCore.Builder; diff --git a/src/EventsProcessor/Startup.cs b/src/EventsProcessor/Startup.cs index 1fc7d5d13b..eeedd3b982 100644 --- a/src/EventsProcessor/Startup.cs +++ b/src/EventsProcessor/Startup.cs @@ -1,5 +1,5 @@ using System.Globalization; -using Bit.Core; +using Bit.Core.Settings; using Bit.Core.Utilities; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; diff --git a/src/Icons/Startup.cs b/src/Icons/Startup.cs index fed262e148..27936d2c34 100644 --- a/src/Icons/Startup.cs +++ b/src/Icons/Startup.cs @@ -1,6 +1,6 @@ using System; using System.Globalization; -using Bit.Core; +using Bit.Core.Settings; using Bit.Core.Utilities; using Bit.Icons.Services; using Microsoft.AspNetCore.Builder; diff --git a/src/Identity/Startup.cs b/src/Identity/Startup.cs index e12a21e187..a3d03b2957 100644 --- a/src/Identity/Startup.cs +++ b/src/Identity/Startup.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Configuration; using Bit.Core; using Bit.Core.Context; +using Bit.Core.Settings; using Bit.Core.Utilities; using AspNetCoreRateLimit; using System.Globalization; diff --git a/src/Identity/Utilities/DiscoveryResponseGenerator.cs b/src/Identity/Utilities/DiscoveryResponseGenerator.cs index a034e8312d..e4e008e28e 100644 --- a/src/Identity/Utilities/DiscoveryResponseGenerator.cs +++ b/src/Identity/Utilities/DiscoveryResponseGenerator.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Bit.Core; +using Bit.Core.Settings; using Bit.Core.Utilities; using IdentityServer4.Configuration; using IdentityServer4.Services; diff --git a/src/Identity/Utilities/ServiceCollectionExtensions.cs b/src/Identity/Utilities/ServiceCollectionExtensions.cs index 23e8134c4e..3600dba162 100644 --- a/src/Identity/Utilities/ServiceCollectionExtensions.cs +++ b/src/Identity/Utilities/ServiceCollectionExtensions.cs @@ -1,6 +1,6 @@ using System; -using Bit.Core; using Bit.Core.IdentityServer; +using Bit.Core.Settings; using Bit.Core.Utilities; using IdentityServer4.ResponseHandling; using IdentityServer4.Services; diff --git a/src/Notifications/AzureQueueHostedService.cs b/src/Notifications/AzureQueueHostedService.cs index 06f21905ba..85a7038dd3 100644 --- a/src/Notifications/AzureQueueHostedService.cs +++ b/src/Notifications/AzureQueueHostedService.cs @@ -2,7 +2,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Bit.Core; +using Bit.Core.Settings; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; diff --git a/src/Notifications/HeartbeatHostedService.cs b/src/Notifications/HeartbeatHostedService.cs index 357fca5846..3cb2eda255 100644 --- a/src/Notifications/HeartbeatHostedService.cs +++ b/src/Notifications/HeartbeatHostedService.cs @@ -1,7 +1,7 @@ using System; using System.Threading; using System.Threading.Tasks; -using Bit.Core; +using Bit.Core.Settings; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; diff --git a/src/Notifications/Jobs/JobsHostedService.cs b/src/Notifications/Jobs/JobsHostedService.cs index 5d9570aab5..e59b0939a7 100644 --- a/src/Notifications/Jobs/JobsHostedService.cs +++ b/src/Notifications/Jobs/JobsHostedService.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Bit.Core; using Bit.Core.Jobs; +using Bit.Core.Settings; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Quartz; diff --git a/src/Notifications/NotificationsHub.cs b/src/Notifications/NotificationsHub.cs index d40e885323..f9c38ccea4 100644 --- a/src/Notifications/NotificationsHub.cs +++ b/src/Notifications/NotificationsHub.cs @@ -1,7 +1,7 @@ using System; using System.Threading.Tasks; -using Bit.Core; using Bit.Core.Context; +using Bit.Core.Settings; using Microsoft.AspNetCore.Authorization; namespace Bit.Notifications diff --git a/src/Notifications/Startup.cs b/src/Notifications/Startup.cs index c1c7f9d7fd..4ce00909de 100644 --- a/src/Notifications/Startup.cs +++ b/src/Notifications/Startup.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Globalization; -using Bit.Core; +using Bit.Core.Settings; using Bit.Core.Utilities; using IdentityModel; using Microsoft.AspNetCore.Builder; diff --git a/test/Api.Test/Controllers/AccountsControllerTests.cs b/test/Api.Test/Controllers/AccountsControllerTests.cs index cabad8f4b5..ff75fd51e7 100644 --- a/test/Api.Test/Controllers/AccountsControllerTests.cs +++ b/test/Api.Test/Controllers/AccountsControllerTests.cs @@ -7,6 +7,7 @@ using Bit.Core.Models.Data; using Bit.Core.Models.Table; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using Microsoft.AspNetCore.Identity; using NSubstitute; using System; diff --git a/test/Core.Test/AutoFixture/CipherAttachmentMetaDataFixtures.cs b/test/Core.Test/AutoFixture/CipherAttachmentMetaDataFixtures.cs new file mode 100644 index 0000000000..d5f961ff67 --- /dev/null +++ b/test/Core.Test/AutoFixture/CipherAttachmentMetaDataFixtures.cs @@ -0,0 +1,33 @@ +using AutoFixture; +using AutoFixture.Dsl; +using Bit.Core.Models.Data; + +namespace Bit.Core.Test.AutoFixture.CipherAttachmentMetaData +{ + public class MetaData : ICustomization + { + protected virtual IPostprocessComposer ComposerAction(IFixture fixture, + ICustomizationComposer composer) + { + return composer.With(d => d.Size, fixture.Create()).Without(d => d.SizeString); + } + public void Customize(IFixture fixture) + { + fixture.Customize(composer => ComposerAction(fixture, composer)); + } + } + + public class MetaDataWithoutContainer : MetaData + { + protected override IPostprocessComposer ComposerAction(IFixture fixture, + ICustomizationComposer composer) => + base.ComposerAction(fixture, composer).With(d => d.ContainerName, (string)null); + } + + public class MetaDataWithoutKey : MetaDataWithoutContainer + { + protected override IPostprocessComposer ComposerAction(IFixture fixture, + ICustomizationComposer composer) => + base.ComposerAction(fixture, composer).Without(d => d.Key); + } +} diff --git a/test/Core.Test/Services/AmazonSesMailDeliveryServiceTests.cs b/test/Core.Test/Services/AmazonSesMailDeliveryServiceTests.cs index bb7e26cca7..c2974b6f86 100644 --- a/test/Core.Test/Services/AmazonSesMailDeliveryServiceTests.cs +++ b/test/Core.Test/Services/AmazonSesMailDeliveryServiceTests.cs @@ -6,6 +6,7 @@ using Amazon.SimpleEmail; using Amazon.SimpleEmail.Model; using Bit.Core.Models.Mail; using Bit.Core.Services; +using Bit.Core.Settings; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Logging; using NSubstitute; diff --git a/test/Core.Test/Services/AmazonSqsBlockIpServiceTests.cs b/test/Core.Test/Services/AmazonSqsBlockIpServiceTests.cs index 875a31f7c9..10a7dba29a 100644 --- a/test/Core.Test/Services/AmazonSqsBlockIpServiceTests.cs +++ b/test/Core.Test/Services/AmazonSqsBlockIpServiceTests.cs @@ -2,6 +2,7 @@ using System; using System.Threading.Tasks; using Amazon.SQS; using Bit.Core.Services; +using Bit.Core.Settings; using NSubstitute; using Xunit; diff --git a/test/Core.Test/Services/AzureAttachmentStorageServiceTests.cs b/test/Core.Test/Services/AzureAttachmentStorageServiceTests.cs index c18027d1c0..b7bc73a4e4 100644 --- a/test/Core.Test/Services/AzureAttachmentStorageServiceTests.cs +++ b/test/Core.Test/Services/AzureAttachmentStorageServiceTests.cs @@ -1,5 +1,6 @@ using System; using Bit.Core.Services; +using Bit.Core.Settings; using NSubstitute; using Xunit; diff --git a/test/Core.Test/Services/AzureQueueBlockIpServiceTests.cs b/test/Core.Test/Services/AzureQueueBlockIpServiceTests.cs index 7b1d7b6a8d..dbc8a81063 100644 --- a/test/Core.Test/Services/AzureQueueBlockIpServiceTests.cs +++ b/test/Core.Test/Services/AzureQueueBlockIpServiceTests.cs @@ -1,5 +1,6 @@ using System; using Bit.Core.Services; +using Bit.Core.Settings; using NSubstitute; using Xunit; diff --git a/test/Core.Test/Services/AzureQueueEventWriteServiceTests.cs b/test/Core.Test/Services/AzureQueueEventWriteServiceTests.cs index e479f30347..a155ad8819 100644 --- a/test/Core.Test/Services/AzureQueueEventWriteServiceTests.cs +++ b/test/Core.Test/Services/AzureQueueEventWriteServiceTests.cs @@ -1,6 +1,7 @@ using System; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using NSubstitute; using Xunit; diff --git a/test/Core.Test/Services/AzureQueuePushNotificationServiceTests.cs b/test/Core.Test/Services/AzureQueuePushNotificationServiceTests.cs index caaf1dcf8b..7b304c215c 100644 --- a/test/Core.Test/Services/AzureQueuePushNotificationServiceTests.cs +++ b/test/Core.Test/Services/AzureQueuePushNotificationServiceTests.cs @@ -1,5 +1,6 @@ using System; using Bit.Core.Services; +using Bit.Core.Settings; using Microsoft.AspNetCore.Http; using NSubstitute; using Xunit; diff --git a/test/Core.Test/Services/EventServiceTests.cs b/test/Core.Test/Services/EventServiceTests.cs index 14fbf2c3b5..c307525454 100644 --- a/test/Core.Test/Services/EventServiceTests.cs +++ b/test/Core.Test/Services/EventServiceTests.cs @@ -2,6 +2,7 @@ using System; using Bit.Core.Context; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using NSubstitute; using Xunit; diff --git a/test/Core.Test/Services/HandlebarsMailServiceTests.cs b/test/Core.Test/Services/HandlebarsMailServiceTests.cs index f6207a95fa..161ceecfbe 100644 --- a/test/Core.Test/Services/HandlebarsMailServiceTests.cs +++ b/test/Core.Test/Services/HandlebarsMailServiceTests.cs @@ -1,5 +1,6 @@ using System; using Bit.Core.Services; +using Bit.Core.Settings; using NSubstitute; using Xunit; diff --git a/test/Core.Test/Services/InMemoryServiceBusApplicationCacheServiceTests.cs b/test/Core.Test/Services/InMemoryServiceBusApplicationCacheServiceTests.cs index 25751f7b6d..090802d8e1 100644 --- a/test/Core.Test/Services/InMemoryServiceBusApplicationCacheServiceTests.cs +++ b/test/Core.Test/Services/InMemoryServiceBusApplicationCacheServiceTests.cs @@ -1,6 +1,7 @@ using System; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using NSubstitute; using Xunit; diff --git a/test/Core.Test/Services/LicensingServiceTests.cs b/test/Core.Test/Services/LicensingServiceTests.cs index b234a0054a..076293631e 100644 --- a/test/Core.Test/Services/LicensingServiceTests.cs +++ b/test/Core.Test/Services/LicensingServiceTests.cs @@ -1,6 +1,7 @@ using System; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Logging; using NSubstitute; diff --git a/test/Core.Test/Services/LocalAttachmentStorageServiceTests.cs b/test/Core.Test/Services/LocalAttachmentStorageServiceTests.cs index 44cf843498..e70495d474 100644 --- a/test/Core.Test/Services/LocalAttachmentStorageServiceTests.cs +++ b/test/Core.Test/Services/LocalAttachmentStorageServiceTests.cs @@ -1,29 +1,233 @@ using System; using Bit.Core.Services; +using Bit.Core.Settings; using NSubstitute; using Xunit; +using System.IO; +using Bit.Core.Test.AutoFixture.Attributes; +using Bit.Core.Test.AutoFixture; +using Bit.Core.Test.AutoFixture.CipherFixtures; +using Bit.Core.Models.Data; +using System.Threading.Tasks; +using Bit.Core.Models.Table; +using U2F.Core.Utils; +using Bit.Core.Test.AutoFixture.CipherAttachmentMetaData; +using AutoFixture; namespace Bit.Core.Test.Services { public class LocalAttachmentStorageServiceTests { - private readonly LocalAttachmentStorageService _sut; - private readonly GlobalSettings _globalSettings; - - public LocalAttachmentStorageServiceTests() + private void AssertFileCreation(string expectedPath, string expectedFileContents) { - _globalSettings = new GlobalSettings(); - - _sut = new LocalAttachmentStorageService(_globalSettings); + Assert.True(File.Exists(expectedPath)); + Assert.Equal(expectedFileContents, File.ReadAllText(expectedPath)); } - // Remove this test when we add actual tests. It only proves that - // we've properly constructed the system under test. - [Fact] - public void ServiceExists() + [Theory] + [InlineCustomAutoData(new[] { typeof(UserCipher), typeof(MetaData) })] + [InlineCustomAutoData(new[] { typeof(UserCipher), typeof(MetaDataWithoutContainer) })] + [InlineCustomAutoData(new[] { typeof(UserCipher), typeof(MetaDataWithoutKey) })] + public async Task UploadNewAttachmentAsync_Success(string stream, Cipher cipher, CipherAttachment.MetaData attachmentData) { - Assert.NotNull(_sut); + using (var tempDirectory = new TempDirectory()) + { + var sutProvider = GetSutProvider(tempDirectory); + + await sutProvider.Sut.UploadNewAttachmentAsync(new MemoryStream(stream.GetBytes()), cipher, attachmentData); + + AssertFileCreation($"{tempDirectory}/{cipher.Id}/{attachmentData.AttachmentId}", stream); + } + } + + [Theory] + [InlineCustomAutoData(new[] { typeof(OrganizationCipher), typeof(MetaData) })] + [InlineCustomAutoData(new[] { typeof(OrganizationCipher), typeof(MetaDataWithoutContainer) })] + [InlineCustomAutoData(new[] { typeof(OrganizationCipher), typeof(MetaDataWithoutKey) })] + public async Task UploadShareAttachmentAsync_Success(string stream, Cipher cipher, CipherAttachment.MetaData attachmentData) + { + using (var tempDirectory = new TempDirectory()) + { + var sutProvider = GetSutProvider(tempDirectory); + + await sutProvider.Sut.UploadShareAttachmentAsync(new MemoryStream(stream.GetBytes()), cipher.Id, + cipher.OrganizationId.Value, attachmentData); + + AssertFileCreation($"{tempDirectory}/temp/{cipher.Id}/{cipher.OrganizationId}/{attachmentData.AttachmentId}", stream); + } + } + + [Theory] + [InlineCustomAutoData(new[] { typeof(OrganizationCipher), typeof(MetaData) })] + [InlineCustomAutoData(new[] { typeof(OrganizationCipher), typeof(MetaDataWithoutContainer) })] + [InlineCustomAutoData(new[] { typeof(OrganizationCipher), typeof(MetaDataWithoutKey) })] + public async Task StartShareAttachmentAsync_NoSource_NoWork(Cipher cipher, CipherAttachment.MetaData attachmentData) + { + using (var tempDirectory = new TempDirectory()) + { + var sutProvider = GetSutProvider(tempDirectory); + + await sutProvider.Sut.StartShareAttachmentAsync(cipher.Id, cipher.OrganizationId.Value, attachmentData); + + Assert.False(File.Exists($"{tempDirectory}/{cipher.Id}/{attachmentData.AttachmentId}")); + Assert.False(File.Exists($"{tempDirectory}/{cipher.Id}/{attachmentData.AttachmentId}")); + } + } + + [Theory] + [InlineCustomAutoData(new[] { typeof(OrganizationCipher), typeof(MetaData) })] + [InlineCustomAutoData(new[] { typeof(OrganizationCipher), typeof(MetaDataWithoutContainer) })] + [InlineCustomAutoData(new[] { typeof(OrganizationCipher), typeof(MetaDataWithoutKey) })] + public async Task StartShareAttachmentAsync_NoDest_NoWork(string source, Cipher cipher, CipherAttachment.MetaData attachmentData) + { + using (var tempDirectory = new TempDirectory()) + { + var sutProvider = GetSutProvider(tempDirectory); + + var sourcePath = $"{tempDirectory}/temp/{cipher.Id}/{cipher.OrganizationId}/{attachmentData.AttachmentId}"; + var destPath = $"{tempDirectory}/{cipher.Id}/{attachmentData.AttachmentId}"; + var rollBackPath = $"{tempDirectory}/temp/{cipher.Id}/{attachmentData.AttachmentId}"; + Directory.CreateDirectory(Path.GetDirectoryName(sourcePath)); + File.WriteAllText(sourcePath, source); + + await sutProvider.Sut.StartShareAttachmentAsync(cipher.Id, cipher.OrganizationId.Value, attachmentData); + + Assert.True(File.Exists(sourcePath)); + Assert.Equal(source, File.ReadAllText(sourcePath)); + Assert.False(File.Exists(destPath)); + Assert.False(File.Exists(rollBackPath)); + } + } + + + [Theory] + [InlineCustomAutoData(new[] { typeof(OrganizationCipher), typeof(MetaData) })] + [InlineCustomAutoData(new[] { typeof(OrganizationCipher), typeof(MetaDataWithoutContainer) })] + [InlineCustomAutoData(new[] { typeof(OrganizationCipher), typeof(MetaDataWithoutKey) })] + public async Task StartShareAttachmentAsync_Success(string source, string destOriginal, Cipher cipher, CipherAttachment.MetaData attachmentData) + { + using (var tempDirectory = new TempDirectory()) + { + await StartShareAttachmentAsync(source, destOriginal, cipher, attachmentData, tempDirectory); + } + } + + [Theory] + [InlineCustomAutoData(new[] { typeof(OrganizationCipher), typeof(MetaData) })] + [InlineCustomAutoData(new[] { typeof(OrganizationCipher), typeof(MetaDataWithoutContainer) })] + [InlineCustomAutoData(new[] { typeof(OrganizationCipher), typeof(MetaDataWithoutKey) })] + public async Task RollbackShareAttachmentAsync_Success(string source, string destOriginal, Cipher cipher, CipherAttachment.MetaData attachmentData) + { + using (var tempDirectory = new TempDirectory()) + { + var sutProvider = GetSutProvider(tempDirectory); + + var sourcePath = $"{tempDirectory}/temp/{cipher.Id}/{cipher.OrganizationId}/{attachmentData.AttachmentId}"; + var destPath = $"{tempDirectory}/{cipher.Id}/{attachmentData.AttachmentId}"; + var rollBackPath = $"{tempDirectory}/temp/{cipher.Id}/{attachmentData.AttachmentId}"; + + await StartShareAttachmentAsync(source, destOriginal, cipher, attachmentData, tempDirectory); + await sutProvider.Sut.RollbackShareAttachmentAsync(cipher.Id, cipher.OrganizationId.Value, attachmentData, "Not Used Here"); + + Assert.True(File.Exists(destPath)); + Assert.Equal(destOriginal, File.ReadAllText(destPath)); + Assert.False(File.Exists(sourcePath)); + Assert.False(File.Exists(rollBackPath)); + } + } + + [Theory] + [InlineCustomAutoData(new[] { typeof(UserCipher), typeof(MetaData) })] + [InlineCustomAutoData(new[] { typeof(UserCipher), typeof(MetaDataWithoutContainer) })] + [InlineCustomAutoData(new[] { typeof(UserCipher), typeof(MetaDataWithoutKey) })] + public async Task DeleteAttachmentAsync_Success(Cipher cipher, CipherAttachment.MetaData attachmentData) + { + using (var tempDirectory = new TempDirectory()) + { + var sutProvider = GetSutProvider(tempDirectory); + + var expectedPath = $"{tempDirectory}/{cipher.Id}/{attachmentData.AttachmentId}"; + Directory.CreateDirectory(Path.GetDirectoryName(expectedPath)); + File.Create(expectedPath).Close(); + + await sutProvider.Sut.DeleteAttachmentAsync(cipher.Id, attachmentData); + + Assert.False(File.Exists(expectedPath)); + } + } + + [Theory] + [InlineUserCipherAutoData] + [InlineOrganizationCipherAutoData] + public async Task CleanupAsync_Succes(Cipher cipher) + { + using (var tempDirectory = new TempDirectory()) + { + var sutProvider = GetSutProvider(tempDirectory); + + var tempPath = $"{tempDirectory}/temp/{cipher.Id}"; + var permPath = $"{tempDirectory}/{cipher.Id}"; + Directory.CreateDirectory(tempPath); + Directory.CreateDirectory(permPath); + + await sutProvider.Sut.CleanupAsync(cipher.Id); + + Assert.False(Directory.Exists(tempPath)); + Assert.True(Directory.Exists(permPath)); + } + } + + [Theory] + [InlineUserCipherAutoData] + [InlineOrganizationCipherAutoData] + public async Task DeleteAttachmentsForCipherAsync_Succes(Cipher cipher) + { + using (var tempDirectory = new TempDirectory()) + { + var sutProvider = GetSutProvider(tempDirectory); + + var tempPath = $"{tempDirectory}/temp/{cipher.Id}"; + var permPath = $"{tempDirectory}/{cipher.Id}"; + Directory.CreateDirectory(tempPath); + Directory.CreateDirectory(permPath); + + await sutProvider.Sut.DeleteAttachmentsForCipherAsync(cipher.Id); + + Assert.True(Directory.Exists(tempPath)); + Assert.False(Directory.Exists(permPath)); + } + } + + private async Task StartShareAttachmentAsync(string source, string destOriginal, Cipher cipher, + CipherAttachment.MetaData attachmentData, TempDirectory tempDirectory) + { + var sutProvider = GetSutProvider(tempDirectory); + + var sourcePath = $"{tempDirectory}/temp/{cipher.Id}/{cipher.OrganizationId}/{attachmentData.AttachmentId}"; + var destPath = $"{tempDirectory}/{cipher.Id}/{attachmentData.AttachmentId}"; + var rollBackPath = $"{tempDirectory}/temp/{cipher.Id}/{attachmentData.AttachmentId}"; + Directory.CreateDirectory(Path.GetDirectoryName(sourcePath)); + Directory.CreateDirectory(Path.GetDirectoryName(destPath)); + File.WriteAllText(sourcePath, source); + File.WriteAllText(destPath, destOriginal); + + await sutProvider.Sut.StartShareAttachmentAsync(cipher.Id, cipher.OrganizationId.Value, attachmentData); + + Assert.False(File.Exists(sourcePath)); + Assert.True(File.Exists(destPath)); + Assert.Equal(source, File.ReadAllText(destPath)); + Assert.True(File.Exists(rollBackPath)); + Assert.Equal(destOriginal, File.ReadAllText(rollBackPath)); + } + + private SutProvider GetSutProvider(TempDirectory tempDirectory) + { + var fixture = new Fixture().WithAutoNSubstitutions(); + fixture.Freeze().Attachment.BaseDirectory.Returns(tempDirectory.Directory); + fixture.Freeze().Attachment.BaseUrl.Returns(Guid.NewGuid().ToString()); + + return new SutProvider(fixture).Create(); } } } diff --git a/test/Core.Test/Services/MailKitSmtpMailDeliveryServiceTests.cs b/test/Core.Test/Services/MailKitSmtpMailDeliveryServiceTests.cs index 568af8df3b..d2853d2599 100644 --- a/test/Core.Test/Services/MailKitSmtpMailDeliveryServiceTests.cs +++ b/test/Core.Test/Services/MailKitSmtpMailDeliveryServiceTests.cs @@ -1,5 +1,6 @@ using System; using Bit.Core.Services; +using Bit.Core.Settings; using Microsoft.Extensions.Logging; using NSubstitute; using Xunit; diff --git a/test/Core.Test/Services/MultiServicePushNotificationServiceTests.cs b/test/Core.Test/Services/MultiServicePushNotificationServiceTests.cs index b78b4842d2..0ac9d2b0ee 100644 --- a/test/Core.Test/Services/MultiServicePushNotificationServiceTests.cs +++ b/test/Core.Test/Services/MultiServicePushNotificationServiceTests.cs @@ -1,6 +1,7 @@ using System; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using NSubstitute; diff --git a/test/Core.Test/Services/NotificationHubPushNotificationServiceTests.cs b/test/Core.Test/Services/NotificationHubPushNotificationServiceTests.cs index b049877418..cbca82b1ed 100644 --- a/test/Core.Test/Services/NotificationHubPushNotificationServiceTests.cs +++ b/test/Core.Test/Services/NotificationHubPushNotificationServiceTests.cs @@ -1,6 +1,7 @@ using System; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using Microsoft.AspNetCore.Http; using NSubstitute; using Xunit; diff --git a/test/Core.Test/Services/NotificationHubPushRegistrationServiceTests.cs b/test/Core.Test/Services/NotificationHubPushRegistrationServiceTests.cs index bd5f373030..336e524a56 100644 --- a/test/Core.Test/Services/NotificationHubPushRegistrationServiceTests.cs +++ b/test/Core.Test/Services/NotificationHubPushRegistrationServiceTests.cs @@ -1,6 +1,7 @@ using System; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using NSubstitute; using Xunit; diff --git a/test/Core.Test/Services/NotificationsApiPushNotificationServiceTests.cs b/test/Core.Test/Services/NotificationsApiPushNotificationServiceTests.cs index fa6e6773c5..3b103a4e56 100644 --- a/test/Core.Test/Services/NotificationsApiPushNotificationServiceTests.cs +++ b/test/Core.Test/Services/NotificationsApiPushNotificationServiceTests.cs @@ -1,5 +1,6 @@ using System; using Bit.Core.Services; +using Bit.Core.Settings; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using NSubstitute; diff --git a/test/Core.Test/Services/OrganizationServiceTests.cs b/test/Core.Test/Services/OrganizationServiceTests.cs index 9fc4f6de09..bac45b970f 100644 --- a/test/Core.Test/Services/OrganizationServiceTests.cs +++ b/test/Core.Test/Services/OrganizationServiceTests.cs @@ -6,6 +6,7 @@ using Bit.Core.Models.Table; using Bit.Core.Models.Business; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using Microsoft.AspNetCore.DataProtection; using NSubstitute; using Xunit; diff --git a/test/Core.Test/Services/RelayPushNotificationServiceTests.cs b/test/Core.Test/Services/RelayPushNotificationServiceTests.cs index 079b049619..e53508d47f 100644 --- a/test/Core.Test/Services/RelayPushNotificationServiceTests.cs +++ b/test/Core.Test/Services/RelayPushNotificationServiceTests.cs @@ -1,6 +1,7 @@ using System; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using NSubstitute; diff --git a/test/Core.Test/Services/RelayPushRegistrationServiceTests.cs b/test/Core.Test/Services/RelayPushRegistrationServiceTests.cs index 606f814ebd..3d6fd03b75 100644 --- a/test/Core.Test/Services/RelayPushRegistrationServiceTests.cs +++ b/test/Core.Test/Services/RelayPushRegistrationServiceTests.cs @@ -1,5 +1,6 @@ using System; using Bit.Core.Services; +using Bit.Core.Settings; using Microsoft.Extensions.Logging; using NSubstitute; using Xunit; diff --git a/test/Core.Test/Services/StripePaymentServiceTests.cs b/test/Core.Test/Services/StripePaymentServiceTests.cs index e8d2456e44..0c1c8ca2da 100644 --- a/test/Core.Test/Services/StripePaymentServiceTests.cs +++ b/test/Core.Test/Services/StripePaymentServiceTests.cs @@ -1,6 +1,7 @@ using System; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using Microsoft.Extensions.Logging; using NSubstitute; using Xunit; diff --git a/test/Core.Test/Services/UserServiceTests.cs b/test/Core.Test/Services/UserServiceTests.cs index aab31e50a5..69cb3bfd0c 100644 --- a/test/Core.Test/Services/UserServiceTests.cs +++ b/test/Core.Test/Services/UserServiceTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Bit.Core.Models.Table; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; diff --git a/test/Core.Test/TempDirectory.cs b/test/Core.Test/TempDirectory.cs new file mode 100644 index 0000000000..c87c9863a5 --- /dev/null +++ b/test/Core.Test/TempDirectory.cs @@ -0,0 +1,42 @@ +using System; +using System.IO; + +namespace Bit.Core.Test +{ + public class TempDirectory : IDisposable + { + public string Directory { get; private set; } + + public TempDirectory() + { + Directory = Path.Combine(Path.GetTempPath(), $"bitwarden_{Guid.NewGuid().ToString().Replace("-", "")}"); + } + + public override string ToString() => Directory; + + #region IDisposable implementation + ~TempDirectory() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + public void Dispose(bool disposing) + { + if (disposing) + { + try + { + System.IO.Directory.Delete(Directory, true); + } + catch { } + } + } + # endregion + } +} diff --git a/test/Core.Test/Utilities/SelfHostedAttributeTests.cs b/test/Core.Test/Utilities/SelfHostedAttributeTests.cs index d9c3b469c4..13937451af 100644 --- a/test/Core.Test/Utilities/SelfHostedAttributeTests.cs +++ b/test/Core.Test/Utilities/SelfHostedAttributeTests.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Bit.Core.Exceptions; +using Bit.Core.Settings; using Bit.Core.Utilities; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc;