From 5537470703d6da42d02fc751c4ccd76c681f22f7 Mon Sep 17 00:00:00 2001 From: Matt Gibson Date: Mon, 22 Feb 2021 15:35:16 -0600 Subject: [PATCH] Use sas token for attachment downloads (#1153) * Get limited life attachment download URL This change limits url download to a 1min lifetime. This requires moving to a new container to allow for non-public blob access. Clients will have to call GetAttachmentData api function to receive the download URL. For backwards compatibility, attachment URLs are still present, but will not work for attachments stored in non-public access blobs. * Make GlobalSettings interface for testing * Test LocalAttachmentStorageService equivalence * Remove comment * Add missing globalSettings using * Simplify default attachment container * Default to attachments containe for existing methods A new upload method will be made for uploading to attachments-v2. For compatibility for clients which don't use these new methods, we need to still use the old container. The new container will be used only for new uploads * Remove Default MetaData fixture. * Keep attachments container blob-level security for all instances * Close unclosed FileStream * Favor default value for noop services --- .../src/Portal/Controllers/SsoController.cs | 2 +- .../Portal/Models/SsoConfigDataViewModel.cs | 2 +- .../Portal/Models/SsoConfigEditViewModel.cs | 2 +- bitwarden_license/src/Portal/Startup.cs | 1 + ...nterprisePortalCurrentContextMiddleware.cs | 1 + bitwarden_license/src/Sso/Startup.cs | 1 + .../Utilities/DiscoveryResponseGenerator.cs | 2 +- .../DynamicAuthenticationSchemeProvider.cs | 2 +- .../Utilities/ServiceCollectionExtensions.cs | 2 +- src/Admin/Controllers/HomeController.cs | 2 +- src/Admin/Controllers/LogsController.cs | 2 +- .../Controllers/OrganizationsController.cs | 2 +- src/Admin/Controllers/ToolsController.cs | 1 + src/Admin/Controllers/UsersController.cs | 2 +- .../AmazonSqsBlockIpHostedService.cs | 2 +- .../AzureQueueBlockIpHostedService.cs | 2 +- .../HostedServices/BlockIpHostedService.cs | 2 +- .../DatabaseMigrationHostedService.cs | 2 +- src/Admin/Jobs/AliveJob.cs | 1 + src/Admin/Jobs/JobsHostedService.cs | 2 +- src/Admin/Models/HomeModel.cs | 2 +- src/Admin/Models/OrganizationEditModel.cs | 2 +- src/Admin/Models/UserEditModel.cs | 2 +- src/Admin/Startup.cs | 2 +- src/Admin/Views/Shared/_Layout.cshtml | 2 +- src/Api/Controllers/AccountsController.cs | 1 + src/Api/Controllers/CiphersController.cs | 28 ++- src/Api/Controllers/HibpController.cs | 2 +- src/Api/Controllers/MiscController.cs | 2 +- .../Controllers/OrganizationsController.cs | 2 +- src/Api/Controllers/PoliciesController.cs | 2 +- src/Api/Controllers/PushController.cs | 1 + src/Api/Controllers/SendsController.cs | 2 +- src/Api/Controllers/SyncController.cs | 2 +- src/Api/Controllers/TwoFactorController.cs | 2 +- src/Api/Jobs/JobsHostedService.cs | 2 +- .../Controllers/OrganizationController.cs | 2 +- src/Api/Startup.cs | 1 + .../Utilities/ServiceCollectionExtensions.cs | 2 +- .../Controllers/FreshdeskController.cs | 3 +- src/Billing/Controllers/StripeController.cs | 4 +- src/Billing/Jobs/JobsHostedService.cs | 2 +- src/Billing/Startup.cs | 2 +- src/Core/Context/CurrentContext.cs | 1 + src/Core/Context/ICurrentContext.cs | 1 + .../ApplicationCacheHostedService.cs | 1 + src/Core/Identity/DuoWebTokenProvider.cs | 1 + .../OrganizationDuoWebTokenProvider.cs | 1 + src/Core/Identity/U2fTokenProvider.cs | 1 + src/Core/Identity/UserStore.cs | 1 + src/Core/Identity/YubicoOtpTokenProvider.cs | 1 + src/Core/IdentityServer/ApiClient.cs | 1 + .../IdentityServer/BaseRequestValidator.cs | 1 + src/Core/IdentityServer/ClientStore.cs | 1 + ...onfigureOpenIdConnectDistributedOptions.cs | 1 + .../CustomTokenRequestValidator.cs | 1 + src/Core/IdentityServer/OidcIdentityClient.cs | 1 + src/Core/IdentityServer/ProfileService.cs | 1 + .../ResourceOwnerPasswordValidator.cs | 1 + src/Core/IdentityServer/StaticClientStore.cs | 1 + .../IdentityServer/VaultCorsPolicyService.cs | 1 + src/Core/Jobs/BaseJobsHostedService.cs | 1 + .../Request/Accounts/PremiumRequestModel.cs | 2 + .../Api/Request/BitPayInvoiceRequestModel.cs | 1 + .../OrganizationUpdateRequestModel.cs | 1 + .../Api/Response/AttachmentResponseModel.cs | 1 + .../Api/Response/CipherResponseModel.cs | 1 + .../Response/EmergencyAccessResponseModel.cs | 1 + .../Api/Response/SendAccessResponseModel.cs | 1 + .../Models/Api/Response/SendResponseModel.cs | 1 + .../Models/Api/Response/SyncResponseModel.cs | 1 + src/Core/Models/Api/SendFileModel.cs | 1 + .../Models/Business/OrganizationLicense.cs | 1 + src/Core/Models/Data/CipherAttachment.cs | 6 + src/Core/Models/Data/EventMessage.cs | 1 + src/Core/Models/Table/Cipher.cs | 4 + .../Repositories/PostgreSql/UserRepository.cs | 1 + .../SqlServer/CipherRepository.cs | 1 + .../SqlServer/CollectionCipherRepository.cs | 1 + .../SqlServer/CollectionRepository.cs | 1 + .../SqlServer/DeviceRepository.cs | 1 + .../SqlServer/EmergencyAccessRepository.cs | 1 + .../Repositories/SqlServer/EventRepository.cs | 1 + .../SqlServer/FolderRepository.cs | 1 + .../Repositories/SqlServer/GrantRepository.cs | 1 + .../Repositories/SqlServer/GroupRepository.cs | 1 + .../SqlServer/InstallationRepository.cs | 1 + .../SqlServer/MaintenanceRepository.cs | 1 + .../SqlServer/OrganizationRepository.cs | 1 + .../SqlServer/OrganizationUserRepository.cs | 1 + .../SqlServer/PolicyRepository.cs | 1 + .../Repositories/SqlServer/SendRepository.cs | 1 + .../SqlServer/SsoConfigRepository.cs | 1 + .../SqlServer/SsoUserRepository.cs | 1 + .../SqlServer/TaxRateRepository.cs | 1 + .../SqlServer/TransactionRepository.cs | 1 + .../Repositories/SqlServer/U2fRepository.cs | 1 + .../Repositories/SqlServer/UserRepository.cs | 1 + .../TableStorage/EventRepository.cs | 1 + .../InstallationDeviceRepository.cs | 1 + .../TableStorage/MetaDataRepository.cs | 1 + .../Services/IAttachmentStorageService.cs | 14 +- .../AmazonSesMailDeliveryService.cs | 1 + .../AmazonSqsBlockIpService.cs | 1 + .../Implementations/AppleIapService.cs | 1 + .../AzureAttachmentStorageService.cs | 148 ++++++------ .../AzureQueueBlockIpService.cs | 1 + .../AzureQueueEventWriteService.cs | 1 + .../AzureQueuePushNotificationService.cs | 5 +- .../AzureQueueReferenceEventService.cs | 1 + .../AzureSendFileStorageService.cs | 1 + .../Services/Implementations/CipherService.cs | 48 +++- .../Implementations/EmergencyAccessService.cs | 1 + .../Services/Implementations/EventService.cs | 1 + .../Implementations/HandlebarsMailService.cs | 1 + ...MemoryServiceBusApplicationCacheService.cs | 1 + .../Implementations/LicensingService.cs | 1 + .../LocalAttachmentStorageService.cs | 61 +++-- .../LocalSendStorageService.cs | 1 + .../MailKitSmtpMailDeliveryService.cs | 1 + .../MultiServicePushNotificationService.cs | 1 + .../NotificationHubPushNotificationService.cs | 1 + .../NotificationHubPushRegistrationService.cs | 1 + ...NotificationsApiPushNotificationService.cs | 1 + .../Implementations/OrganizationService.cs | 1 + .../RelayPushNotificationService.cs | 1 + .../RelayPushRegistrationService.cs | 1 + .../Services/Implementations/SendService.cs | 1 + .../Implementations/StripePaymentService.cs | 3 +- .../Services/Implementations/UserService.cs | 1 + .../NoopAttachmentStorageService.cs | 17 +- .../NoopLicensingService.cs | 1 + src/Core/{ => Settings}/GlobalSettings.cs | 8 +- src/Core/Settings/IFileStorageSettings.cs | 9 + src/Core/Settings/IGlobalSettings.cs | 8 + src/Core/Utilities/BitPayClient.cs | 1 + src/Core/Utilities/CoreHelpers.cs | 1 + .../Utilities/CurrentContextMiddleware.cs | 1 + src/Core/Utilities/LoggerFactoryExtensions.cs | 1 + src/Core/Utilities/SelfHostedAttribute.cs | 1 + .../Utilities/ServiceCollectionExtensions.cs | 2 + src/Events/Startup.cs | 2 +- src/EventsProcessor/Startup.cs | 2 +- src/Icons/Startup.cs | 2 +- src/Identity/Startup.cs | 1 + .../Utilities/DiscoveryResponseGenerator.cs | 2 +- .../Utilities/ServiceCollectionExtensions.cs | 2 +- src/Notifications/AzureQueueHostedService.cs | 2 +- src/Notifications/HeartbeatHostedService.cs | 2 +- src/Notifications/Jobs/JobsHostedService.cs | 2 +- src/Notifications/NotificationsHub.cs | 2 +- src/Notifications/Startup.cs | 2 +- .../Controllers/AccountsControllerTests.cs | 1 + .../CipherAttachmentMetaDataFixtures.cs | 33 +++ .../AmazonSesMailDeliveryServiceTests.cs | 1 + .../Services/AmazonSqsBlockIpServiceTests.cs | 1 + .../AzureAttachmentStorageServiceTests.cs | 1 + .../Services/AzureQueueBlockIpServiceTests.cs | 1 + .../AzureQueueEventWriteServiceTests.cs | 1 + .../AzureQueuePushNotificationServiceTests.cs | 1 + test/Core.Test/Services/EventServiceTests.cs | 1 + .../Services/HandlebarsMailServiceTests.cs | 1 + ...yServiceBusApplicationCacheServiceTests.cs | 1 + .../Services/LicensingServiceTests.cs | 1 + .../LocalAttachmentStorageServiceTests.cs | 228 +++++++++++++++++- .../MailKitSmtpMailDeliveryServiceTests.cs | 1 + ...ultiServicePushNotificationServiceTests.cs | 1 + ...ficationHubPushNotificationServiceTests.cs | 1 + ...ficationHubPushRegistrationServiceTests.cs | 1 + ...icationsApiPushNotificationServiceTests.cs | 1 + .../Services/OrganizationServiceTests.cs | 1 + .../RelayPushNotificationServiceTests.cs | 1 + .../RelayPushRegistrationServiceTests.cs | 1 + .../Services/StripePaymentServiceTests.cs | 1 + test/Core.Test/Services/UserServiceTests.cs | 1 + test/Core.Test/TempDirectory.cs | 42 ++++ .../Utilities/SelfHostedAttributeTests.cs | 1 + 177 files changed, 694 insertions(+), 178 deletions(-) rename src/Core/{ => Settings}/GlobalSettings.cs (97%) create mode 100644 src/Core/Settings/IFileStorageSettings.cs create mode 100644 src/Core/Settings/IGlobalSettings.cs create mode 100644 test/Core.Test/AutoFixture/CipherAttachmentMetaDataFixtures.cs create mode 100644 test/Core.Test/TempDirectory.cs 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;