2023-04-14 11:13:16 +01:00
using System.Security.Claims ;
using System.Text.Json ;
2023-10-20 06:37:46 +10:00
using Bit.Core.AdminConsole.Entities ;
2023-11-23 07:07:37 +10:00
using Bit.Core.AdminConsole.Enums ;
2023-10-27 03:38:29 +10:00
using Bit.Core.AdminConsole.Enums.Provider ;
2023-10-20 06:37:46 +10:00
using Bit.Core.AdminConsole.Models.Business ;
2023-11-23 07:07:37 +10:00
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies ;
2023-10-27 07:47:44 +10:00
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces ;
2023-10-20 06:37:46 +10:00
using Bit.Core.AdminConsole.Repositories ;
2023-11-23 07:07:37 +10:00
using Bit.Core.AdminConsole.Services ;
2023-04-14 13:25:56 -04:00
using Bit.Core.Auth.Enums ;
using Bit.Core.Auth.Models.Business ;
Auth/PM-3275 - Changes to support TDE User without MP being able to Set a Password + misc refactoring (#3242)
* PM-3275 - Add new GetMasterPasswordPolicy endpoint which will allow authenticated clients to get an enabled MP org policy if it exists for the purposes of enforcing those policy requirements when setting a password.
* PM-3275 - AccountsController.cs - PostSetPasswordAsync - (1) Convert UserService.setPasswordAsync into new SetInitialMasterPasswordCommand (2) Refactor SetInitialMasterPasswordCommand to only accept post SSO users who are in the invited state
(3) Add TODOs for more cleanup work and more commands
* PM-3275 - Update AccountsControllerTests.cs to add new SetInitialMasterPasswordCommand
* PM-3275 - UserService.cs - Remove non implemented ChangePasswordAsync method
* PM-3275 - The new SetInitialMasterPasswordCommand leveraged the OrganizationService.cs AcceptUserAsync method so while I was in here I converted the AcceptUserAsync methods into a new AcceptOrgUserCommand.cs and turned the private method which accepted an existing org user public for use in the SetInitialMasterPasswordCommand
* PM-3275 - Dotnet format
* PM-3275 - Test SetInitialMasterPasswordCommand
* Dotnet format
* PM-3275 - In process AcceptOrgUserCommandTests.cs
* PM-3275 - Migrate changes from AC-244 / #3199 over into new AcceptOrgUserCommand
* PM-3275 - AcceptOrgUserCommand.cs - create data protector specifically for this command
* PM-3275 - Add TODO for renaming / removing overloading of methods to improve readability / clarity
* PM-3275 - AcceptOrgUserCommand.cs - refactor AcceptOrgUserAsync by OrgId to retrieve orgUser with _organizationUserRepository.GetByOrganizationAsync which gets a single user instead of a collection
* PM-3275 - AcceptOrgUserCommand.cs - update name in TODO for evaluation later
* PM-3275 / PM-1196 - (1) Slightly refactor SsoEmail2faSessionTokenable to provide public static GetTokenLifeTime() method for testing (2) Add missed tests to SsoEmail2faSessionTokenable in preparation for building tests for new OrgUserInviteTokenable.cs
* PM-3275 / PM-1196 - Removing SsoEmail2faSessionTokenable.cs changes + tests as I've handled that separately in a new PR (#3270) for newly created task PM-3925
* PM-3275 - ExpiringTokenable.cs - add clarifying comments to help distinguish between the Valid property and the TokenIsValid method.
* PM-3275 - Create OrgUserInviteTokenable.cs and add tests in OrgUserInviteTokenableTests.cs
* PM-3275 - OrganizationService.cs - Refactor Org User Invite methods to use new OrgUserInviteTokenable instead of manual creation of a token
* PM-3275 - OrgUserInviteTokenable.cs - clarify backwards compat note
* PM-3275 - AcceptOrgUserCommand.cs - Add TODOs + minor name refactor
* PM-3275 - AcceptOrgUserCommand.cs - replace method overloading with more easily readable names.
* PM-3275 - AcceptOrgUserCommand.cs - Update ValidateOrgUserInviteToken to add new token validation while maintaining backwards compatibility for 1 release.
* dotnet format
* PM-3275 - AcceptOrgUserCommand.cs - Move private method below where it is used
* PM-3275 - ServiceCollectionExtensions.cs - Must register IDataProtectorTokenFactory<OrgUserInviteTokenable> for new tokenable
* PM-3275 - OrgUserInviteTokenable needed access to global settings to set its token lifetime to the _globalSettings.OrganizationInviteExpirationHours value. Creating a factory seemed the most straightforward way to encapsulate the desired creation logic. Unsure if in the correct location in ServiceCollectionExtensions.cs but will figure that out later.
* PM-3275 - In process work of creating AcceptOrgUserCommandTests.cs
* PM-3275 - Remove no longer relevant AcceptOrgUser tests from OrganizationServiceTests.cs
* PM-3275 - Register OrgUserInviteTokenableFactory alongside tokenizer
* PM-3275 - AcceptOrgUserCommandTests.cs - AcceptOrgUserAsync basic test suite completed.
* PM-3275 - AcceptOrgUserCommandTests.cs - tweak test names
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Remove old tests from OrganizationServiceTests as no longer needed to reference (2) Add summary for SetupCommonAcceptOrgUserMocks (3) Get AcceptOrgUserByToken_OldToken_AcceptsUserAndVerifiesEmail passing
* PM-3275 - Create interface for OrgUserInviteTokenableFactory b/c that's the right thing to do + enables test substitution
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Start work on AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail (2) Create and use SetupCommonAcceptOrgUserByTokenMocks() (3) Create generic FakeDataProtectorTokenFactory for tokenable testing
* PM-3275 - (1) Get AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail test passing (2) Move FakeDataProtectorTokenFactory to own file
* PM-3275 - AcceptOrgUserCommandTests.cs - Finish up tests for AcceptOrgUserByTokenAsync
* PM-3275 - Add pseudo section comments
* PM-3275 - Clean up unused params on AcceptOrgUserByToken_EmailMismatch_ThrowsBadRequest test
* PM-3275 - (1) Tests written for AcceptOrgUserByOrgSsoIdAsync (2) Refactor happy path assertions into helper function AssertValidAcceptedOrgUser to reduce code duplication
* PM-3275 - Finish up testing AcceptOrgUserCommandTests.cs by adding tests for AcceptOrgUserByOrgIdAsync
* PM-3275 - Tweaking test naming to ensure consistency.
* PM-3275 - Bugfix - OrgUserInviteTokenableFactory implementation required when declaring singleton service in ServiceCollectionExtensions.cs
* PM-3275 - Resolve failing OrganizationServiceTests.cs
* dotnet format
* PM-3275 - PoliciesController.cs - GetMasterPasswordPolicy bugfix - for orgs without a MP policy, policy comes back as null and we should return notFound in that case.
* PM-3275 - Add PoliciesControllerTests.cs specifically for new GetMasterPasswordPolicy(...) endpoint.
* PM-3275 - dotnet format PoliciesControllerTests.cs
* PM-3275 - PoliciesController.cs - (1) Add tech debt task number (2) Properly flag endpoint as deprecated
* PM-3275 - Add new hasManageResetPasswordPermission property to ProfileResponseModel.cs primarily for sync so that we can condition client side if TDE user obtains elevated permissions
* PM-3275 - Fix AccountsControllerTests.cs
* PM-3275 - OrgUserInviteTokenable.cs - clarify TODO
* PM-3275 - AcceptOrgUserCommand.cs - Refactor token validation to use short circuiting to only run old token validation if new token validation fails.
* PM-3275 - OrgUserInviteTokenable.cs - (1) Add new static methods to centralize validation logic to avoid repetition (2) Add new token validation method so we can avoid having to pass in a full org user (and hitting the db to do so)
* PM-3275 - Realized that the old token validation was used in the PoliciesController.cs (existing user clicks invite link in email and goes to log in) and UserService.cs (user clicks invite link in email and registers for a new acct). Added tech debt item for cleaning up backwards compatibility in future.
* dotnet format
* PM-3275 - (1) AccountsController.cs - Update PostSetPasswordAsync SetPasswordRequestModel to allow null keys for the case where we have a TDE user who obtains elevated permissions - they already have a user public and user encrypted private key saved in the db. (2) AccountsControllerTests.cs - test PostSetPasswordAsync scenarios to ensure changes will work as expected.
* PM-3275 - PR review feedback - (1) set CurrentContext to private (2) Refactor GetProfile to use variables to improve clarity and simplify debugging.
* PM-3275 - SyncController.cs - PR Review Feedback - Set current context as private instead of protected.
* PM-3275 - CurrentContextExtensions.cs - PR Feedback - move parenthesis up from own line.
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - Replace unnecessary variable
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - PR Feedback - Add expected outcome statement to test name
* PM-3275 - Set Initial Password command and tests - PR Feedback changes - (1) Rename orgIdentifier --> OrgSsoIdentifier for clarity (2) Update SetInitialMasterPasswordAsync to not allow null orgSsoId with explicit message saying this vs letting null org trigger invalid organization (3) Add test to cover this new scenario.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Move summary from implementation to interface to better respect standards and the fact that the interface is the more seen piece of code.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, rename AcceptOrgUserByTokenAsync -> AcceptOrgUserByEmailTokenAsync + replace generic name token with emailToken
* PM-3275 - OrganizationService.cs - Per PR feedback, remove dupe line
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove new lines in error messages for consistency.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Per PR feedback, adjust formatting of constructor for improved readability.
* PM-3275 - CurrentContextExtensions.cs - Refactor AnyOrgUserHasManageResetPasswordPermission per PR feedback to remove unnecessary var.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove completed TODO
* PM-3275 - PoliciesController.cs - Per PR feedback, update GetByInvitedUser param to be guid instead of string.
* PM-3275 - OrgUserInviteTokenable.cs - per PR feedback, add tech debt item info.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, use const purpose from tokenable instead of magic string.
* PM-3275 - Restore non duplicate line to fix tests
* PM-3275 - Per PR feedback, revert all sync controller changes as the ProfileResponseModel.organizations array has org objects which have permissions which have the ManageResetPassword permission. So, I have the information that I need clientside already to determine if the user has the ManageResetPassword in any org.
* PM-3275 - PoliciesControllerTests.cs - Update imports as the PoliciesController was moved under the admin console team's domain.
* PM-3275 - Resolve issues from merge conflict resolutions to get solution building.
* PM-3275 / PM-4633 - PoliciesController.cs - use orgUserId to look up user instead of orgId. Oops.
* Fix user service tests
* Resolve merge conflict
2023-11-02 11:02:25 -04:00
using Bit.Core.Auth.Models.Business.Tokenables ;
2023-04-14 13:25:56 -04:00
using Bit.Core.Auth.Repositories ;
2017-03-03 00:07:11 -05:00
using Bit.Core.Context ;
2022-01-11 10:40:51 +01:00
using Bit.Core.Entities ;
2017-04-10 10:44:27 -04:00
using Bit.Core.Enums ;
2017-03-03 00:07:11 -05:00
using Bit.Core.Exceptions ;
using Bit.Core.Models.Business ;
2017-05-11 14:52:35 -04:00
using Bit.Core.Models.Data ;
2023-12-18 11:16:17 -05:00
using Bit.Core.Models.Mail ;
2023-08-05 07:51:12 +10:00
using Bit.Core.OrganizationFeatures.OrganizationSubscriptions.Interface ;
2017-03-03 00:07:11 -05:00
using Bit.Core.Repositories ;
2021-02-22 15:35:16 -06:00
using Bit.Core.Settings ;
Auth/PM-3275 - Changes to support TDE User without MP being able to Set a Password + misc refactoring (#3242)
* PM-3275 - Add new GetMasterPasswordPolicy endpoint which will allow authenticated clients to get an enabled MP org policy if it exists for the purposes of enforcing those policy requirements when setting a password.
* PM-3275 - AccountsController.cs - PostSetPasswordAsync - (1) Convert UserService.setPasswordAsync into new SetInitialMasterPasswordCommand (2) Refactor SetInitialMasterPasswordCommand to only accept post SSO users who are in the invited state
(3) Add TODOs for more cleanup work and more commands
* PM-3275 - Update AccountsControllerTests.cs to add new SetInitialMasterPasswordCommand
* PM-3275 - UserService.cs - Remove non implemented ChangePasswordAsync method
* PM-3275 - The new SetInitialMasterPasswordCommand leveraged the OrganizationService.cs AcceptUserAsync method so while I was in here I converted the AcceptUserAsync methods into a new AcceptOrgUserCommand.cs and turned the private method which accepted an existing org user public for use in the SetInitialMasterPasswordCommand
* PM-3275 - Dotnet format
* PM-3275 - Test SetInitialMasterPasswordCommand
* Dotnet format
* PM-3275 - In process AcceptOrgUserCommandTests.cs
* PM-3275 - Migrate changes from AC-244 / #3199 over into new AcceptOrgUserCommand
* PM-3275 - AcceptOrgUserCommand.cs - create data protector specifically for this command
* PM-3275 - Add TODO for renaming / removing overloading of methods to improve readability / clarity
* PM-3275 - AcceptOrgUserCommand.cs - refactor AcceptOrgUserAsync by OrgId to retrieve orgUser with _organizationUserRepository.GetByOrganizationAsync which gets a single user instead of a collection
* PM-3275 - AcceptOrgUserCommand.cs - update name in TODO for evaluation later
* PM-3275 / PM-1196 - (1) Slightly refactor SsoEmail2faSessionTokenable to provide public static GetTokenLifeTime() method for testing (2) Add missed tests to SsoEmail2faSessionTokenable in preparation for building tests for new OrgUserInviteTokenable.cs
* PM-3275 / PM-1196 - Removing SsoEmail2faSessionTokenable.cs changes + tests as I've handled that separately in a new PR (#3270) for newly created task PM-3925
* PM-3275 - ExpiringTokenable.cs - add clarifying comments to help distinguish between the Valid property and the TokenIsValid method.
* PM-3275 - Create OrgUserInviteTokenable.cs and add tests in OrgUserInviteTokenableTests.cs
* PM-3275 - OrganizationService.cs - Refactor Org User Invite methods to use new OrgUserInviteTokenable instead of manual creation of a token
* PM-3275 - OrgUserInviteTokenable.cs - clarify backwards compat note
* PM-3275 - AcceptOrgUserCommand.cs - Add TODOs + minor name refactor
* PM-3275 - AcceptOrgUserCommand.cs - replace method overloading with more easily readable names.
* PM-3275 - AcceptOrgUserCommand.cs - Update ValidateOrgUserInviteToken to add new token validation while maintaining backwards compatibility for 1 release.
* dotnet format
* PM-3275 - AcceptOrgUserCommand.cs - Move private method below where it is used
* PM-3275 - ServiceCollectionExtensions.cs - Must register IDataProtectorTokenFactory<OrgUserInviteTokenable> for new tokenable
* PM-3275 - OrgUserInviteTokenable needed access to global settings to set its token lifetime to the _globalSettings.OrganizationInviteExpirationHours value. Creating a factory seemed the most straightforward way to encapsulate the desired creation logic. Unsure if in the correct location in ServiceCollectionExtensions.cs but will figure that out later.
* PM-3275 - In process work of creating AcceptOrgUserCommandTests.cs
* PM-3275 - Remove no longer relevant AcceptOrgUser tests from OrganizationServiceTests.cs
* PM-3275 - Register OrgUserInviteTokenableFactory alongside tokenizer
* PM-3275 - AcceptOrgUserCommandTests.cs - AcceptOrgUserAsync basic test suite completed.
* PM-3275 - AcceptOrgUserCommandTests.cs - tweak test names
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Remove old tests from OrganizationServiceTests as no longer needed to reference (2) Add summary for SetupCommonAcceptOrgUserMocks (3) Get AcceptOrgUserByToken_OldToken_AcceptsUserAndVerifiesEmail passing
* PM-3275 - Create interface for OrgUserInviteTokenableFactory b/c that's the right thing to do + enables test substitution
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Start work on AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail (2) Create and use SetupCommonAcceptOrgUserByTokenMocks() (3) Create generic FakeDataProtectorTokenFactory for tokenable testing
* PM-3275 - (1) Get AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail test passing (2) Move FakeDataProtectorTokenFactory to own file
* PM-3275 - AcceptOrgUserCommandTests.cs - Finish up tests for AcceptOrgUserByTokenAsync
* PM-3275 - Add pseudo section comments
* PM-3275 - Clean up unused params on AcceptOrgUserByToken_EmailMismatch_ThrowsBadRequest test
* PM-3275 - (1) Tests written for AcceptOrgUserByOrgSsoIdAsync (2) Refactor happy path assertions into helper function AssertValidAcceptedOrgUser to reduce code duplication
* PM-3275 - Finish up testing AcceptOrgUserCommandTests.cs by adding tests for AcceptOrgUserByOrgIdAsync
* PM-3275 - Tweaking test naming to ensure consistency.
* PM-3275 - Bugfix - OrgUserInviteTokenableFactory implementation required when declaring singleton service in ServiceCollectionExtensions.cs
* PM-3275 - Resolve failing OrganizationServiceTests.cs
* dotnet format
* PM-3275 - PoliciesController.cs - GetMasterPasswordPolicy bugfix - for orgs without a MP policy, policy comes back as null and we should return notFound in that case.
* PM-3275 - Add PoliciesControllerTests.cs specifically for new GetMasterPasswordPolicy(...) endpoint.
* PM-3275 - dotnet format PoliciesControllerTests.cs
* PM-3275 - PoliciesController.cs - (1) Add tech debt task number (2) Properly flag endpoint as deprecated
* PM-3275 - Add new hasManageResetPasswordPermission property to ProfileResponseModel.cs primarily for sync so that we can condition client side if TDE user obtains elevated permissions
* PM-3275 - Fix AccountsControllerTests.cs
* PM-3275 - OrgUserInviteTokenable.cs - clarify TODO
* PM-3275 - AcceptOrgUserCommand.cs - Refactor token validation to use short circuiting to only run old token validation if new token validation fails.
* PM-3275 - OrgUserInviteTokenable.cs - (1) Add new static methods to centralize validation logic to avoid repetition (2) Add new token validation method so we can avoid having to pass in a full org user (and hitting the db to do so)
* PM-3275 - Realized that the old token validation was used in the PoliciesController.cs (existing user clicks invite link in email and goes to log in) and UserService.cs (user clicks invite link in email and registers for a new acct). Added tech debt item for cleaning up backwards compatibility in future.
* dotnet format
* PM-3275 - (1) AccountsController.cs - Update PostSetPasswordAsync SetPasswordRequestModel to allow null keys for the case where we have a TDE user who obtains elevated permissions - they already have a user public and user encrypted private key saved in the db. (2) AccountsControllerTests.cs - test PostSetPasswordAsync scenarios to ensure changes will work as expected.
* PM-3275 - PR review feedback - (1) set CurrentContext to private (2) Refactor GetProfile to use variables to improve clarity and simplify debugging.
* PM-3275 - SyncController.cs - PR Review Feedback - Set current context as private instead of protected.
* PM-3275 - CurrentContextExtensions.cs - PR Feedback - move parenthesis up from own line.
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - Replace unnecessary variable
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - PR Feedback - Add expected outcome statement to test name
* PM-3275 - Set Initial Password command and tests - PR Feedback changes - (1) Rename orgIdentifier --> OrgSsoIdentifier for clarity (2) Update SetInitialMasterPasswordAsync to not allow null orgSsoId with explicit message saying this vs letting null org trigger invalid organization (3) Add test to cover this new scenario.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Move summary from implementation to interface to better respect standards and the fact that the interface is the more seen piece of code.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, rename AcceptOrgUserByTokenAsync -> AcceptOrgUserByEmailTokenAsync + replace generic name token with emailToken
* PM-3275 - OrganizationService.cs - Per PR feedback, remove dupe line
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove new lines in error messages for consistency.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Per PR feedback, adjust formatting of constructor for improved readability.
* PM-3275 - CurrentContextExtensions.cs - Refactor AnyOrgUserHasManageResetPasswordPermission per PR feedback to remove unnecessary var.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove completed TODO
* PM-3275 - PoliciesController.cs - Per PR feedback, update GetByInvitedUser param to be guid instead of string.
* PM-3275 - OrgUserInviteTokenable.cs - per PR feedback, add tech debt item info.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, use const purpose from tokenable instead of magic string.
* PM-3275 - Restore non duplicate line to fix tests
* PM-3275 - Per PR feedback, revert all sync controller changes as the ProfileResponseModel.organizations array has org objects which have permissions which have the ManageResetPassword permission. So, I have the information that I need clientside already to determine if the user has the ManageResetPassword in any org.
* PM-3275 - PoliciesControllerTests.cs - Update imports as the PoliciesController was moved under the admin console team's domain.
* PM-3275 - Resolve issues from merge conflict resolutions to get solution building.
* PM-3275 / PM-4633 - PoliciesController.cs - use orgUserId to look up user instead of orgId. Oops.
* Fix user service tests
* Resolve merge conflict
2023-11-02 11:02:25 -04:00
using Bit.Core.Tokens ;
2023-04-18 14:05:17 +02:00
using Bit.Core.Tools.Enums ;
using Bit.Core.Tools.Models.Business ;
using Bit.Core.Tools.Services ;
2017-03-03 00:07:11 -05:00
using Bit.Core.Utilities ;
2021-09-23 06:36:08 -04:00
using Microsoft.Extensions.Logging ;
2017-04-04 10:13:16 -04:00
using Stripe ;
2017-03-03 00:07:11 -05:00
namespace Bit.Core.Services ;
2022-08-29 16:06:55 -04:00
2017-03-03 00:07:11 -05:00
public class OrganizationService : IOrganizationService
{
private readonly IOrganizationRepository _organizationRepository ;
private readonly IOrganizationUserRepository _organizationUserRepository ;
2017-04-27 09:19:30 -04:00
private readonly ICollectionRepository _collectionRepository ;
2017-03-04 21:28:41 -05:00
private readonly IUserRepository _userRepository ;
2017-05-13 12:00:40 -04:00
private readonly IGroupRepository _groupRepository ;
2017-03-23 00:17:34 -04:00
private readonly IMailService _mailService ;
2017-05-26 22:52:50 -04:00
private readonly IPushNotificationService _pushNotificationService ;
private readonly IPushRegistrationService _pushRegistrationService ;
2017-08-11 08:57:31 -04:00
private readonly IDeviceRepository _deviceRepository ;
2017-08-14 20:57:45 -04:00
private readonly ILicensingService _licensingService ;
2017-12-01 16:00:30 -05:00
private readonly IEventService _eventService ;
2017-12-19 16:02:39 -05:00
private readonly IApplicationCacheService _applicationCacheService ;
2019-02-08 23:53:09 -05:00
private readonly IPaymentService _paymentService ;
2020-01-15 15:00:54 -05:00
private readonly IPolicyRepository _policyRepository ;
2023-05-12 08:22:19 +01:00
private readonly IPolicyService _policyService ;
2020-07-22 09:38:39 -04:00
private readonly ISsoConfigRepository _ssoConfigRepository ;
2020-08-26 14:12:04 -04:00
private readonly ISsoUserRepository _ssoUserRepository ;
2020-07-07 12:01:34 -04:00
private readonly IReferenceEventService _referenceEventService ;
2021-09-23 06:36:08 -04:00
private readonly IGlobalSettings _globalSettings ;
2022-05-10 17:12:09 -04:00
private readonly IOrganizationApiKeyRepository _organizationApiKeyRepository ;
2021-07-01 14:31:05 +02:00
private readonly ICurrentContext _currentContext ;
2021-09-23 06:36:08 -04:00
private readonly ILogger < OrganizationService > _logger ;
2023-01-26 11:51:26 -05:00
private readonly IProviderOrganizationRepository _providerOrganizationRepository ;
private readonly IProviderUserRepository _providerUserRepository ;
2023-08-05 07:51:12 +10:00
private readonly ICountNewSmSeatsRequiredQuery _countNewSmSeatsRequiredQuery ;
private readonly IUpdateSecretsManagerSubscriptionCommand _updateSecretsManagerSubscriptionCommand ;
2023-11-20 09:05:35 -05:00
private readonly IProviderRepository _providerRepository ;
Auth/PM-3275 - Changes to support TDE User without MP being able to Set a Password + misc refactoring (#3242)
* PM-3275 - Add new GetMasterPasswordPolicy endpoint which will allow authenticated clients to get an enabled MP org policy if it exists for the purposes of enforcing those policy requirements when setting a password.
* PM-3275 - AccountsController.cs - PostSetPasswordAsync - (1) Convert UserService.setPasswordAsync into new SetInitialMasterPasswordCommand (2) Refactor SetInitialMasterPasswordCommand to only accept post SSO users who are in the invited state
(3) Add TODOs for more cleanup work and more commands
* PM-3275 - Update AccountsControllerTests.cs to add new SetInitialMasterPasswordCommand
* PM-3275 - UserService.cs - Remove non implemented ChangePasswordAsync method
* PM-3275 - The new SetInitialMasterPasswordCommand leveraged the OrganizationService.cs AcceptUserAsync method so while I was in here I converted the AcceptUserAsync methods into a new AcceptOrgUserCommand.cs and turned the private method which accepted an existing org user public for use in the SetInitialMasterPasswordCommand
* PM-3275 - Dotnet format
* PM-3275 - Test SetInitialMasterPasswordCommand
* Dotnet format
* PM-3275 - In process AcceptOrgUserCommandTests.cs
* PM-3275 - Migrate changes from AC-244 / #3199 over into new AcceptOrgUserCommand
* PM-3275 - AcceptOrgUserCommand.cs - create data protector specifically for this command
* PM-3275 - Add TODO for renaming / removing overloading of methods to improve readability / clarity
* PM-3275 - AcceptOrgUserCommand.cs - refactor AcceptOrgUserAsync by OrgId to retrieve orgUser with _organizationUserRepository.GetByOrganizationAsync which gets a single user instead of a collection
* PM-3275 - AcceptOrgUserCommand.cs - update name in TODO for evaluation later
* PM-3275 / PM-1196 - (1) Slightly refactor SsoEmail2faSessionTokenable to provide public static GetTokenLifeTime() method for testing (2) Add missed tests to SsoEmail2faSessionTokenable in preparation for building tests for new OrgUserInviteTokenable.cs
* PM-3275 / PM-1196 - Removing SsoEmail2faSessionTokenable.cs changes + tests as I've handled that separately in a new PR (#3270) for newly created task PM-3925
* PM-3275 - ExpiringTokenable.cs - add clarifying comments to help distinguish between the Valid property and the TokenIsValid method.
* PM-3275 - Create OrgUserInviteTokenable.cs and add tests in OrgUserInviteTokenableTests.cs
* PM-3275 - OrganizationService.cs - Refactor Org User Invite methods to use new OrgUserInviteTokenable instead of manual creation of a token
* PM-3275 - OrgUserInviteTokenable.cs - clarify backwards compat note
* PM-3275 - AcceptOrgUserCommand.cs - Add TODOs + minor name refactor
* PM-3275 - AcceptOrgUserCommand.cs - replace method overloading with more easily readable names.
* PM-3275 - AcceptOrgUserCommand.cs - Update ValidateOrgUserInviteToken to add new token validation while maintaining backwards compatibility for 1 release.
* dotnet format
* PM-3275 - AcceptOrgUserCommand.cs - Move private method below where it is used
* PM-3275 - ServiceCollectionExtensions.cs - Must register IDataProtectorTokenFactory<OrgUserInviteTokenable> for new tokenable
* PM-3275 - OrgUserInviteTokenable needed access to global settings to set its token lifetime to the _globalSettings.OrganizationInviteExpirationHours value. Creating a factory seemed the most straightforward way to encapsulate the desired creation logic. Unsure if in the correct location in ServiceCollectionExtensions.cs but will figure that out later.
* PM-3275 - In process work of creating AcceptOrgUserCommandTests.cs
* PM-3275 - Remove no longer relevant AcceptOrgUser tests from OrganizationServiceTests.cs
* PM-3275 - Register OrgUserInviteTokenableFactory alongside tokenizer
* PM-3275 - AcceptOrgUserCommandTests.cs - AcceptOrgUserAsync basic test suite completed.
* PM-3275 - AcceptOrgUserCommandTests.cs - tweak test names
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Remove old tests from OrganizationServiceTests as no longer needed to reference (2) Add summary for SetupCommonAcceptOrgUserMocks (3) Get AcceptOrgUserByToken_OldToken_AcceptsUserAndVerifiesEmail passing
* PM-3275 - Create interface for OrgUserInviteTokenableFactory b/c that's the right thing to do + enables test substitution
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Start work on AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail (2) Create and use SetupCommonAcceptOrgUserByTokenMocks() (3) Create generic FakeDataProtectorTokenFactory for tokenable testing
* PM-3275 - (1) Get AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail test passing (2) Move FakeDataProtectorTokenFactory to own file
* PM-3275 - AcceptOrgUserCommandTests.cs - Finish up tests for AcceptOrgUserByTokenAsync
* PM-3275 - Add pseudo section comments
* PM-3275 - Clean up unused params on AcceptOrgUserByToken_EmailMismatch_ThrowsBadRequest test
* PM-3275 - (1) Tests written for AcceptOrgUserByOrgSsoIdAsync (2) Refactor happy path assertions into helper function AssertValidAcceptedOrgUser to reduce code duplication
* PM-3275 - Finish up testing AcceptOrgUserCommandTests.cs by adding tests for AcceptOrgUserByOrgIdAsync
* PM-3275 - Tweaking test naming to ensure consistency.
* PM-3275 - Bugfix - OrgUserInviteTokenableFactory implementation required when declaring singleton service in ServiceCollectionExtensions.cs
* PM-3275 - Resolve failing OrganizationServiceTests.cs
* dotnet format
* PM-3275 - PoliciesController.cs - GetMasterPasswordPolicy bugfix - for orgs without a MP policy, policy comes back as null and we should return notFound in that case.
* PM-3275 - Add PoliciesControllerTests.cs specifically for new GetMasterPasswordPolicy(...) endpoint.
* PM-3275 - dotnet format PoliciesControllerTests.cs
* PM-3275 - PoliciesController.cs - (1) Add tech debt task number (2) Properly flag endpoint as deprecated
* PM-3275 - Add new hasManageResetPasswordPermission property to ProfileResponseModel.cs primarily for sync so that we can condition client side if TDE user obtains elevated permissions
* PM-3275 - Fix AccountsControllerTests.cs
* PM-3275 - OrgUserInviteTokenable.cs - clarify TODO
* PM-3275 - AcceptOrgUserCommand.cs - Refactor token validation to use short circuiting to only run old token validation if new token validation fails.
* PM-3275 - OrgUserInviteTokenable.cs - (1) Add new static methods to centralize validation logic to avoid repetition (2) Add new token validation method so we can avoid having to pass in a full org user (and hitting the db to do so)
* PM-3275 - Realized that the old token validation was used in the PoliciesController.cs (existing user clicks invite link in email and goes to log in) and UserService.cs (user clicks invite link in email and registers for a new acct). Added tech debt item for cleaning up backwards compatibility in future.
* dotnet format
* PM-3275 - (1) AccountsController.cs - Update PostSetPasswordAsync SetPasswordRequestModel to allow null keys for the case where we have a TDE user who obtains elevated permissions - they already have a user public and user encrypted private key saved in the db. (2) AccountsControllerTests.cs - test PostSetPasswordAsync scenarios to ensure changes will work as expected.
* PM-3275 - PR review feedback - (1) set CurrentContext to private (2) Refactor GetProfile to use variables to improve clarity and simplify debugging.
* PM-3275 - SyncController.cs - PR Review Feedback - Set current context as private instead of protected.
* PM-3275 - CurrentContextExtensions.cs - PR Feedback - move parenthesis up from own line.
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - Replace unnecessary variable
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - PR Feedback - Add expected outcome statement to test name
* PM-3275 - Set Initial Password command and tests - PR Feedback changes - (1) Rename orgIdentifier --> OrgSsoIdentifier for clarity (2) Update SetInitialMasterPasswordAsync to not allow null orgSsoId with explicit message saying this vs letting null org trigger invalid organization (3) Add test to cover this new scenario.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Move summary from implementation to interface to better respect standards and the fact that the interface is the more seen piece of code.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, rename AcceptOrgUserByTokenAsync -> AcceptOrgUserByEmailTokenAsync + replace generic name token with emailToken
* PM-3275 - OrganizationService.cs - Per PR feedback, remove dupe line
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove new lines in error messages for consistency.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Per PR feedback, adjust formatting of constructor for improved readability.
* PM-3275 - CurrentContextExtensions.cs - Refactor AnyOrgUserHasManageResetPasswordPermission per PR feedback to remove unnecessary var.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove completed TODO
* PM-3275 - PoliciesController.cs - Per PR feedback, update GetByInvitedUser param to be guid instead of string.
* PM-3275 - OrgUserInviteTokenable.cs - per PR feedback, add tech debt item info.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, use const purpose from tokenable instead of magic string.
* PM-3275 - Restore non duplicate line to fix tests
* PM-3275 - Per PR feedback, revert all sync controller changes as the ProfileResponseModel.organizations array has org objects which have permissions which have the ManageResetPassword permission. So, I have the information that I need clientside already to determine if the user has the ManageResetPassword in any org.
* PM-3275 - PoliciesControllerTests.cs - Update imports as the PoliciesController was moved under the admin console team's domain.
* PM-3275 - Resolve issues from merge conflict resolutions to get solution building.
* PM-3275 / PM-4633 - PoliciesController.cs - use orgUserId to look up user instead of orgId. Oops.
* Fix user service tests
* Resolve merge conflict
2023-11-02 11:02:25 -04:00
private readonly IOrgUserInviteTokenableFactory _orgUserInviteTokenableFactory ;
private readonly IDataProtectorTokenFactory < OrgUserInviteTokenable > _orgUserInviteTokenDataFactory ;
[AC-1373] Flexible Collections (#3245)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* fix: merge conflict resolution
* [AC-1174] CollectionUser and CollectionGroup authorization handlers (#3194)
* [AC-1174] Introduce BulkAuthorizationHandler.cs
* [AC-1174] Introduce CollectionUserAuthorizationHandler
* [AC-1174] Add CreateForNewCollection CollectionUser requirement
* [AC-1174] Add some more details to CollectionCustomization
* [AC-1174] Formatting
* [AC-1174] Add CollectionGroupOperation.cs
* [AC-1174] Introduce CollectionGroupAuthorizationHandler.cs
* [AC-1174] Cleanup CollectionFixture customization
Implement and use re-usable extension method to support seeded Guids
* [AC-1174] Introduce WithValueFromList AutoFixtureExtensions
Modify CollectionCustomization to use multiple organization Ids for auto generated test data
* [AC-1174] Simplify CollectionUserAuthorizationHandler.cs
Modify the authorization handler to only perform authorization logic. Validation logic will need to be handled by any calling commands/controllers instead.
* [AC-1174] Introduce shared CollectionAccessAuthorizationHandlerBase
A shared base authorization handler was created for both CollectionUser and CollectionGroup resources, as they share the same underlying management authorization logic.
* [AC-1174] Update CollectionUserAuthorizationHandler and CollectionGroupAuthorizationHandler to use the new CollectionAccessAuthorizationHandlerBase class
* [AC-1174] Formatting
* [AC-1174] Cleanup typo and redundant ToList() call
* [AC-1174] Add check for provider users
* [AC-1174] Reduce nested loops
* [AC-1174] Introduce ICollectionAccess.cs
* [AC-1174] Remove individual CollectionGroup and CollectionUser auth handlers and use base class instead
* [AC-1174] Tweak unit test to fail minimally
* [AC-1174] Reorganize authorization handlers in Core project
* [AC-1174] Introduce new AddCoreAuthorizationHandlers() extension method
* [AC-1174] Move CollectionAccessAuthorizationHandler into Api project
* [AC-1174] Move CollectionFixture to Vault folder
* [AC-1174] Rename operation to CreateUpdateDelete
* [AC-1174] Require single organization for collection access authorization handler
- Add requirement that all target collections must belong to the same organization
- Simplify logic related to multiple organizations
- Update tests and helpers
- Use ToHashSet to improve lookup time
* [AC-1174] Fix null reference exception
* [AC-1174] Throw bad request exception when collections belong to different organizations
* [AC-1174] Switch to CollectionAuthorizationHandler instead of CollectionAccessAuthorizationHandler to reduce complexity
* Fix improper merge conflict resolution
* fix: add permission check for collection management api, refs AC-1647 (#3252)
* [AC-1125] Enforce org setting for creating/deleting collections (#3241)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* feat: created collection auth handler/operations, added LimitCollectionCdOwnerAdmin to CurrentContentOrganization, refs AC-1125
* feat: create vault service collection extensions and register with base services, refs AC-1125
* feat: deprecated CurrentContext.CreateNewCollections, refs AC-1125
* feat: deprecate DeleteAnyCollection for single resource usages, refs AC-1125
* feat: move service registration to api, update references, refs AC-1125
* feat: add bulk delete authorization handler, refs AC-1125
* feat: always assign user and give manage access on create, refs AC-1125
* fix: updated CurrentContextOrganization type, refs AC-1125
* feat: combined existing collection authorization handlers/operations, refs AC-1125
* fix: OrganizationServiceTests -> CurrentContentOrganization typo, refs AC-1125
* fix: format, refs AC-1125
* fix: update collection controller tests, refs AC-1125
* fix: dotnet format, refs AC-1125
* feat: removed extra BulkAuthorizationHandler, refs AC-1125
* fix: dotnet format, refs AC-1125
* fix: change string to guid for org id, update bulk delete request model, refs AC-1125
* fix: remove delete many collection check, refs AC-1125
* fix: clean up collection auth handler, refs AC-1125
* fix: format fix for CollectionOperations, refs AC-1125
* fix: removed unnecessary owner check, add org null check to custom permission validation, refs AC-1125
* fix: remove unused methods in CurrentContext, refs AC-1125
* fix: removed obsolete test, fixed failling delete many test, refs AC-1125
* fix: CollectionAuthorizationHandlerTests fixes, refs AC-1125
* fix: OrganizationServiceTests fix broken test by mocking GetOrganization, refs AC-1125
* fix: CollectionAuthorizationHandler - remove unused repository, refs AC-1125
* feat: moved UserId null check to common method, refs AC-1125
* fix: updated auth handler tests to remove dependency on requirement for common code checks, refs AC-1125
* feat: updated conditionals/comments for create/delete methods within colleciton auth handler, refs AC-1125
* feat: added create/delete collection auth handler success methods, refs AC-1125
* fix: new up permissions to prevent excessive null checks, refs AC-1125
* fix: remove old reference to CreateNewCollections, refs AC-1125
* fix: typo within ViewAssignedCollections method, refs AC-1125
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
* refactor: remove organizationId from CollectionBulkDeleteRequestModel, refs AC-1649 (#3282)
* [AC-1174] Bulk Collection Management (#3229)
* [AC-1174] Update SelectionReadOnlyRequestModel to use Guid for Id property
* [AC-1174] Introduce initial bulk-access collection endpoint
* [AC-1174] Introduce BulkAddCollectionAccessCommand and validation logic/tests
* [AC-1174] Add CreateOrUpdateAccessMany method to CollectionRepository
* [AC-1174] Add event logs for bulk add collection access command
* [AC-1174] Add User_BumpAccountRevisionDateByCollectionIds and database migration script
* [AC-1174] Implement EF repository method
* [AC-1174] Improve null checks
* [AC-1174] Remove unnecessary BulkCollectionAccessRequestModel helpers
* [AC-1174] Add unit tests for new controller endpoint
* [AC-1174] Fix formatting
* [AC-1174] Remove comment
* [AC-1174] Remove redundant organizationId parameter
* [AC-1174] Ensure user and group Ids are distinct
* [AC-1174] Cleanup tests based on PR feedback
* [AC-1174] Formatting
* [AC-1174] Update CollectionGroup alias in the sproc
* [AC-1174] Add some additional comments to SQL sproc
* [AC-1174] Add comment explaining additional SaveChangesAsync call
---------
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
* [AC-1646] Rename LimitCollectionCdOwnerAdmin column (#3300)
* Rename LimitCollectionCdOwnerAdmin -> LimitCollectionCreationDeletion
* Rename and bump migration script
* [AC-1666] Removed EditAnyCollection from Create/Delete permission checks (#3301)
* fix: remove EditAnyCollection from Create/Delete permission check, refs AC-1666
* fix: updated comment, refs AC-1666
* [AC-1669] Bug - Remove obsolete assignUserId from CollectionService.SaveAsync(...) (#3312)
* fix: remove AssignUserId from CollectionService.SaveAsync, refs AC-1669
* fix: add manage access conditional before creating collection, refs AC-1669
* fix: move access logic for create/update, fix all tests, refs AC-1669
* fix: add CollectionAccessSelection fixture, update tests, update bad reqeuest message, refs AC-1669
* fix: format, refs AC-1669
* fix: update null params with specific arg.is null checks, refs Ac-1669
* fix: update attribute class name, refs AC-1669
* [AC-1713] [Flexible collections] Add feature flags to server (#3334)
* Add feature flags for FlexibleCollections and BulkCollectionAccess
* Flag new routes and behaviour
---------
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
* Add joint codeownership for auth handlers (#3346)
* [AC-1717] Update default values for LimitCollectionCreationDeletion (#3365)
* Change default value in organization create sproc to 1
* Drop old column name still present in some QA instances
* Set LimitCollectionCreationDeletion value in code based on feature flag
* Fix: add missing namespace after merging in master
* Fix: add missing namespace after merging in master
* [AC-1683] Fix DB migrations for new Manage permission (#3307)
* [AC-1683] Update migration script and introduce V2 procedures and types
* [AC-1683] Update repository calls to use new V2 procedures / types
* [AC-1684] Update bulk add collection migration script to use new V2 type
* [AC-1683] Undo Manage changes to more original procedures
* [AC-1683] Restore whitespace changes
* [AC-1683] Clarify comments regarding explicit column lists
* [AC-1683] Update migration script dates
* [AC-1683] Split the migration script for readability
* [AC-1683] Re-name SelectReadOnlyArray_V2 to CollectionAccessSelectionType
* [AC-1648] [Flexible Collections] Bump migration scripts before feature branch merge (#3371)
* Bump dates on sql migration scripts
* Bump date on ef migrations
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
Co-authored-by: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com>
Co-authored-by: Vincent Salucci <vincesalucci21@gmail.com>
Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
2023-11-01 19:30:52 +10:00
private readonly IFeatureService _featureService ;
2022-08-29 16:06:55 -04:00
2017-03-03 00:07:11 -05:00
public OrganizationService (
IOrganizationRepository organizationRepository ,
2017-03-04 21:28:41 -05:00
IOrganizationUserRepository organizationUserRepository ,
2017-04-27 09:19:30 -04:00
ICollectionRepository collectionRepository ,
2017-03-23 00:17:34 -04:00
IUserRepository userRepository ,
2017-05-13 12:00:40 -04:00
IGroupRepository groupRepository ,
2017-04-21 14:22:32 -04:00
IMailService mailService ,
2017-05-26 22:52:50 -04:00
IPushNotificationService pushNotificationService ,
2017-08-11 08:57:31 -04:00
IPushRegistrationService pushRegistrationService ,
2017-08-14 20:57:45 -04:00
IDeviceRepository deviceRepository ,
ILicensingService licensingService ,
2017-12-01 16:00:30 -05:00
IEventService eventService ,
2017-12-19 16:02:39 -05:00
IApplicationCacheService applicationCacheService ,
2019-02-08 23:53:09 -05:00
IPaymentService paymentService ,
2020-01-15 15:00:54 -05:00
IPolicyRepository policyRepository ,
2023-05-12 08:22:19 +01:00
IPolicyService policyService ,
2020-07-22 09:38:39 -04:00
ISsoConfigRepository ssoConfigRepository ,
2020-08-26 14:12:04 -04:00
ISsoUserRepository ssoUserRepository ,
2020-07-07 12:01:34 -04:00
IReferenceEventService referenceEventService ,
2021-09-23 06:36:08 -04:00
IGlobalSettings globalSettings ,
2022-05-10 17:12:09 -04:00
IOrganizationApiKeyRepository organizationApiKeyRepository ,
2021-09-23 06:36:08 -04:00
ICurrentContext currentContext ,
2023-01-26 11:51:26 -05:00
ILogger < OrganizationService > logger ,
IProviderOrganizationRepository providerOrganizationRepository ,
2023-08-05 07:51:12 +10:00
IProviderUserRepository providerUserRepository ,
ICountNewSmSeatsRequiredQuery countNewSmSeatsRequiredQuery ,
Auth/PM-3275 - Changes to support TDE User without MP being able to Set a Password + misc refactoring (#3242)
* PM-3275 - Add new GetMasterPasswordPolicy endpoint which will allow authenticated clients to get an enabled MP org policy if it exists for the purposes of enforcing those policy requirements when setting a password.
* PM-3275 - AccountsController.cs - PostSetPasswordAsync - (1) Convert UserService.setPasswordAsync into new SetInitialMasterPasswordCommand (2) Refactor SetInitialMasterPasswordCommand to only accept post SSO users who are in the invited state
(3) Add TODOs for more cleanup work and more commands
* PM-3275 - Update AccountsControllerTests.cs to add new SetInitialMasterPasswordCommand
* PM-3275 - UserService.cs - Remove non implemented ChangePasswordAsync method
* PM-3275 - The new SetInitialMasterPasswordCommand leveraged the OrganizationService.cs AcceptUserAsync method so while I was in here I converted the AcceptUserAsync methods into a new AcceptOrgUserCommand.cs and turned the private method which accepted an existing org user public for use in the SetInitialMasterPasswordCommand
* PM-3275 - Dotnet format
* PM-3275 - Test SetInitialMasterPasswordCommand
* Dotnet format
* PM-3275 - In process AcceptOrgUserCommandTests.cs
* PM-3275 - Migrate changes from AC-244 / #3199 over into new AcceptOrgUserCommand
* PM-3275 - AcceptOrgUserCommand.cs - create data protector specifically for this command
* PM-3275 - Add TODO for renaming / removing overloading of methods to improve readability / clarity
* PM-3275 - AcceptOrgUserCommand.cs - refactor AcceptOrgUserAsync by OrgId to retrieve orgUser with _organizationUserRepository.GetByOrganizationAsync which gets a single user instead of a collection
* PM-3275 - AcceptOrgUserCommand.cs - update name in TODO for evaluation later
* PM-3275 / PM-1196 - (1) Slightly refactor SsoEmail2faSessionTokenable to provide public static GetTokenLifeTime() method for testing (2) Add missed tests to SsoEmail2faSessionTokenable in preparation for building tests for new OrgUserInviteTokenable.cs
* PM-3275 / PM-1196 - Removing SsoEmail2faSessionTokenable.cs changes + tests as I've handled that separately in a new PR (#3270) for newly created task PM-3925
* PM-3275 - ExpiringTokenable.cs - add clarifying comments to help distinguish between the Valid property and the TokenIsValid method.
* PM-3275 - Create OrgUserInviteTokenable.cs and add tests in OrgUserInviteTokenableTests.cs
* PM-3275 - OrganizationService.cs - Refactor Org User Invite methods to use new OrgUserInviteTokenable instead of manual creation of a token
* PM-3275 - OrgUserInviteTokenable.cs - clarify backwards compat note
* PM-3275 - AcceptOrgUserCommand.cs - Add TODOs + minor name refactor
* PM-3275 - AcceptOrgUserCommand.cs - replace method overloading with more easily readable names.
* PM-3275 - AcceptOrgUserCommand.cs - Update ValidateOrgUserInviteToken to add new token validation while maintaining backwards compatibility for 1 release.
* dotnet format
* PM-3275 - AcceptOrgUserCommand.cs - Move private method below where it is used
* PM-3275 - ServiceCollectionExtensions.cs - Must register IDataProtectorTokenFactory<OrgUserInviteTokenable> for new tokenable
* PM-3275 - OrgUserInviteTokenable needed access to global settings to set its token lifetime to the _globalSettings.OrganizationInviteExpirationHours value. Creating a factory seemed the most straightforward way to encapsulate the desired creation logic. Unsure if in the correct location in ServiceCollectionExtensions.cs but will figure that out later.
* PM-3275 - In process work of creating AcceptOrgUserCommandTests.cs
* PM-3275 - Remove no longer relevant AcceptOrgUser tests from OrganizationServiceTests.cs
* PM-3275 - Register OrgUserInviteTokenableFactory alongside tokenizer
* PM-3275 - AcceptOrgUserCommandTests.cs - AcceptOrgUserAsync basic test suite completed.
* PM-3275 - AcceptOrgUserCommandTests.cs - tweak test names
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Remove old tests from OrganizationServiceTests as no longer needed to reference (2) Add summary for SetupCommonAcceptOrgUserMocks (3) Get AcceptOrgUserByToken_OldToken_AcceptsUserAndVerifiesEmail passing
* PM-3275 - Create interface for OrgUserInviteTokenableFactory b/c that's the right thing to do + enables test substitution
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Start work on AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail (2) Create and use SetupCommonAcceptOrgUserByTokenMocks() (3) Create generic FakeDataProtectorTokenFactory for tokenable testing
* PM-3275 - (1) Get AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail test passing (2) Move FakeDataProtectorTokenFactory to own file
* PM-3275 - AcceptOrgUserCommandTests.cs - Finish up tests for AcceptOrgUserByTokenAsync
* PM-3275 - Add pseudo section comments
* PM-3275 - Clean up unused params on AcceptOrgUserByToken_EmailMismatch_ThrowsBadRequest test
* PM-3275 - (1) Tests written for AcceptOrgUserByOrgSsoIdAsync (2) Refactor happy path assertions into helper function AssertValidAcceptedOrgUser to reduce code duplication
* PM-3275 - Finish up testing AcceptOrgUserCommandTests.cs by adding tests for AcceptOrgUserByOrgIdAsync
* PM-3275 - Tweaking test naming to ensure consistency.
* PM-3275 - Bugfix - OrgUserInviteTokenableFactory implementation required when declaring singleton service in ServiceCollectionExtensions.cs
* PM-3275 - Resolve failing OrganizationServiceTests.cs
* dotnet format
* PM-3275 - PoliciesController.cs - GetMasterPasswordPolicy bugfix - for orgs without a MP policy, policy comes back as null and we should return notFound in that case.
* PM-3275 - Add PoliciesControllerTests.cs specifically for new GetMasterPasswordPolicy(...) endpoint.
* PM-3275 - dotnet format PoliciesControllerTests.cs
* PM-3275 - PoliciesController.cs - (1) Add tech debt task number (2) Properly flag endpoint as deprecated
* PM-3275 - Add new hasManageResetPasswordPermission property to ProfileResponseModel.cs primarily for sync so that we can condition client side if TDE user obtains elevated permissions
* PM-3275 - Fix AccountsControllerTests.cs
* PM-3275 - OrgUserInviteTokenable.cs - clarify TODO
* PM-3275 - AcceptOrgUserCommand.cs - Refactor token validation to use short circuiting to only run old token validation if new token validation fails.
* PM-3275 - OrgUserInviteTokenable.cs - (1) Add new static methods to centralize validation logic to avoid repetition (2) Add new token validation method so we can avoid having to pass in a full org user (and hitting the db to do so)
* PM-3275 - Realized that the old token validation was used in the PoliciesController.cs (existing user clicks invite link in email and goes to log in) and UserService.cs (user clicks invite link in email and registers for a new acct). Added tech debt item for cleaning up backwards compatibility in future.
* dotnet format
* PM-3275 - (1) AccountsController.cs - Update PostSetPasswordAsync SetPasswordRequestModel to allow null keys for the case where we have a TDE user who obtains elevated permissions - they already have a user public and user encrypted private key saved in the db. (2) AccountsControllerTests.cs - test PostSetPasswordAsync scenarios to ensure changes will work as expected.
* PM-3275 - PR review feedback - (1) set CurrentContext to private (2) Refactor GetProfile to use variables to improve clarity and simplify debugging.
* PM-3275 - SyncController.cs - PR Review Feedback - Set current context as private instead of protected.
* PM-3275 - CurrentContextExtensions.cs - PR Feedback - move parenthesis up from own line.
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - Replace unnecessary variable
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - PR Feedback - Add expected outcome statement to test name
* PM-3275 - Set Initial Password command and tests - PR Feedback changes - (1) Rename orgIdentifier --> OrgSsoIdentifier for clarity (2) Update SetInitialMasterPasswordAsync to not allow null orgSsoId with explicit message saying this vs letting null org trigger invalid organization (3) Add test to cover this new scenario.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Move summary from implementation to interface to better respect standards and the fact that the interface is the more seen piece of code.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, rename AcceptOrgUserByTokenAsync -> AcceptOrgUserByEmailTokenAsync + replace generic name token with emailToken
* PM-3275 - OrganizationService.cs - Per PR feedback, remove dupe line
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove new lines in error messages for consistency.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Per PR feedback, adjust formatting of constructor for improved readability.
* PM-3275 - CurrentContextExtensions.cs - Refactor AnyOrgUserHasManageResetPasswordPermission per PR feedback to remove unnecessary var.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove completed TODO
* PM-3275 - PoliciesController.cs - Per PR feedback, update GetByInvitedUser param to be guid instead of string.
* PM-3275 - OrgUserInviteTokenable.cs - per PR feedback, add tech debt item info.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, use const purpose from tokenable instead of magic string.
* PM-3275 - Restore non duplicate line to fix tests
* PM-3275 - Per PR feedback, revert all sync controller changes as the ProfileResponseModel.organizations array has org objects which have permissions which have the ManageResetPassword permission. So, I have the information that I need clientside already to determine if the user has the ManageResetPassword in any org.
* PM-3275 - PoliciesControllerTests.cs - Update imports as the PoliciesController was moved under the admin console team's domain.
* PM-3275 - Resolve issues from merge conflict resolutions to get solution building.
* PM-3275 / PM-4633 - PoliciesController.cs - use orgUserId to look up user instead of orgId. Oops.
* Fix user service tests
* Resolve merge conflict
2023-11-02 11:02:25 -04:00
IOrgUserInviteTokenableFactory orgUserInviteTokenableFactory ,
IDataProtectorTokenFactory < OrgUserInviteTokenable > orgUserInviteTokenDataFactory ,
[AC-1373] Flexible Collections (#3245)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* fix: merge conflict resolution
* [AC-1174] CollectionUser and CollectionGroup authorization handlers (#3194)
* [AC-1174] Introduce BulkAuthorizationHandler.cs
* [AC-1174] Introduce CollectionUserAuthorizationHandler
* [AC-1174] Add CreateForNewCollection CollectionUser requirement
* [AC-1174] Add some more details to CollectionCustomization
* [AC-1174] Formatting
* [AC-1174] Add CollectionGroupOperation.cs
* [AC-1174] Introduce CollectionGroupAuthorizationHandler.cs
* [AC-1174] Cleanup CollectionFixture customization
Implement and use re-usable extension method to support seeded Guids
* [AC-1174] Introduce WithValueFromList AutoFixtureExtensions
Modify CollectionCustomization to use multiple organization Ids for auto generated test data
* [AC-1174] Simplify CollectionUserAuthorizationHandler.cs
Modify the authorization handler to only perform authorization logic. Validation logic will need to be handled by any calling commands/controllers instead.
* [AC-1174] Introduce shared CollectionAccessAuthorizationHandlerBase
A shared base authorization handler was created for both CollectionUser and CollectionGroup resources, as they share the same underlying management authorization logic.
* [AC-1174] Update CollectionUserAuthorizationHandler and CollectionGroupAuthorizationHandler to use the new CollectionAccessAuthorizationHandlerBase class
* [AC-1174] Formatting
* [AC-1174] Cleanup typo and redundant ToList() call
* [AC-1174] Add check for provider users
* [AC-1174] Reduce nested loops
* [AC-1174] Introduce ICollectionAccess.cs
* [AC-1174] Remove individual CollectionGroup and CollectionUser auth handlers and use base class instead
* [AC-1174] Tweak unit test to fail minimally
* [AC-1174] Reorganize authorization handlers in Core project
* [AC-1174] Introduce new AddCoreAuthorizationHandlers() extension method
* [AC-1174] Move CollectionAccessAuthorizationHandler into Api project
* [AC-1174] Move CollectionFixture to Vault folder
* [AC-1174] Rename operation to CreateUpdateDelete
* [AC-1174] Require single organization for collection access authorization handler
- Add requirement that all target collections must belong to the same organization
- Simplify logic related to multiple organizations
- Update tests and helpers
- Use ToHashSet to improve lookup time
* [AC-1174] Fix null reference exception
* [AC-1174] Throw bad request exception when collections belong to different organizations
* [AC-1174] Switch to CollectionAuthorizationHandler instead of CollectionAccessAuthorizationHandler to reduce complexity
* Fix improper merge conflict resolution
* fix: add permission check for collection management api, refs AC-1647 (#3252)
* [AC-1125] Enforce org setting for creating/deleting collections (#3241)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* feat: created collection auth handler/operations, added LimitCollectionCdOwnerAdmin to CurrentContentOrganization, refs AC-1125
* feat: create vault service collection extensions and register with base services, refs AC-1125
* feat: deprecated CurrentContext.CreateNewCollections, refs AC-1125
* feat: deprecate DeleteAnyCollection for single resource usages, refs AC-1125
* feat: move service registration to api, update references, refs AC-1125
* feat: add bulk delete authorization handler, refs AC-1125
* feat: always assign user and give manage access on create, refs AC-1125
* fix: updated CurrentContextOrganization type, refs AC-1125
* feat: combined existing collection authorization handlers/operations, refs AC-1125
* fix: OrganizationServiceTests -> CurrentContentOrganization typo, refs AC-1125
* fix: format, refs AC-1125
* fix: update collection controller tests, refs AC-1125
* fix: dotnet format, refs AC-1125
* feat: removed extra BulkAuthorizationHandler, refs AC-1125
* fix: dotnet format, refs AC-1125
* fix: change string to guid for org id, update bulk delete request model, refs AC-1125
* fix: remove delete many collection check, refs AC-1125
* fix: clean up collection auth handler, refs AC-1125
* fix: format fix for CollectionOperations, refs AC-1125
* fix: removed unnecessary owner check, add org null check to custom permission validation, refs AC-1125
* fix: remove unused methods in CurrentContext, refs AC-1125
* fix: removed obsolete test, fixed failling delete many test, refs AC-1125
* fix: CollectionAuthorizationHandlerTests fixes, refs AC-1125
* fix: OrganizationServiceTests fix broken test by mocking GetOrganization, refs AC-1125
* fix: CollectionAuthorizationHandler - remove unused repository, refs AC-1125
* feat: moved UserId null check to common method, refs AC-1125
* fix: updated auth handler tests to remove dependency on requirement for common code checks, refs AC-1125
* feat: updated conditionals/comments for create/delete methods within colleciton auth handler, refs AC-1125
* feat: added create/delete collection auth handler success methods, refs AC-1125
* fix: new up permissions to prevent excessive null checks, refs AC-1125
* fix: remove old reference to CreateNewCollections, refs AC-1125
* fix: typo within ViewAssignedCollections method, refs AC-1125
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
* refactor: remove organizationId from CollectionBulkDeleteRequestModel, refs AC-1649 (#3282)
* [AC-1174] Bulk Collection Management (#3229)
* [AC-1174] Update SelectionReadOnlyRequestModel to use Guid for Id property
* [AC-1174] Introduce initial bulk-access collection endpoint
* [AC-1174] Introduce BulkAddCollectionAccessCommand and validation logic/tests
* [AC-1174] Add CreateOrUpdateAccessMany method to CollectionRepository
* [AC-1174] Add event logs for bulk add collection access command
* [AC-1174] Add User_BumpAccountRevisionDateByCollectionIds and database migration script
* [AC-1174] Implement EF repository method
* [AC-1174] Improve null checks
* [AC-1174] Remove unnecessary BulkCollectionAccessRequestModel helpers
* [AC-1174] Add unit tests for new controller endpoint
* [AC-1174] Fix formatting
* [AC-1174] Remove comment
* [AC-1174] Remove redundant organizationId parameter
* [AC-1174] Ensure user and group Ids are distinct
* [AC-1174] Cleanup tests based on PR feedback
* [AC-1174] Formatting
* [AC-1174] Update CollectionGroup alias in the sproc
* [AC-1174] Add some additional comments to SQL sproc
* [AC-1174] Add comment explaining additional SaveChangesAsync call
---------
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
* [AC-1646] Rename LimitCollectionCdOwnerAdmin column (#3300)
* Rename LimitCollectionCdOwnerAdmin -> LimitCollectionCreationDeletion
* Rename and bump migration script
* [AC-1666] Removed EditAnyCollection from Create/Delete permission checks (#3301)
* fix: remove EditAnyCollection from Create/Delete permission check, refs AC-1666
* fix: updated comment, refs AC-1666
* [AC-1669] Bug - Remove obsolete assignUserId from CollectionService.SaveAsync(...) (#3312)
* fix: remove AssignUserId from CollectionService.SaveAsync, refs AC-1669
* fix: add manage access conditional before creating collection, refs AC-1669
* fix: move access logic for create/update, fix all tests, refs AC-1669
* fix: add CollectionAccessSelection fixture, update tests, update bad reqeuest message, refs AC-1669
* fix: format, refs AC-1669
* fix: update null params with specific arg.is null checks, refs Ac-1669
* fix: update attribute class name, refs AC-1669
* [AC-1713] [Flexible collections] Add feature flags to server (#3334)
* Add feature flags for FlexibleCollections and BulkCollectionAccess
* Flag new routes and behaviour
---------
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
* Add joint codeownership for auth handlers (#3346)
* [AC-1717] Update default values for LimitCollectionCreationDeletion (#3365)
* Change default value in organization create sproc to 1
* Drop old column name still present in some QA instances
* Set LimitCollectionCreationDeletion value in code based on feature flag
* Fix: add missing namespace after merging in master
* Fix: add missing namespace after merging in master
* [AC-1683] Fix DB migrations for new Manage permission (#3307)
* [AC-1683] Update migration script and introduce V2 procedures and types
* [AC-1683] Update repository calls to use new V2 procedures / types
* [AC-1684] Update bulk add collection migration script to use new V2 type
* [AC-1683] Undo Manage changes to more original procedures
* [AC-1683] Restore whitespace changes
* [AC-1683] Clarify comments regarding explicit column lists
* [AC-1683] Update migration script dates
* [AC-1683] Split the migration script for readability
* [AC-1683] Re-name SelectReadOnlyArray_V2 to CollectionAccessSelectionType
* [AC-1648] [Flexible Collections] Bump migration scripts before feature branch merge (#3371)
* Bump dates on sql migration scripts
* Bump date on ef migrations
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
Co-authored-by: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com>
Co-authored-by: Vincent Salucci <vincesalucci21@gmail.com>
Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
2023-11-01 19:30:52 +10:00
IUpdateSecretsManagerSubscriptionCommand updateSecretsManagerSubscriptionCommand ,
2023-11-20 09:05:35 -05:00
IProviderRepository providerRepository ,
[AC-1373] Flexible Collections (#3245)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* fix: merge conflict resolution
* [AC-1174] CollectionUser and CollectionGroup authorization handlers (#3194)
* [AC-1174] Introduce BulkAuthorizationHandler.cs
* [AC-1174] Introduce CollectionUserAuthorizationHandler
* [AC-1174] Add CreateForNewCollection CollectionUser requirement
* [AC-1174] Add some more details to CollectionCustomization
* [AC-1174] Formatting
* [AC-1174] Add CollectionGroupOperation.cs
* [AC-1174] Introduce CollectionGroupAuthorizationHandler.cs
* [AC-1174] Cleanup CollectionFixture customization
Implement and use re-usable extension method to support seeded Guids
* [AC-1174] Introduce WithValueFromList AutoFixtureExtensions
Modify CollectionCustomization to use multiple organization Ids for auto generated test data
* [AC-1174] Simplify CollectionUserAuthorizationHandler.cs
Modify the authorization handler to only perform authorization logic. Validation logic will need to be handled by any calling commands/controllers instead.
* [AC-1174] Introduce shared CollectionAccessAuthorizationHandlerBase
A shared base authorization handler was created for both CollectionUser and CollectionGroup resources, as they share the same underlying management authorization logic.
* [AC-1174] Update CollectionUserAuthorizationHandler and CollectionGroupAuthorizationHandler to use the new CollectionAccessAuthorizationHandlerBase class
* [AC-1174] Formatting
* [AC-1174] Cleanup typo and redundant ToList() call
* [AC-1174] Add check for provider users
* [AC-1174] Reduce nested loops
* [AC-1174] Introduce ICollectionAccess.cs
* [AC-1174] Remove individual CollectionGroup and CollectionUser auth handlers and use base class instead
* [AC-1174] Tweak unit test to fail minimally
* [AC-1174] Reorganize authorization handlers in Core project
* [AC-1174] Introduce new AddCoreAuthorizationHandlers() extension method
* [AC-1174] Move CollectionAccessAuthorizationHandler into Api project
* [AC-1174] Move CollectionFixture to Vault folder
* [AC-1174] Rename operation to CreateUpdateDelete
* [AC-1174] Require single organization for collection access authorization handler
- Add requirement that all target collections must belong to the same organization
- Simplify logic related to multiple organizations
- Update tests and helpers
- Use ToHashSet to improve lookup time
* [AC-1174] Fix null reference exception
* [AC-1174] Throw bad request exception when collections belong to different organizations
* [AC-1174] Switch to CollectionAuthorizationHandler instead of CollectionAccessAuthorizationHandler to reduce complexity
* Fix improper merge conflict resolution
* fix: add permission check for collection management api, refs AC-1647 (#3252)
* [AC-1125] Enforce org setting for creating/deleting collections (#3241)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* feat: created collection auth handler/operations, added LimitCollectionCdOwnerAdmin to CurrentContentOrganization, refs AC-1125
* feat: create vault service collection extensions and register with base services, refs AC-1125
* feat: deprecated CurrentContext.CreateNewCollections, refs AC-1125
* feat: deprecate DeleteAnyCollection for single resource usages, refs AC-1125
* feat: move service registration to api, update references, refs AC-1125
* feat: add bulk delete authorization handler, refs AC-1125
* feat: always assign user and give manage access on create, refs AC-1125
* fix: updated CurrentContextOrganization type, refs AC-1125
* feat: combined existing collection authorization handlers/operations, refs AC-1125
* fix: OrganizationServiceTests -> CurrentContentOrganization typo, refs AC-1125
* fix: format, refs AC-1125
* fix: update collection controller tests, refs AC-1125
* fix: dotnet format, refs AC-1125
* feat: removed extra BulkAuthorizationHandler, refs AC-1125
* fix: dotnet format, refs AC-1125
* fix: change string to guid for org id, update bulk delete request model, refs AC-1125
* fix: remove delete many collection check, refs AC-1125
* fix: clean up collection auth handler, refs AC-1125
* fix: format fix for CollectionOperations, refs AC-1125
* fix: removed unnecessary owner check, add org null check to custom permission validation, refs AC-1125
* fix: remove unused methods in CurrentContext, refs AC-1125
* fix: removed obsolete test, fixed failling delete many test, refs AC-1125
* fix: CollectionAuthorizationHandlerTests fixes, refs AC-1125
* fix: OrganizationServiceTests fix broken test by mocking GetOrganization, refs AC-1125
* fix: CollectionAuthorizationHandler - remove unused repository, refs AC-1125
* feat: moved UserId null check to common method, refs AC-1125
* fix: updated auth handler tests to remove dependency on requirement for common code checks, refs AC-1125
* feat: updated conditionals/comments for create/delete methods within colleciton auth handler, refs AC-1125
* feat: added create/delete collection auth handler success methods, refs AC-1125
* fix: new up permissions to prevent excessive null checks, refs AC-1125
* fix: remove old reference to CreateNewCollections, refs AC-1125
* fix: typo within ViewAssignedCollections method, refs AC-1125
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
* refactor: remove organizationId from CollectionBulkDeleteRequestModel, refs AC-1649 (#3282)
* [AC-1174] Bulk Collection Management (#3229)
* [AC-1174] Update SelectionReadOnlyRequestModel to use Guid for Id property
* [AC-1174] Introduce initial bulk-access collection endpoint
* [AC-1174] Introduce BulkAddCollectionAccessCommand and validation logic/tests
* [AC-1174] Add CreateOrUpdateAccessMany method to CollectionRepository
* [AC-1174] Add event logs for bulk add collection access command
* [AC-1174] Add User_BumpAccountRevisionDateByCollectionIds and database migration script
* [AC-1174] Implement EF repository method
* [AC-1174] Improve null checks
* [AC-1174] Remove unnecessary BulkCollectionAccessRequestModel helpers
* [AC-1174] Add unit tests for new controller endpoint
* [AC-1174] Fix formatting
* [AC-1174] Remove comment
* [AC-1174] Remove redundant organizationId parameter
* [AC-1174] Ensure user and group Ids are distinct
* [AC-1174] Cleanup tests based on PR feedback
* [AC-1174] Formatting
* [AC-1174] Update CollectionGroup alias in the sproc
* [AC-1174] Add some additional comments to SQL sproc
* [AC-1174] Add comment explaining additional SaveChangesAsync call
---------
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
* [AC-1646] Rename LimitCollectionCdOwnerAdmin column (#3300)
* Rename LimitCollectionCdOwnerAdmin -> LimitCollectionCreationDeletion
* Rename and bump migration script
* [AC-1666] Removed EditAnyCollection from Create/Delete permission checks (#3301)
* fix: remove EditAnyCollection from Create/Delete permission check, refs AC-1666
* fix: updated comment, refs AC-1666
* [AC-1669] Bug - Remove obsolete assignUserId from CollectionService.SaveAsync(...) (#3312)
* fix: remove AssignUserId from CollectionService.SaveAsync, refs AC-1669
* fix: add manage access conditional before creating collection, refs AC-1669
* fix: move access logic for create/update, fix all tests, refs AC-1669
* fix: add CollectionAccessSelection fixture, update tests, update bad reqeuest message, refs AC-1669
* fix: format, refs AC-1669
* fix: update null params with specific arg.is null checks, refs Ac-1669
* fix: update attribute class name, refs AC-1669
* [AC-1713] [Flexible collections] Add feature flags to server (#3334)
* Add feature flags for FlexibleCollections and BulkCollectionAccess
* Flag new routes and behaviour
---------
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
* Add joint codeownership for auth handlers (#3346)
* [AC-1717] Update default values for LimitCollectionCreationDeletion (#3365)
* Change default value in organization create sproc to 1
* Drop old column name still present in some QA instances
* Set LimitCollectionCreationDeletion value in code based on feature flag
* Fix: add missing namespace after merging in master
* Fix: add missing namespace after merging in master
* [AC-1683] Fix DB migrations for new Manage permission (#3307)
* [AC-1683] Update migration script and introduce V2 procedures and types
* [AC-1683] Update repository calls to use new V2 procedures / types
* [AC-1684] Update bulk add collection migration script to use new V2 type
* [AC-1683] Undo Manage changes to more original procedures
* [AC-1683] Restore whitespace changes
* [AC-1683] Clarify comments regarding explicit column lists
* [AC-1683] Update migration script dates
* [AC-1683] Split the migration script for readability
* [AC-1683] Re-name SelectReadOnlyArray_V2 to CollectionAccessSelectionType
* [AC-1648] [Flexible Collections] Bump migration scripts before feature branch merge (#3371)
* Bump dates on sql migration scripts
* Bump date on ef migrations
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
Co-authored-by: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com>
Co-authored-by: Vincent Salucci <vincesalucci21@gmail.com>
Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
2023-11-01 19:30:52 +10:00
IFeatureService featureService )
2017-03-03 00:07:11 -05:00
{
_organizationRepository = organizationRepository ;
_organizationUserRepository = organizationUserRepository ;
2017-04-27 09:19:30 -04:00
_collectionRepository = collectionRepository ;
2017-03-04 21:28:41 -05:00
_userRepository = userRepository ;
2017-05-13 12:00:40 -04:00
_groupRepository = groupRepository ;
2017-03-23 00:17:34 -04:00
_mailService = mailService ;
2017-05-26 22:52:50 -04:00
_pushNotificationService = pushNotificationService ;
_pushRegistrationService = pushRegistrationService ;
2017-08-11 08:57:31 -04:00
_deviceRepository = deviceRepository ;
2017-08-14 20:57:45 -04:00
_licensingService = licensingService ;
2017-12-01 16:00:30 -05:00
_eventService = eventService ;
2017-12-19 16:02:39 -05:00
_applicationCacheService = applicationCacheService ;
2019-02-08 23:53:09 -05:00
_paymentService = paymentService ;
2020-01-15 15:00:54 -05:00
_policyRepository = policyRepository ;
2023-05-12 08:22:19 +01:00
_policyService = policyService ;
2020-07-22 09:38:39 -04:00
_ssoConfigRepository = ssoConfigRepository ;
2020-08-26 14:12:04 -04:00
_ssoUserRepository = ssoUserRepository ;
2020-07-07 12:01:34 -04:00
_referenceEventService = referenceEventService ;
2017-08-14 20:57:45 -04:00
_globalSettings = globalSettings ;
2022-05-10 17:12:09 -04:00
_organizationApiKeyRepository = organizationApiKeyRepository ;
2021-07-01 14:31:05 +02:00
_currentContext = currentContext ;
2021-09-23 06:36:08 -04:00
_logger = logger ;
2023-01-26 11:51:26 -05:00
_providerOrganizationRepository = providerOrganizationRepository ;
_providerUserRepository = providerUserRepository ;
2023-08-05 07:51:12 +10:00
_countNewSmSeatsRequiredQuery = countNewSmSeatsRequiredQuery ;
_updateSecretsManagerSubscriptionCommand = updateSecretsManagerSubscriptionCommand ;
2023-11-20 09:05:35 -05:00
_providerRepository = providerRepository ;
Auth/PM-3275 - Changes to support TDE User without MP being able to Set a Password + misc refactoring (#3242)
* PM-3275 - Add new GetMasterPasswordPolicy endpoint which will allow authenticated clients to get an enabled MP org policy if it exists for the purposes of enforcing those policy requirements when setting a password.
* PM-3275 - AccountsController.cs - PostSetPasswordAsync - (1) Convert UserService.setPasswordAsync into new SetInitialMasterPasswordCommand (2) Refactor SetInitialMasterPasswordCommand to only accept post SSO users who are in the invited state
(3) Add TODOs for more cleanup work and more commands
* PM-3275 - Update AccountsControllerTests.cs to add new SetInitialMasterPasswordCommand
* PM-3275 - UserService.cs - Remove non implemented ChangePasswordAsync method
* PM-3275 - The new SetInitialMasterPasswordCommand leveraged the OrganizationService.cs AcceptUserAsync method so while I was in here I converted the AcceptUserAsync methods into a new AcceptOrgUserCommand.cs and turned the private method which accepted an existing org user public for use in the SetInitialMasterPasswordCommand
* PM-3275 - Dotnet format
* PM-3275 - Test SetInitialMasterPasswordCommand
* Dotnet format
* PM-3275 - In process AcceptOrgUserCommandTests.cs
* PM-3275 - Migrate changes from AC-244 / #3199 over into new AcceptOrgUserCommand
* PM-3275 - AcceptOrgUserCommand.cs - create data protector specifically for this command
* PM-3275 - Add TODO for renaming / removing overloading of methods to improve readability / clarity
* PM-3275 - AcceptOrgUserCommand.cs - refactor AcceptOrgUserAsync by OrgId to retrieve orgUser with _organizationUserRepository.GetByOrganizationAsync which gets a single user instead of a collection
* PM-3275 - AcceptOrgUserCommand.cs - update name in TODO for evaluation later
* PM-3275 / PM-1196 - (1) Slightly refactor SsoEmail2faSessionTokenable to provide public static GetTokenLifeTime() method for testing (2) Add missed tests to SsoEmail2faSessionTokenable in preparation for building tests for new OrgUserInviteTokenable.cs
* PM-3275 / PM-1196 - Removing SsoEmail2faSessionTokenable.cs changes + tests as I've handled that separately in a new PR (#3270) for newly created task PM-3925
* PM-3275 - ExpiringTokenable.cs - add clarifying comments to help distinguish between the Valid property and the TokenIsValid method.
* PM-3275 - Create OrgUserInviteTokenable.cs and add tests in OrgUserInviteTokenableTests.cs
* PM-3275 - OrganizationService.cs - Refactor Org User Invite methods to use new OrgUserInviteTokenable instead of manual creation of a token
* PM-3275 - OrgUserInviteTokenable.cs - clarify backwards compat note
* PM-3275 - AcceptOrgUserCommand.cs - Add TODOs + minor name refactor
* PM-3275 - AcceptOrgUserCommand.cs - replace method overloading with more easily readable names.
* PM-3275 - AcceptOrgUserCommand.cs - Update ValidateOrgUserInviteToken to add new token validation while maintaining backwards compatibility for 1 release.
* dotnet format
* PM-3275 - AcceptOrgUserCommand.cs - Move private method below where it is used
* PM-3275 - ServiceCollectionExtensions.cs - Must register IDataProtectorTokenFactory<OrgUserInviteTokenable> for new tokenable
* PM-3275 - OrgUserInviteTokenable needed access to global settings to set its token lifetime to the _globalSettings.OrganizationInviteExpirationHours value. Creating a factory seemed the most straightforward way to encapsulate the desired creation logic. Unsure if in the correct location in ServiceCollectionExtensions.cs but will figure that out later.
* PM-3275 - In process work of creating AcceptOrgUserCommandTests.cs
* PM-3275 - Remove no longer relevant AcceptOrgUser tests from OrganizationServiceTests.cs
* PM-3275 - Register OrgUserInviteTokenableFactory alongside tokenizer
* PM-3275 - AcceptOrgUserCommandTests.cs - AcceptOrgUserAsync basic test suite completed.
* PM-3275 - AcceptOrgUserCommandTests.cs - tweak test names
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Remove old tests from OrganizationServiceTests as no longer needed to reference (2) Add summary for SetupCommonAcceptOrgUserMocks (3) Get AcceptOrgUserByToken_OldToken_AcceptsUserAndVerifiesEmail passing
* PM-3275 - Create interface for OrgUserInviteTokenableFactory b/c that's the right thing to do + enables test substitution
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Start work on AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail (2) Create and use SetupCommonAcceptOrgUserByTokenMocks() (3) Create generic FakeDataProtectorTokenFactory for tokenable testing
* PM-3275 - (1) Get AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail test passing (2) Move FakeDataProtectorTokenFactory to own file
* PM-3275 - AcceptOrgUserCommandTests.cs - Finish up tests for AcceptOrgUserByTokenAsync
* PM-3275 - Add pseudo section comments
* PM-3275 - Clean up unused params on AcceptOrgUserByToken_EmailMismatch_ThrowsBadRequest test
* PM-3275 - (1) Tests written for AcceptOrgUserByOrgSsoIdAsync (2) Refactor happy path assertions into helper function AssertValidAcceptedOrgUser to reduce code duplication
* PM-3275 - Finish up testing AcceptOrgUserCommandTests.cs by adding tests for AcceptOrgUserByOrgIdAsync
* PM-3275 - Tweaking test naming to ensure consistency.
* PM-3275 - Bugfix - OrgUserInviteTokenableFactory implementation required when declaring singleton service in ServiceCollectionExtensions.cs
* PM-3275 - Resolve failing OrganizationServiceTests.cs
* dotnet format
* PM-3275 - PoliciesController.cs - GetMasterPasswordPolicy bugfix - for orgs without a MP policy, policy comes back as null and we should return notFound in that case.
* PM-3275 - Add PoliciesControllerTests.cs specifically for new GetMasterPasswordPolicy(...) endpoint.
* PM-3275 - dotnet format PoliciesControllerTests.cs
* PM-3275 - PoliciesController.cs - (1) Add tech debt task number (2) Properly flag endpoint as deprecated
* PM-3275 - Add new hasManageResetPasswordPermission property to ProfileResponseModel.cs primarily for sync so that we can condition client side if TDE user obtains elevated permissions
* PM-3275 - Fix AccountsControllerTests.cs
* PM-3275 - OrgUserInviteTokenable.cs - clarify TODO
* PM-3275 - AcceptOrgUserCommand.cs - Refactor token validation to use short circuiting to only run old token validation if new token validation fails.
* PM-3275 - OrgUserInviteTokenable.cs - (1) Add new static methods to centralize validation logic to avoid repetition (2) Add new token validation method so we can avoid having to pass in a full org user (and hitting the db to do so)
* PM-3275 - Realized that the old token validation was used in the PoliciesController.cs (existing user clicks invite link in email and goes to log in) and UserService.cs (user clicks invite link in email and registers for a new acct). Added tech debt item for cleaning up backwards compatibility in future.
* dotnet format
* PM-3275 - (1) AccountsController.cs - Update PostSetPasswordAsync SetPasswordRequestModel to allow null keys for the case where we have a TDE user who obtains elevated permissions - they already have a user public and user encrypted private key saved in the db. (2) AccountsControllerTests.cs - test PostSetPasswordAsync scenarios to ensure changes will work as expected.
* PM-3275 - PR review feedback - (1) set CurrentContext to private (2) Refactor GetProfile to use variables to improve clarity and simplify debugging.
* PM-3275 - SyncController.cs - PR Review Feedback - Set current context as private instead of protected.
* PM-3275 - CurrentContextExtensions.cs - PR Feedback - move parenthesis up from own line.
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - Replace unnecessary variable
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - PR Feedback - Add expected outcome statement to test name
* PM-3275 - Set Initial Password command and tests - PR Feedback changes - (1) Rename orgIdentifier --> OrgSsoIdentifier for clarity (2) Update SetInitialMasterPasswordAsync to not allow null orgSsoId with explicit message saying this vs letting null org trigger invalid organization (3) Add test to cover this new scenario.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Move summary from implementation to interface to better respect standards and the fact that the interface is the more seen piece of code.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, rename AcceptOrgUserByTokenAsync -> AcceptOrgUserByEmailTokenAsync + replace generic name token with emailToken
* PM-3275 - OrganizationService.cs - Per PR feedback, remove dupe line
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove new lines in error messages for consistency.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Per PR feedback, adjust formatting of constructor for improved readability.
* PM-3275 - CurrentContextExtensions.cs - Refactor AnyOrgUserHasManageResetPasswordPermission per PR feedback to remove unnecessary var.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove completed TODO
* PM-3275 - PoliciesController.cs - Per PR feedback, update GetByInvitedUser param to be guid instead of string.
* PM-3275 - OrgUserInviteTokenable.cs - per PR feedback, add tech debt item info.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, use const purpose from tokenable instead of magic string.
* PM-3275 - Restore non duplicate line to fix tests
* PM-3275 - Per PR feedback, revert all sync controller changes as the ProfileResponseModel.organizations array has org objects which have permissions which have the ManageResetPassword permission. So, I have the information that I need clientside already to determine if the user has the ManageResetPassword in any org.
* PM-3275 - PoliciesControllerTests.cs - Update imports as the PoliciesController was moved under the admin console team's domain.
* PM-3275 - Resolve issues from merge conflict resolutions to get solution building.
* PM-3275 / PM-4633 - PoliciesController.cs - use orgUserId to look up user instead of orgId. Oops.
* Fix user service tests
* Resolve merge conflict
2023-11-02 11:02:25 -04:00
_orgUserInviteTokenableFactory = orgUserInviteTokenableFactory ;
_orgUserInviteTokenDataFactory = orgUserInviteTokenDataFactory ;
[AC-1373] Flexible Collections (#3245)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* fix: merge conflict resolution
* [AC-1174] CollectionUser and CollectionGroup authorization handlers (#3194)
* [AC-1174] Introduce BulkAuthorizationHandler.cs
* [AC-1174] Introduce CollectionUserAuthorizationHandler
* [AC-1174] Add CreateForNewCollection CollectionUser requirement
* [AC-1174] Add some more details to CollectionCustomization
* [AC-1174] Formatting
* [AC-1174] Add CollectionGroupOperation.cs
* [AC-1174] Introduce CollectionGroupAuthorizationHandler.cs
* [AC-1174] Cleanup CollectionFixture customization
Implement and use re-usable extension method to support seeded Guids
* [AC-1174] Introduce WithValueFromList AutoFixtureExtensions
Modify CollectionCustomization to use multiple organization Ids for auto generated test data
* [AC-1174] Simplify CollectionUserAuthorizationHandler.cs
Modify the authorization handler to only perform authorization logic. Validation logic will need to be handled by any calling commands/controllers instead.
* [AC-1174] Introduce shared CollectionAccessAuthorizationHandlerBase
A shared base authorization handler was created for both CollectionUser and CollectionGroup resources, as they share the same underlying management authorization logic.
* [AC-1174] Update CollectionUserAuthorizationHandler and CollectionGroupAuthorizationHandler to use the new CollectionAccessAuthorizationHandlerBase class
* [AC-1174] Formatting
* [AC-1174] Cleanup typo and redundant ToList() call
* [AC-1174] Add check for provider users
* [AC-1174] Reduce nested loops
* [AC-1174] Introduce ICollectionAccess.cs
* [AC-1174] Remove individual CollectionGroup and CollectionUser auth handlers and use base class instead
* [AC-1174] Tweak unit test to fail minimally
* [AC-1174] Reorganize authorization handlers in Core project
* [AC-1174] Introduce new AddCoreAuthorizationHandlers() extension method
* [AC-1174] Move CollectionAccessAuthorizationHandler into Api project
* [AC-1174] Move CollectionFixture to Vault folder
* [AC-1174] Rename operation to CreateUpdateDelete
* [AC-1174] Require single organization for collection access authorization handler
- Add requirement that all target collections must belong to the same organization
- Simplify logic related to multiple organizations
- Update tests and helpers
- Use ToHashSet to improve lookup time
* [AC-1174] Fix null reference exception
* [AC-1174] Throw bad request exception when collections belong to different organizations
* [AC-1174] Switch to CollectionAuthorizationHandler instead of CollectionAccessAuthorizationHandler to reduce complexity
* Fix improper merge conflict resolution
* fix: add permission check for collection management api, refs AC-1647 (#3252)
* [AC-1125] Enforce org setting for creating/deleting collections (#3241)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* feat: created collection auth handler/operations, added LimitCollectionCdOwnerAdmin to CurrentContentOrganization, refs AC-1125
* feat: create vault service collection extensions and register with base services, refs AC-1125
* feat: deprecated CurrentContext.CreateNewCollections, refs AC-1125
* feat: deprecate DeleteAnyCollection for single resource usages, refs AC-1125
* feat: move service registration to api, update references, refs AC-1125
* feat: add bulk delete authorization handler, refs AC-1125
* feat: always assign user and give manage access on create, refs AC-1125
* fix: updated CurrentContextOrganization type, refs AC-1125
* feat: combined existing collection authorization handlers/operations, refs AC-1125
* fix: OrganizationServiceTests -> CurrentContentOrganization typo, refs AC-1125
* fix: format, refs AC-1125
* fix: update collection controller tests, refs AC-1125
* fix: dotnet format, refs AC-1125
* feat: removed extra BulkAuthorizationHandler, refs AC-1125
* fix: dotnet format, refs AC-1125
* fix: change string to guid for org id, update bulk delete request model, refs AC-1125
* fix: remove delete many collection check, refs AC-1125
* fix: clean up collection auth handler, refs AC-1125
* fix: format fix for CollectionOperations, refs AC-1125
* fix: removed unnecessary owner check, add org null check to custom permission validation, refs AC-1125
* fix: remove unused methods in CurrentContext, refs AC-1125
* fix: removed obsolete test, fixed failling delete many test, refs AC-1125
* fix: CollectionAuthorizationHandlerTests fixes, refs AC-1125
* fix: OrganizationServiceTests fix broken test by mocking GetOrganization, refs AC-1125
* fix: CollectionAuthorizationHandler - remove unused repository, refs AC-1125
* feat: moved UserId null check to common method, refs AC-1125
* fix: updated auth handler tests to remove dependency on requirement for common code checks, refs AC-1125
* feat: updated conditionals/comments for create/delete methods within colleciton auth handler, refs AC-1125
* feat: added create/delete collection auth handler success methods, refs AC-1125
* fix: new up permissions to prevent excessive null checks, refs AC-1125
* fix: remove old reference to CreateNewCollections, refs AC-1125
* fix: typo within ViewAssignedCollections method, refs AC-1125
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
* refactor: remove organizationId from CollectionBulkDeleteRequestModel, refs AC-1649 (#3282)
* [AC-1174] Bulk Collection Management (#3229)
* [AC-1174] Update SelectionReadOnlyRequestModel to use Guid for Id property
* [AC-1174] Introduce initial bulk-access collection endpoint
* [AC-1174] Introduce BulkAddCollectionAccessCommand and validation logic/tests
* [AC-1174] Add CreateOrUpdateAccessMany method to CollectionRepository
* [AC-1174] Add event logs for bulk add collection access command
* [AC-1174] Add User_BumpAccountRevisionDateByCollectionIds and database migration script
* [AC-1174] Implement EF repository method
* [AC-1174] Improve null checks
* [AC-1174] Remove unnecessary BulkCollectionAccessRequestModel helpers
* [AC-1174] Add unit tests for new controller endpoint
* [AC-1174] Fix formatting
* [AC-1174] Remove comment
* [AC-1174] Remove redundant organizationId parameter
* [AC-1174] Ensure user and group Ids are distinct
* [AC-1174] Cleanup tests based on PR feedback
* [AC-1174] Formatting
* [AC-1174] Update CollectionGroup alias in the sproc
* [AC-1174] Add some additional comments to SQL sproc
* [AC-1174] Add comment explaining additional SaveChangesAsync call
---------
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
* [AC-1646] Rename LimitCollectionCdOwnerAdmin column (#3300)
* Rename LimitCollectionCdOwnerAdmin -> LimitCollectionCreationDeletion
* Rename and bump migration script
* [AC-1666] Removed EditAnyCollection from Create/Delete permission checks (#3301)
* fix: remove EditAnyCollection from Create/Delete permission check, refs AC-1666
* fix: updated comment, refs AC-1666
* [AC-1669] Bug - Remove obsolete assignUserId from CollectionService.SaveAsync(...) (#3312)
* fix: remove AssignUserId from CollectionService.SaveAsync, refs AC-1669
* fix: add manage access conditional before creating collection, refs AC-1669
* fix: move access logic for create/update, fix all tests, refs AC-1669
* fix: add CollectionAccessSelection fixture, update tests, update bad reqeuest message, refs AC-1669
* fix: format, refs AC-1669
* fix: update null params with specific arg.is null checks, refs Ac-1669
* fix: update attribute class name, refs AC-1669
* [AC-1713] [Flexible collections] Add feature flags to server (#3334)
* Add feature flags for FlexibleCollections and BulkCollectionAccess
* Flag new routes and behaviour
---------
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
* Add joint codeownership for auth handlers (#3346)
* [AC-1717] Update default values for LimitCollectionCreationDeletion (#3365)
* Change default value in organization create sproc to 1
* Drop old column name still present in some QA instances
* Set LimitCollectionCreationDeletion value in code based on feature flag
* Fix: add missing namespace after merging in master
* Fix: add missing namespace after merging in master
* [AC-1683] Fix DB migrations for new Manage permission (#3307)
* [AC-1683] Update migration script and introduce V2 procedures and types
* [AC-1683] Update repository calls to use new V2 procedures / types
* [AC-1684] Update bulk add collection migration script to use new V2 type
* [AC-1683] Undo Manage changes to more original procedures
* [AC-1683] Restore whitespace changes
* [AC-1683] Clarify comments regarding explicit column lists
* [AC-1683] Update migration script dates
* [AC-1683] Split the migration script for readability
* [AC-1683] Re-name SelectReadOnlyArray_V2 to CollectionAccessSelectionType
* [AC-1648] [Flexible Collections] Bump migration scripts before feature branch merge (#3371)
* Bump dates on sql migration scripts
* Bump date on ef migrations
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
Co-authored-by: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com>
Co-authored-by: Vincent Salucci <vincesalucci21@gmail.com>
Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
2023-11-01 19:30:52 +10:00
_featureService = featureService ;
2018-12-31 13:34:02 -05:00
}
2020-07-07 12:01:34 -04:00
public async Task ReplacePaymentMethodAsync ( Guid organizationId , string paymentToken ,
PaymentMethodType paymentMethodType , TaxInfo taxInfo )
2022-08-29 15:53:48 -04:00
{
2020-07-07 12:01:34 -04:00
var organization = await GetOrgById ( organizationId ) ;
2020-03-27 14:36:37 -04:00
if ( organization = = null )
2022-08-29 16:06:55 -04:00
{
2020-07-07 12:01:34 -04:00
throw new NotFoundException ( ) ;
2017-04-08 18:15:20 -04:00
}
2017-04-10 18:20:21 -04:00
await _paymentService . SaveTaxInfoAsync ( organization , taxInfo ) ;
2024-02-01 13:21:17 -05:00
var updated = await _paymentService . UpdatePaymentMethodAsync (
organization ,
paymentMethodType ,
paymentToken ,
_featureService . IsEnabled ( FeatureFlagKeys . PM5766AutomaticTax )
? taxInfo
: null ) ;
2017-04-10 18:20:21 -04:00
if ( updated )
2017-04-10 16:42:53 -04:00
{
2023-02-24 07:54:19 +10:00
await ReplaceAndUpdateCacheAsync ( organization ) ;
2022-08-29 14:53:16 -04:00
}
2017-04-10 16:42:53 -04:00
}
2019-02-08 23:53:09 -05:00
public async Task CancelSubscriptionAsync ( Guid organizationId , bool? endOfPeriod = null )
2022-08-29 16:06:55 -04:00
{
2019-02-08 23:53:09 -05:00
var organization = await GetOrgById ( organizationId ) ;
if ( organization = = null )
2022-08-29 16:06:55 -04:00
{
2019-02-08 23:53:09 -05:00
throw new NotFoundException ( ) ;
2017-04-10 16:42:53 -04:00
}
2017-12-19 16:02:39 -05:00
var eop = endOfPeriod . GetValueOrDefault ( true ) ;
2019-08-09 23:56:26 -04:00
if ( ! endOfPeriod . HasValue & & organization . ExpirationDate . HasValue & &
organization . ExpirationDate . Value < DateTime . UtcNow )
2017-04-10 09:36:21 -04:00
{
2017-12-19 16:02:39 -05:00
eop = false ;
2022-08-29 16:06:55 -04:00
}
2017-12-19 16:02:39 -05:00
await _paymentService . CancelSubscriptionAsync ( organization , eop ) ;
2019-02-08 23:53:09 -05:00
await _referenceEventService . RaiseEventAsync (
2023-05-16 16:21:57 +02:00
new ReferenceEvent ( ReferenceEventType . CancelSubscription , organization , _currentContext )
2022-08-29 15:53:48 -04:00
{
2017-04-10 09:36:21 -04:00
EndOfPeriod = endOfPeriod ,
} ) ;
}
2020-03-27 14:36:37 -04:00
public async Task ReinstateSubscriptionAsync ( Guid organizationId )
2022-08-29 16:06:55 -04:00
{
2019-03-21 21:36:03 -04:00
var organization = await GetOrgById ( organizationId ) ;
2020-03-27 14:36:37 -04:00
if ( organization = = null )
2022-08-29 16:06:55 -04:00
{
2019-03-21 21:36:03 -04:00
throw new NotFoundException ( ) ;
2017-04-10 09:36:21 -04:00
}
2017-08-15 16:11:08 -04:00
await _paymentService . ReinstateSubscriptionAsync ( organization ) ;
2019-03-21 21:36:03 -04:00
await _referenceEventService . RaiseEventAsync (
2023-05-16 16:21:57 +02:00
new ReferenceEvent ( ReferenceEventType . ReinstateSubscription , organization , _currentContext ) ) ;
2022-08-29 16:06:55 -04:00
}
2019-08-09 23:56:26 -04:00
public async Task < string > AdjustStorageAsync ( Guid organizationId , short storageAdjustmentGb )
2022-08-29 16:06:55 -04:00
{
2017-07-11 10:59:59 -04:00
var organization = await GetOrgById ( organizationId ) ;
2021-09-23 06:36:08 -04:00
if ( organization = = null )
2022-08-29 16:06:55 -04:00
{
2017-07-11 10:59:59 -04:00
throw new NotFoundException ( ) ;
2022-08-29 16:06:55 -04:00
}
2019-03-21 21:36:03 -04:00
2023-10-17 15:56:35 +01:00
var plan = StaticStore . Plans . FirstOrDefault ( p = > p . Type = = organization . PlanType ) ;
2020-09-18 14:10:30 -04:00
if ( plan = = null )
2022-08-29 15:53:48 -04:00
{
2020-09-18 14:10:30 -04:00
throw new BadRequestException ( "Existing plan not found." ) ;
2022-08-29 14:53:16 -04:00
}
2023-10-17 15:56:35 +01:00
if ( ! plan . PasswordManager . HasAdditionalStorageOption )
2022-08-29 16:06:55 -04:00
{
2019-03-21 21:36:03 -04:00
throw new BadRequestException ( "Plan does not allow additional storage." ) ;
2022-08-29 16:06:55 -04:00
}
2019-03-21 21:36:03 -04:00
var secret = await BillingHelpers . AdjustStorageAsync ( _paymentService , organization , storageAdjustmentGb ,
2023-10-17 15:56:35 +01:00
plan . PasswordManager . StripeStoragePlanId ) ;
2019-03-21 21:36:03 -04:00
await _referenceEventService . RaiseEventAsync (
2023-05-16 16:21:57 +02:00
new ReferenceEvent ( ReferenceEventType . AdjustStorage , organization , _currentContext )
2020-07-07 12:01:34 -04:00
{
PlanName = plan . Name ,
PlanType = plan . Type ,
Storage = storageAdjustmentGb ,
2022-08-29 16:06:55 -04:00
} ) ;
2023-02-24 07:54:19 +10:00
await ReplaceAndUpdateCacheAsync ( organization ) ;
2020-07-07 12:01:34 -04:00
return secret ;
}
2019-08-09 23:56:26 -04:00
public async Task UpdateSubscription ( Guid organizationId , int seatAdjustment , int? maxAutoscaleSeats )
2022-08-29 16:06:55 -04:00
{
2019-08-09 23:56:26 -04:00
var organization = await GetOrgById ( organizationId ) ;
2021-09-23 06:36:08 -04:00
if ( organization = = null )
2022-08-29 16:06:55 -04:00
{
2019-08-09 23:56:26 -04:00
throw new NotFoundException ( ) ;
2017-04-10 09:36:21 -04:00
}
2019-08-10 12:59:32 -04:00
var newSeatCount = organization . Seats + seatAdjustment ;
if ( maxAutoscaleSeats . HasValue & & newSeatCount > maxAutoscaleSeats . Value )
2017-07-11 10:59:59 -04:00
{
throw new BadRequestException ( "Cannot set max seat autoscaling below seat count." ) ;
}
if ( seatAdjustment ! = 0 )
2022-08-29 16:06:55 -04:00
{
2017-07-11 10:59:59 -04:00
await AdjustSeatsAsync ( organization , seatAdjustment ) ;
2022-08-29 16:06:55 -04:00
}
2017-07-11 10:59:59 -04:00
if ( maxAutoscaleSeats ! = organization . MaxAutoscaleSeats )
{
await UpdateAutoscalingAsync ( organization , maxAutoscaleSeats ) ;
2022-08-29 14:53:16 -04:00
}
2022-08-29 16:06:55 -04:00
}
2017-07-11 10:59:59 -04:00
private async Task UpdateAutoscalingAsync ( Organization organization , int? maxAutoscaleSeats )
2022-08-29 16:06:55 -04:00
{
2017-07-11 10:59:59 -04:00
2021-09-23 06:36:08 -04:00
if ( maxAutoscaleSeats . HasValue & &
2019-08-10 12:59:32 -04:00
organization . Seats . HasValue & &
maxAutoscaleSeats . Value < organization . Seats . Value )
2022-08-29 16:06:55 -04:00
{
2019-08-10 12:59:32 -04:00
throw new BadRequestException ( $"Cannot set max seat autoscaling below current seat count." ) ;
2017-07-11 10:59:59 -04:00
}
2023-10-17 15:56:35 +01:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
2021-09-23 06:36:08 -04:00
if ( plan = = null )
{
throw new BadRequestException ( "Existing plan not found." ) ;
}
2023-10-17 15:56:35 +01:00
if ( ! plan . PasswordManager . AllowSeatAutoscale )
2021-09-23 06:36:08 -04:00
{
throw new BadRequestException ( "Your plan does not allow seat autoscaling." ) ;
2022-08-29 14:53:16 -04:00
}
2021-09-23 06:36:08 -04:00
2023-10-17 15:56:35 +01:00
if ( plan . PasswordManager . MaxSeats . HasValue & & maxAutoscaleSeats . HasValue & &
maxAutoscaleSeats > plan . PasswordManager . MaxSeats )
2022-08-29 14:53:16 -04:00
{
2023-10-17 15:56:35 +01:00
throw new BadRequestException ( string . Concat ( $"Your plan has a seat limit of {plan.PasswordManager.MaxSeats}, " ,
2021-09-23 06:36:08 -04:00
$"but you have specified a max autoscale count of {maxAutoscaleSeats}." ,
2017-04-10 09:36:21 -04:00
"Reduce your max autoscale seat count." ) ) ;
2022-08-29 16:06:55 -04:00
}
2021-09-23 06:36:08 -04:00
organization . MaxAutoscaleSeats = maxAutoscaleSeats ;
2023-02-24 07:54:19 +10:00
await ReplaceAndUpdateCacheAsync ( organization ) ;
2022-08-29 14:53:16 -04:00
}
2021-09-23 06:36:08 -04:00
public async Task < string > AdjustSeatsAsync ( Guid organizationId , int seatAdjustment , DateTime ? prorationDate = null )
2022-08-29 16:06:55 -04:00
{
2021-09-23 06:36:08 -04:00
var organization = await GetOrgById ( organizationId ) ;
2017-04-10 09:36:21 -04:00
if ( organization = = null )
2022-08-29 16:06:55 -04:00
{
2021-09-23 06:36:08 -04:00
throw new NotFoundException ( ) ;
}
2017-04-10 09:36:21 -04:00
return await AdjustSeatsAsync ( organization , seatAdjustment , prorationDate ) ;
}
2021-09-23 06:36:08 -04:00
private async Task < string > AdjustSeatsAsync ( Organization organization , int seatAdjustment , DateTime ? prorationDate = null , IEnumerable < string > ownerEmails = null )
2022-08-29 16:06:55 -04:00
{
2021-09-23 06:36:08 -04:00
if ( organization . Seats = = null )
2022-08-29 16:06:55 -04:00
{
2021-09-23 06:36:08 -04:00
throw new BadRequestException ( "Organization has no seat limit, no need to adjust seats" ) ;
2022-08-29 16:06:55 -04:00
}
2021-09-23 06:36:08 -04:00
2021-09-14 09:18:06 -04:00
if ( string . IsNullOrWhiteSpace ( organization . GatewayCustomerId ) )
2022-08-29 16:06:55 -04:00
{
2021-09-14 09:18:06 -04:00
throw new BadRequestException ( "No payment method found." ) ;
}
2020-03-27 14:36:37 -04:00
if ( string . IsNullOrWhiteSpace ( organization . GatewaySubscriptionId ) )
2017-04-10 09:36:21 -04:00
{
throw new BadRequestException ( "No subscription found." ) ;
}
2023-10-17 15:56:35 +01:00
var plan = StaticStore . Plans . FirstOrDefault ( p = > p . Type = = organization . PlanType ) ;
2020-03-27 14:36:37 -04:00
if ( plan = = null )
2022-08-29 16:06:55 -04:00
{
2017-04-10 09:36:21 -04:00
throw new BadRequestException ( "Existing plan not found." ) ;
}
2023-10-17 15:56:35 +01:00
if ( ! plan . PasswordManager . HasAdditionalSeatsOption )
2017-04-10 09:36:21 -04:00
{
throw new BadRequestException ( "Plan does not allow additional seats." ) ;
}
2020-08-11 14:19:56 -04:00
var newSeatTotal = organization . Seats . Value + seatAdjustment ;
2023-10-17 15:56:35 +01:00
if ( plan . PasswordManager . BaseSeats > newSeatTotal )
2017-04-10 09:36:21 -04:00
{
2023-10-17 15:56:35 +01:00
throw new BadRequestException ( $"Plan has a minimum of {plan.PasswordManager.BaseSeats} seats." ) ;
2017-04-10 09:36:21 -04:00
}
2021-09-14 09:18:06 -04:00
if ( newSeatTotal < = 0 )
2017-04-10 11:49:53 -04:00
{
throw new BadRequestException ( "You must have at least 1 seat." ) ;
2022-08-29 15:53:48 -04:00
}
2017-04-10 11:49:53 -04:00
2023-10-17 15:56:35 +01:00
var additionalSeats = newSeatTotal - plan . PasswordManager . BaseSeats ;
if ( plan . PasswordManager . MaxAdditionalSeats . HasValue & & additionalSeats > plan . PasswordManager . MaxAdditionalSeats . Value )
2017-05-20 15:33:17 -04:00
{
throw new BadRequestException ( $"Organization plan allows a maximum of " +
2023-10-17 15:56:35 +01:00
$"{plan.PasswordManager.MaxAdditionalSeats.Value} additional seats." ) ;
2017-05-20 15:33:17 -04:00
}
2022-08-29 15:53:48 -04:00
2020-03-27 14:36:37 -04:00
if ( ! organization . Seats . HasValue | | organization . Seats . Value > newSeatTotal )
2022-08-29 16:06:55 -04:00
{
2023-02-24 07:54:19 +10:00
var occupiedSeats = await _organizationUserRepository . GetOccupiedSeatCountByOrganizationIdAsync ( organization . Id ) ;
2022-09-23 14:30:39 +10:00
if ( occupiedSeats > newSeatTotal )
2017-04-10 09:36:21 -04:00
{
2022-09-23 14:30:39 +10:00
throw new BadRequestException ( $"Your organization currently has {occupiedSeats} seats filled. " +
2017-04-10 09:36:21 -04:00
$"Your new plan only has ({newSeatTotal}) seats. Remove some users." ) ;
}
2022-08-29 16:06:55 -04:00
}
2017-04-10 09:36:21 -04:00
2019-05-14 11:16:30 -04:00
var paymentIntentClientSecret = await _paymentService . AdjustSeatsAsync ( organization , plan , additionalSeats , prorationDate ) ;
2020-03-27 14:36:37 -04:00
await _referenceEventService . RaiseEventAsync (
2023-05-16 16:21:57 +02:00
new ReferenceEvent ( ReferenceEventType . AdjustSeats , organization , _currentContext )
2022-08-29 15:53:48 -04:00
{
2019-05-14 11:16:30 -04:00
PlanName = plan . Name ,
2020-07-07 12:01:34 -04:00
PlanType = plan . Type ,
2019-05-14 11:16:30 -04:00
Seats = newSeatTotal ,
PreviousSeats = organization . Seats
} ) ;
organization . Seats = ( short? ) newSeatTotal ;
2023-02-24 07:54:19 +10:00
await ReplaceAndUpdateCacheAsync ( organization ) ;
2017-04-10 09:36:21 -04:00
2021-08-10 14:38:58 -04:00
if ( organization . Seats . HasValue & & organization . MaxAutoscaleSeats . HasValue & & organization . Seats = = organization . MaxAutoscaleSeats )
2022-08-29 16:06:55 -04:00
{
try
2022-08-29 14:53:16 -04:00
{
2017-12-19 16:02:39 -05:00
if ( ownerEmails = = null )
2022-08-29 16:06:55 -04:00
{
2017-12-19 16:02:39 -05:00
ownerEmails = ( await _organizationUserRepository . GetManyByMinimumRoleAsync ( organization . Id ,
OrganizationUserType . Owner ) ) . Select ( u = > u . Email ) . Distinct ( ) ;
2022-08-29 16:06:55 -04:00
}
2017-12-19 16:02:39 -05:00
await _mailService . SendOrganizationMaxSeatLimitReachedEmailAsync ( organization , organization . MaxAutoscaleSeats . Value , ownerEmails ) ;
2022-08-29 14:53:16 -04:00
}
2021-09-23 06:36:08 -04:00
catch ( Exception e )
{
_logger . LogError ( e , "Error encountered notifying organization owners of seat limit reached." ) ;
}
2022-08-29 16:06:55 -04:00
}
2021-09-23 06:36:08 -04:00
2017-08-14 09:23:54 -04:00
return paymentIntentClientSecret ;
2022-08-29 15:53:48 -04:00
}
2017-04-11 10:00:36 -04:00
2017-08-14 09:23:54 -04:00
public async Task VerifyBankAsync ( Guid organizationId , int amount1 , int amount2 )
2022-08-29 16:06:55 -04:00
{
2017-08-14 09:23:54 -04:00
var organization = await GetOrgById ( organizationId ) ;
2017-04-10 11:49:53 -04:00
if ( organization = = null )
2022-08-29 16:06:55 -04:00
{
2017-08-14 09:23:54 -04:00
throw new NotFoundException ( ) ;
2022-08-29 16:06:55 -04:00
}
2017-08-14 09:23:54 -04:00
if ( string . IsNullOrWhiteSpace ( organization . GatewayCustomerId ) )
2022-08-29 15:53:48 -04:00
{
2017-08-14 09:23:54 -04:00
throw new GatewayException ( "Not a gateway customer." ) ;
2022-08-29 15:53:48 -04:00
}
2017-08-14 09:23:54 -04:00
var bankService = new BankAccountService ( ) ;
2019-01-29 14:41:37 -05:00
var customerService = new CustomerService ( ) ;
2017-08-14 09:23:54 -04:00
var customer = await customerService . GetAsync ( organization . GatewayCustomerId ,
new CustomerGetOptions { Expand = new List < string > { "sources" } } ) ;
2021-07-08 17:05:32 +02:00
if ( customer = = null )
2022-08-29 16:06:55 -04:00
{
2021-07-08 17:05:32 +02:00
throw new GatewayException ( "Cannot find customer." ) ;
2017-08-14 09:23:54 -04:00
}
2019-01-29 14:41:37 -05:00
var bankAccount = customer . Sources
. FirstOrDefault ( s = > s is BankAccount & & ( ( BankAccount ) s ) . Status ! = "verified" ) as BankAccount ;
if ( bankAccount = = null )
2017-08-14 09:23:54 -04:00
{
throw new GatewayException ( "Cannot find an unverified bank account." ) ;
}
try
2022-08-29 16:06:55 -04:00
{
2017-08-14 09:23:54 -04:00
var result = await bankService . VerifyAsync ( organization . GatewayCustomerId , bankAccount . Id ,
new BankAccountVerifyOptions { Amounts = new List < long > { amount1 , amount2 } } ) ;
if ( result . Status ! = "verified" )
2022-08-29 14:53:16 -04:00
{
2017-08-14 09:23:54 -04:00
throw new GatewayException ( "Unable to verify account." ) ;
}
2022-08-29 16:06:55 -04:00
}
2021-07-08 17:05:32 +02:00
catch ( StripeException e )
2022-08-29 16:06:55 -04:00
{
2017-03-03 00:07:11 -05:00
throw new GatewayException ( e . Message ) ;
2022-08-29 16:06:55 -04:00
}
}
2017-08-14 09:23:54 -04:00
2024-01-17 22:33:35 +10:00
/// <summary>
/// Create a new organization in a cloud environment
/// </summary>
2024-02-15 00:41:51 +10:00
public async Task < ( Organization organization , OrganizationUser organizationUser , Collection defaultCollection ) > SignUpAsync ( OrganizationSignup signup ,
2021-07-08 17:05:32 +02:00
bool provider = false )
{
2023-10-17 15:56:35 +01:00
var plan = StaticStore . GetPlan ( signup . Plan ) ;
2022-08-29 14:53:16 -04:00
2023-10-17 15:56:35 +01:00
ValidatePasswordManagerPlan ( plan , signup ) ;
2023-07-24 23:05:05 +01:00
if ( signup . UseSecretsManager )
2022-08-29 15:53:48 -04:00
{
2023-10-13 00:56:50 +10:00
if ( provider )
{
throw new BadRequestException (
"Organizations with a Managed Service Provider do not support Secrets Manager." ) ;
}
2023-10-17 15:56:35 +01:00
ValidateSecretsManagerPlan ( plan , signup ) ;
2021-07-08 17:05:32 +02:00
}
if ( ! provider )
2022-08-29 16:06:55 -04:00
{
2021-07-08 17:05:32 +02:00
await ValidateSignUpPoliciesAsync ( signup . Owner . Id ) ;
2022-08-29 14:53:16 -04:00
}
2022-08-29 15:53:48 -04:00
2024-01-17 22:33:35 +10:00
var flexibleCollectionsSignupEnabled =
2024-01-18 09:47:34 -05:00
_featureService . IsEnabled ( FeatureFlagKeys . FlexibleCollectionsSignup ) ;
2024-01-17 22:33:35 +10:00
2023-12-04 12:41:03 +00:00
var flexibleCollectionsV1IsEnabled =
2024-01-18 09:47:34 -05:00
_featureService . IsEnabled ( FeatureFlagKeys . FlexibleCollectionsV1 ) ;
2023-12-04 12:41:03 +00:00
2021-07-08 17:05:32 +02:00
var organization = new Organization
2022-08-29 14:53:16 -04:00
{
2019-02-19 17:13:21 -05:00
// Pre-generate the org id so that we can save it with the Stripe subscription..
Id = CoreHelpers . GenerateComb ( ) ,
Name = signup . Name ,
2019-01-31 14:25:46 -05:00
BillingEmail = signup . BillingEmail ,
2017-04-04 12:57:50 -04:00
BusinessName = signup . BusinessName ,
2023-10-17 15:56:35 +01:00
PlanType = plan ! . Type ,
Seats = ( short ) ( plan . PasswordManager . BaseSeats + signup . AdditionalSeats ) ,
MaxCollections = plan . PasswordManager . MaxCollections ,
MaxStorageGb = ! plan . PasswordManager . BaseStorageGb . HasValue ?
( short? ) null : ( short ) ( plan . PasswordManager . BaseStorageGb . Value + signup . AdditionalStorageGb ) ,
UsePolicies = plan . HasPolicies ,
UseSso = plan . HasSso ,
UseGroups = plan . HasGroups ,
UseEvents = plan . HasEvents ,
UseDirectory = plan . HasDirectory ,
UseTotp = plan . HasTotp ,
Use2fa = plan . Has2fa ,
UseApi = plan . HasApi ,
UseResetPassword = plan . HasResetPassword ,
SelfHost = plan . HasSelfHost ,
UsersGetPremium = plan . UsersGetPremium | | signup . PremiumAccessAddon ,
UseCustomPermissions = plan . HasCustomPermissions ,
UseScim = plan . HasScim ,
Plan = plan . Name ,
2019-01-31 14:25:46 -05:00
Gateway = null ,
ReferenceData = signup . Owner . ReferenceData ,
Enabled = true ,
LicenseKey = CoreHelpers . SecureRandomString ( 20 ) ,
2021-05-06 14:53:12 -05:00
PublicKey = signup . PublicKey ,
2019-01-31 14:25:46 -05:00
PrivateKey = signup . PrivateKey ,
CreationDate = DateTime . UtcNow ,
2020-06-25 12:28:22 -04:00
RevisionDate = DateTime . UtcNow ,
2023-07-24 23:05:05 +01:00
Status = OrganizationStatusType . Created ,
UsePasswordManager = true ,
2023-08-05 07:51:12 +10:00
UseSecretsManager = signup . UseSecretsManager ,
2024-01-17 22:33:35 +10:00
// This feature flag indicates that new organizations should be automatically onboarded to
// Flexible Collections enhancements
FlexibleCollections = flexibleCollectionsSignupEnabled ,
// These collection management settings smooth the migration for existing organizations by disabling some FC behavior.
// If the organization is onboarded to Flexible Collections on signup, we turn them OFF to enable all new behaviour.
// If the organization is NOT onboarded now, they will have to be migrated later, so they default to ON to limit FC changes on migration.
LimitCollectionCreationDeletion = ! flexibleCollectionsSignupEnabled ,
2023-12-04 12:41:03 +00:00
AllowAdminAccessToAllCollectionItems = ! flexibleCollectionsV1IsEnabled
2022-08-29 14:53:16 -04:00
} ;
2017-03-03 00:07:11 -05:00
2023-08-05 07:51:12 +10:00
if ( signup . UseSecretsManager )
{
2023-10-17 15:56:35 +01:00
organization . SmSeats = plan . SecretsManager . BaseSeats + signup . AdditionalSmSeats . GetValueOrDefault ( ) ;
organization . SmServiceAccounts = plan . SecretsManager . BaseServiceAccount +
2023-08-05 07:51:12 +10:00
signup . AdditionalServiceAccounts . GetValueOrDefault ( ) ;
}
2023-10-17 15:56:35 +01:00
if ( plan . Type = = PlanType . Free & & ! provider )
2022-08-29 16:06:55 -04:00
{
2019-01-31 14:25:46 -05:00
var adminCount =
2021-07-08 17:05:32 +02:00
await _organizationUserRepository . GetCountByFreeOrganizationAdminUserAsync ( signup . Owner . Id ) ;
if ( adminCount > 0 )
{
2020-07-07 12:01:34 -04:00
throw new BadRequestException ( "You can only be an admin of one free organization." ) ;
2021-07-08 17:05:32 +02:00
}
2022-08-29 16:06:55 -04:00
}
2023-10-17 15:56:35 +01:00
else if ( plan . Type ! = PlanType . Free )
2022-08-29 16:06:55 -04:00
{
2021-07-08 17:05:32 +02:00
await _paymentService . PurchaseOrganizationAsync ( organization , signup . PaymentMethodType . Value ,
2023-10-17 15:56:35 +01:00
signup . PaymentToken , plan , signup . AdditionalStorageGb , signup . AdditionalSeats ,
2023-07-24 23:05:05 +01:00
signup . PremiumAccessAddon , signup . TaxInfo , provider , signup . AdditionalSmSeats . GetValueOrDefault ( ) ,
2024-01-29 11:10:27 -05:00
signup . AdditionalServiceAccounts . GetValueOrDefault ( ) , signup . IsFromSecretsManagerTrial ) ;
2022-08-29 16:06:55 -04:00
}
2021-07-08 17:05:32 +02:00
2019-03-21 21:36:03 -04:00
var ownerId = provider ? default : signup . Owner . Id ;
2021-06-30 09:21:41 +02:00
var returnValue = await SignUpAsync ( organization , ownerId , signup . OwnerKey , signup . CollectionName , true ) ;
await _referenceEventService . RaiseEventAsync (
2023-05-16 16:21:57 +02:00
new ReferenceEvent ( ReferenceEventType . Signup , organization , _currentContext )
2022-08-29 15:53:48 -04:00
{
2023-10-17 15:56:35 +01:00
PlanName = plan . Name ,
PlanType = plan . Type ,
2019-03-21 21:36:03 -04:00
Seats = returnValue . Item1 . Seats ,
2024-02-26 11:50:24 -05:00
SignupInitiationPath = signup . InitiationPath ,
2021-06-30 09:21:41 +02:00
Storage = returnValue . Item1 . MaxStorageGb ,
2023-07-24 23:05:05 +01:00
// TODO: add reference events for SmSeats and Service Accounts - see AC-1481
2019-03-21 21:36:03 -04:00
} ) ;
2021-06-30 09:21:41 +02:00
return returnValue ;
2022-08-29 14:53:16 -04:00
}
2017-04-08 10:52:10 -04:00
2017-03-03 00:07:11 -05:00
private async Task ValidateSignUpPoliciesAsync ( Guid ownerId )
2022-08-29 16:06:55 -04:00
{
2023-05-12 08:22:19 +01:00
var anySingleOrgPolicies = await _policyService . AnyPoliciesApplicableToUserAsync ( ownerId , PolicyType . SingleOrg ) ;
if ( anySingleOrgPolicies )
2022-08-29 16:06:55 -04:00
{
2017-03-03 00:07:11 -05:00
throw new BadRequestException ( "You may not create an organization. You belong to an organization " +
"which has a policy that prohibits you from being a member of any other organization." ) ;
2022-08-29 16:06:55 -04:00
}
}
2017-03-03 00:07:11 -05:00
2024-01-17 22:33:35 +10:00
/// <summary>
/// Create a new organization on a self-hosted instance
/// </summary>
2024-02-15 00:41:51 +10:00
public async Task < ( Organization organization , OrganizationUser organizationUser ) > SignUpAsync (
2019-01-31 14:25:46 -05:00
OrganizationLicense license , User owner , string ownerKey , string collectionName , string publicKey ,
string privateKey )
2022-08-29 16:06:55 -04:00
{
2023-02-24 07:54:19 +10:00
var canUse = license . CanUse ( _globalSettings , _licensingService , out var exception ) ;
if ( ! canUse )
2022-08-29 16:06:55 -04:00
{
2023-02-24 07:54:19 +10:00
throw new BadRequestException ( exception ) ;
2021-06-30 09:21:41 +02:00
}
2017-11-06 08:12:36 -05:00
if ( license . PlanType ! = PlanType . Custom & &
2023-10-17 15:56:35 +01:00
StaticStore . Plans . FirstOrDefault ( p = > p . Type = = license . PlanType & & ! p . Disabled ) = = null )
2022-08-29 14:53:16 -04:00
{
2017-11-06 08:12:36 -05:00
throw new BadRequestException ( "Plan not found." ) ;
2022-08-29 14:53:16 -04:00
}
2017-08-30 21:25:46 -04:00
var enabledOrgs = await _organizationRepository . GetManyByEnabledAsync ( ) ;
2022-11-30 08:40:12 -05:00
if ( enabledOrgs . Any ( o = > string . Equals ( o . LicenseKey , license . LicenseKey ) ) )
2022-08-29 16:06:55 -04:00
{
2017-08-30 21:25:46 -04:00
throw new BadRequestException ( "License is already in use by another organization." ) ;
2022-08-29 16:06:55 -04:00
}
2021-07-08 17:05:32 +02:00
await ValidateSignUpPoliciesAsync ( owner . Id ) ;
2022-08-29 16:06:55 -04:00
2024-01-17 22:33:35 +10:00
var flexibleCollectionsSignupEnabled =
2024-01-18 09:47:34 -05:00
_featureService . IsEnabled ( FeatureFlagKeys . FlexibleCollectionsSignup ) ;
[AC-1721] Include limit collection creation/deletion in license file (#3388)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* fix: merge conflict resolution
* [AC-1174] CollectionUser and CollectionGroup authorization handlers (#3194)
* [AC-1174] Introduce BulkAuthorizationHandler.cs
* [AC-1174] Introduce CollectionUserAuthorizationHandler
* [AC-1174] Add CreateForNewCollection CollectionUser requirement
* [AC-1174] Add some more details to CollectionCustomization
* [AC-1174] Formatting
* [AC-1174] Add CollectionGroupOperation.cs
* [AC-1174] Introduce CollectionGroupAuthorizationHandler.cs
* [AC-1174] Cleanup CollectionFixture customization
Implement and use re-usable extension method to support seeded Guids
* [AC-1174] Introduce WithValueFromList AutoFixtureExtensions
Modify CollectionCustomization to use multiple organization Ids for auto generated test data
* [AC-1174] Simplify CollectionUserAuthorizationHandler.cs
Modify the authorization handler to only perform authorization logic. Validation logic will need to be handled by any calling commands/controllers instead.
* [AC-1174] Introduce shared CollectionAccessAuthorizationHandlerBase
A shared base authorization handler was created for both CollectionUser and CollectionGroup resources, as they share the same underlying management authorization logic.
* [AC-1174] Update CollectionUserAuthorizationHandler and CollectionGroupAuthorizationHandler to use the new CollectionAccessAuthorizationHandlerBase class
* [AC-1174] Formatting
* [AC-1174] Cleanup typo and redundant ToList() call
* [AC-1174] Add check for provider users
* [AC-1174] Reduce nested loops
* [AC-1174] Introduce ICollectionAccess.cs
* [AC-1174] Remove individual CollectionGroup and CollectionUser auth handlers and use base class instead
* [AC-1174] Tweak unit test to fail minimally
* [AC-1174] Reorganize authorization handlers in Core project
* [AC-1174] Introduce new AddCoreAuthorizationHandlers() extension method
* [AC-1174] Move CollectionAccessAuthorizationHandler into Api project
* [AC-1174] Move CollectionFixture to Vault folder
* [AC-1174] Rename operation to CreateUpdateDelete
* [AC-1174] Require single organization for collection access authorization handler
- Add requirement that all target collections must belong to the same organization
- Simplify logic related to multiple organizations
- Update tests and helpers
- Use ToHashSet to improve lookup time
* [AC-1174] Fix null reference exception
* [AC-1174] Throw bad request exception when collections belong to different organizations
* [AC-1174] Switch to CollectionAuthorizationHandler instead of CollectionAccessAuthorizationHandler to reduce complexity
* Fix improper merge conflict resolution
* fix: add permission check for collection management api, refs AC-1647 (#3252)
* [AC-1125] Enforce org setting for creating/deleting collections (#3241)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* feat: created collection auth handler/operations, added LimitCollectionCdOwnerAdmin to CurrentContentOrganization, refs AC-1125
* feat: create vault service collection extensions and register with base services, refs AC-1125
* feat: deprecated CurrentContext.CreateNewCollections, refs AC-1125
* feat: deprecate DeleteAnyCollection for single resource usages, refs AC-1125
* feat: move service registration to api, update references, refs AC-1125
* feat: add bulk delete authorization handler, refs AC-1125
* feat: always assign user and give manage access on create, refs AC-1125
* fix: updated CurrentContextOrganization type, refs AC-1125
* feat: combined existing collection authorization handlers/operations, refs AC-1125
* fix: OrganizationServiceTests -> CurrentContentOrganization typo, refs AC-1125
* fix: format, refs AC-1125
* fix: update collection controller tests, refs AC-1125
* fix: dotnet format, refs AC-1125
* feat: removed extra BulkAuthorizationHandler, refs AC-1125
* fix: dotnet format, refs AC-1125
* fix: change string to guid for org id, update bulk delete request model, refs AC-1125
* fix: remove delete many collection check, refs AC-1125
* fix: clean up collection auth handler, refs AC-1125
* fix: format fix for CollectionOperations, refs AC-1125
* fix: removed unnecessary owner check, add org null check to custom permission validation, refs AC-1125
* fix: remove unused methods in CurrentContext, refs AC-1125
* fix: removed obsolete test, fixed failling delete many test, refs AC-1125
* fix: CollectionAuthorizationHandlerTests fixes, refs AC-1125
* fix: OrganizationServiceTests fix broken test by mocking GetOrganization, refs AC-1125
* fix: CollectionAuthorizationHandler - remove unused repository, refs AC-1125
* feat: moved UserId null check to common method, refs AC-1125
* fix: updated auth handler tests to remove dependency on requirement for common code checks, refs AC-1125
* feat: updated conditionals/comments for create/delete methods within colleciton auth handler, refs AC-1125
* feat: added create/delete collection auth handler success methods, refs AC-1125
* fix: new up permissions to prevent excessive null checks, refs AC-1125
* fix: remove old reference to CreateNewCollections, refs AC-1125
* fix: typo within ViewAssignedCollections method, refs AC-1125
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
* refactor: remove organizationId from CollectionBulkDeleteRequestModel, refs AC-1649 (#3282)
* [AC-1174] Bulk Collection Management (#3229)
* [AC-1174] Update SelectionReadOnlyRequestModel to use Guid for Id property
* [AC-1174] Introduce initial bulk-access collection endpoint
* [AC-1174] Introduce BulkAddCollectionAccessCommand and validation logic/tests
* [AC-1174] Add CreateOrUpdateAccessMany method to CollectionRepository
* [AC-1174] Add event logs for bulk add collection access command
* [AC-1174] Add User_BumpAccountRevisionDateByCollectionIds and database migration script
* [AC-1174] Implement EF repository method
* [AC-1174] Improve null checks
* [AC-1174] Remove unnecessary BulkCollectionAccessRequestModel helpers
* [AC-1174] Add unit tests for new controller endpoint
* [AC-1174] Fix formatting
* [AC-1174] Remove comment
* [AC-1174] Remove redundant organizationId parameter
* [AC-1174] Ensure user and group Ids are distinct
* [AC-1174] Cleanup tests based on PR feedback
* [AC-1174] Formatting
* [AC-1174] Update CollectionGroup alias in the sproc
* [AC-1174] Add some additional comments to SQL sproc
* [AC-1174] Add comment explaining additional SaveChangesAsync call
---------
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
* [AC-1646] Rename LimitCollectionCdOwnerAdmin column (#3300)
* Rename LimitCollectionCdOwnerAdmin -> LimitCollectionCreationDeletion
* Rename and bump migration script
* [AC-1666] Removed EditAnyCollection from Create/Delete permission checks (#3301)
* fix: remove EditAnyCollection from Create/Delete permission check, refs AC-1666
* fix: updated comment, refs AC-1666
* [AC-1669] Bug - Remove obsolete assignUserId from CollectionService.SaveAsync(...) (#3312)
* fix: remove AssignUserId from CollectionService.SaveAsync, refs AC-1669
* fix: add manage access conditional before creating collection, refs AC-1669
* fix: move access logic for create/update, fix all tests, refs AC-1669
* fix: add CollectionAccessSelection fixture, update tests, update bad reqeuest message, refs AC-1669
* fix: format, refs AC-1669
* fix: update null params with specific arg.is null checks, refs Ac-1669
* fix: update attribute class name, refs AC-1669
* [AC-1713] [Flexible collections] Add feature flags to server (#3334)
* Add feature flags for FlexibleCollections and BulkCollectionAccess
* Flag new routes and behaviour
---------
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
* Add joint codeownership for auth handlers (#3346)
* [AC-1717] Update default values for LimitCollectionCreationDeletion (#3365)
* Change default value in organization create sproc to 1
* Drop old column name still present in some QA instances
* Set LimitCollectionCreationDeletion value in code based on feature flag
* Fix: add missing namespace after merging in master
* Fix: add missing namespace after merging in master
* [AC-1683] Fix DB migrations for new Manage permission (#3307)
* [AC-1683] Update migration script and introduce V2 procedures and types
* [AC-1683] Update repository calls to use new V2 procedures / types
* [AC-1684] Update bulk add collection migration script to use new V2 type
* [AC-1683] Undo Manage changes to more original procedures
* [AC-1683] Restore whitespace changes
* [AC-1683] Clarify comments regarding explicit column lists
* [AC-1683] Update migration script dates
* [AC-1683] Split the migration script for readability
* [AC-1683] Re-name SelectReadOnlyArray_V2 to CollectionAccessSelectionType
* [AC-1648] [Flexible Collections] Bump migration scripts before feature branch merge (#3371)
* Bump dates on sql migration scripts
* Bump date on ef migrations
* feat: update OrganizationLicense (add property, update GetDataBytes, update VerifyData), refs AC-1721
* feat: update Organization.UpdateFromLicense and SignUpAsync to use value when permittable, refs AC-1721
* feat: Add cloud-only access for PutCollectionManagement endpoint, refs AC-172
* feat: add feature flag to organization entity for updating from license, refs AC-1721
* feat: updated license fixture with new version (14), refs AC-1721
* feat: disable validity checks for version 14, refs AC-1721
* fix: dotnet format, refs AC-1721
* feat: default org license LimitCollectionCreationDeletion to true, refs AC-1721
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
2023-12-08 14:53:53 -06:00
2017-03-23 00:17:34 -04:00
var organization = new Organization
2022-08-29 16:06:55 -04:00
{
2017-08-14 20:57:45 -04:00
Name = license . Name ,
2017-08-16 13:58:52 -04:00
BillingEmail = license . BillingEmail ,
BusinessName = license . BusinessName ,
2017-08-14 20:57:45 -04:00
PlanType = license . PlanType ,
Seats = license . Seats ,
MaxCollections = license . MaxCollections ,
2021-07-08 17:05:32 +02:00
MaxStorageGb = _globalSettings . SelfHosted ? 10240 : license . MaxStorageGb , // 10 TB
2020-01-15 15:00:54 -05:00
UsePolicies = license . UsePolicies ,
2020-07-22 09:38:39 -04:00
UseSso = license . UseSso ,
2021-11-17 11:46:35 +01:00
UseKeyConnector = license . UseKeyConnector ,
2022-07-14 15:58:48 -04:00
UseScim = license . UseScim ,
2021-07-08 17:05:32 +02:00
UseGroups = license . UseGroups ,
2017-08-14 20:57:45 -04:00
UseDirectory = license . UseDirectory ,
2017-12-14 15:48:44 -05:00
UseEvents = license . UseEvents ,
2017-08-14 20:57:45 -04:00
UseTotp = license . UseTotp ,
2018-04-02 14:53:19 -04:00
Use2fa = license . Use2fa ,
2021-07-08 17:05:32 +02:00
UseApi = license . UseApi ,
2021-05-06 14:53:12 -05:00
UseResetPassword = license . UseResetPassword ,
2017-08-14 20:57:45 -04:00
Plan = license . Plan ,
2021-07-08 17:05:32 +02:00
SelfHost = license . SelfHost ,
2017-11-06 16:01:58 -05:00
UsersGetPremium = license . UsersGetPremium ,
2022-12-06 09:50:08 +00:00
UseCustomPermissions = license . UseCustomPermissions ,
2017-08-14 20:57:45 -04:00
Gateway = null ,
2021-07-08 17:05:32 +02:00
GatewayCustomerId = null ,
GatewaySubscriptionId = null ,
ReferenceData = owner . ReferenceData ,
Enabled = license . Enabled ,
2017-08-14 20:57:45 -04:00
ExpirationDate = license . Expires ,
2021-07-08 17:05:32 +02:00
LicenseKey = license . LicenseKey ,
2017-08-14 20:57:45 -04:00
PublicKey = publicKey ,
2021-05-06 14:53:12 -05:00
PrivateKey = privateKey ,
2017-08-14 20:57:45 -04:00
CreationDate = DateTime . UtcNow ,
2023-04-14 11:13:16 +01:00
RevisionDate = DateTime . UtcNow ,
2023-10-16 15:47:12 -05:00
Status = OrganizationStatusType . Created ,
UsePasswordManager = license . UsePasswordManager ,
UseSecretsManager = license . UseSecretsManager ,
SmSeats = license . SmSeats ,
[AC-1721] Include limit collection creation/deletion in license file (#3388)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* fix: merge conflict resolution
* [AC-1174] CollectionUser and CollectionGroup authorization handlers (#3194)
* [AC-1174] Introduce BulkAuthorizationHandler.cs
* [AC-1174] Introduce CollectionUserAuthorizationHandler
* [AC-1174] Add CreateForNewCollection CollectionUser requirement
* [AC-1174] Add some more details to CollectionCustomization
* [AC-1174] Formatting
* [AC-1174] Add CollectionGroupOperation.cs
* [AC-1174] Introduce CollectionGroupAuthorizationHandler.cs
* [AC-1174] Cleanup CollectionFixture customization
Implement and use re-usable extension method to support seeded Guids
* [AC-1174] Introduce WithValueFromList AutoFixtureExtensions
Modify CollectionCustomization to use multiple organization Ids for auto generated test data
* [AC-1174] Simplify CollectionUserAuthorizationHandler.cs
Modify the authorization handler to only perform authorization logic. Validation logic will need to be handled by any calling commands/controllers instead.
* [AC-1174] Introduce shared CollectionAccessAuthorizationHandlerBase
A shared base authorization handler was created for both CollectionUser and CollectionGroup resources, as they share the same underlying management authorization logic.
* [AC-1174] Update CollectionUserAuthorizationHandler and CollectionGroupAuthorizationHandler to use the new CollectionAccessAuthorizationHandlerBase class
* [AC-1174] Formatting
* [AC-1174] Cleanup typo and redundant ToList() call
* [AC-1174] Add check for provider users
* [AC-1174] Reduce nested loops
* [AC-1174] Introduce ICollectionAccess.cs
* [AC-1174] Remove individual CollectionGroup and CollectionUser auth handlers and use base class instead
* [AC-1174] Tweak unit test to fail minimally
* [AC-1174] Reorganize authorization handlers in Core project
* [AC-1174] Introduce new AddCoreAuthorizationHandlers() extension method
* [AC-1174] Move CollectionAccessAuthorizationHandler into Api project
* [AC-1174] Move CollectionFixture to Vault folder
* [AC-1174] Rename operation to CreateUpdateDelete
* [AC-1174] Require single organization for collection access authorization handler
- Add requirement that all target collections must belong to the same organization
- Simplify logic related to multiple organizations
- Update tests and helpers
- Use ToHashSet to improve lookup time
* [AC-1174] Fix null reference exception
* [AC-1174] Throw bad request exception when collections belong to different organizations
* [AC-1174] Switch to CollectionAuthorizationHandler instead of CollectionAccessAuthorizationHandler to reduce complexity
* Fix improper merge conflict resolution
* fix: add permission check for collection management api, refs AC-1647 (#3252)
* [AC-1125] Enforce org setting for creating/deleting collections (#3241)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* feat: created collection auth handler/operations, added LimitCollectionCdOwnerAdmin to CurrentContentOrganization, refs AC-1125
* feat: create vault service collection extensions and register with base services, refs AC-1125
* feat: deprecated CurrentContext.CreateNewCollections, refs AC-1125
* feat: deprecate DeleteAnyCollection for single resource usages, refs AC-1125
* feat: move service registration to api, update references, refs AC-1125
* feat: add bulk delete authorization handler, refs AC-1125
* feat: always assign user and give manage access on create, refs AC-1125
* fix: updated CurrentContextOrganization type, refs AC-1125
* feat: combined existing collection authorization handlers/operations, refs AC-1125
* fix: OrganizationServiceTests -> CurrentContentOrganization typo, refs AC-1125
* fix: format, refs AC-1125
* fix: update collection controller tests, refs AC-1125
* fix: dotnet format, refs AC-1125
* feat: removed extra BulkAuthorizationHandler, refs AC-1125
* fix: dotnet format, refs AC-1125
* fix: change string to guid for org id, update bulk delete request model, refs AC-1125
* fix: remove delete many collection check, refs AC-1125
* fix: clean up collection auth handler, refs AC-1125
* fix: format fix for CollectionOperations, refs AC-1125
* fix: removed unnecessary owner check, add org null check to custom permission validation, refs AC-1125
* fix: remove unused methods in CurrentContext, refs AC-1125
* fix: removed obsolete test, fixed failling delete many test, refs AC-1125
* fix: CollectionAuthorizationHandlerTests fixes, refs AC-1125
* fix: OrganizationServiceTests fix broken test by mocking GetOrganization, refs AC-1125
* fix: CollectionAuthorizationHandler - remove unused repository, refs AC-1125
* feat: moved UserId null check to common method, refs AC-1125
* fix: updated auth handler tests to remove dependency on requirement for common code checks, refs AC-1125
* feat: updated conditionals/comments for create/delete methods within colleciton auth handler, refs AC-1125
* feat: added create/delete collection auth handler success methods, refs AC-1125
* fix: new up permissions to prevent excessive null checks, refs AC-1125
* fix: remove old reference to CreateNewCollections, refs AC-1125
* fix: typo within ViewAssignedCollections method, refs AC-1125
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
* refactor: remove organizationId from CollectionBulkDeleteRequestModel, refs AC-1649 (#3282)
* [AC-1174] Bulk Collection Management (#3229)
* [AC-1174] Update SelectionReadOnlyRequestModel to use Guid for Id property
* [AC-1174] Introduce initial bulk-access collection endpoint
* [AC-1174] Introduce BulkAddCollectionAccessCommand and validation logic/tests
* [AC-1174] Add CreateOrUpdateAccessMany method to CollectionRepository
* [AC-1174] Add event logs for bulk add collection access command
* [AC-1174] Add User_BumpAccountRevisionDateByCollectionIds and database migration script
* [AC-1174] Implement EF repository method
* [AC-1174] Improve null checks
* [AC-1174] Remove unnecessary BulkCollectionAccessRequestModel helpers
* [AC-1174] Add unit tests for new controller endpoint
* [AC-1174] Fix formatting
* [AC-1174] Remove comment
* [AC-1174] Remove redundant organizationId parameter
* [AC-1174] Ensure user and group Ids are distinct
* [AC-1174] Cleanup tests based on PR feedback
* [AC-1174] Formatting
* [AC-1174] Update CollectionGroup alias in the sproc
* [AC-1174] Add some additional comments to SQL sproc
* [AC-1174] Add comment explaining additional SaveChangesAsync call
---------
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
* [AC-1646] Rename LimitCollectionCdOwnerAdmin column (#3300)
* Rename LimitCollectionCdOwnerAdmin -> LimitCollectionCreationDeletion
* Rename and bump migration script
* [AC-1666] Removed EditAnyCollection from Create/Delete permission checks (#3301)
* fix: remove EditAnyCollection from Create/Delete permission check, refs AC-1666
* fix: updated comment, refs AC-1666
* [AC-1669] Bug - Remove obsolete assignUserId from CollectionService.SaveAsync(...) (#3312)
* fix: remove AssignUserId from CollectionService.SaveAsync, refs AC-1669
* fix: add manage access conditional before creating collection, refs AC-1669
* fix: move access logic for create/update, fix all tests, refs AC-1669
* fix: add CollectionAccessSelection fixture, update tests, update bad reqeuest message, refs AC-1669
* fix: format, refs AC-1669
* fix: update null params with specific arg.is null checks, refs Ac-1669
* fix: update attribute class name, refs AC-1669
* [AC-1713] [Flexible collections] Add feature flags to server (#3334)
* Add feature flags for FlexibleCollections and BulkCollectionAccess
* Flag new routes and behaviour
---------
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
* Add joint codeownership for auth handlers (#3346)
* [AC-1717] Update default values for LimitCollectionCreationDeletion (#3365)
* Change default value in organization create sproc to 1
* Drop old column name still present in some QA instances
* Set LimitCollectionCreationDeletion value in code based on feature flag
* Fix: add missing namespace after merging in master
* Fix: add missing namespace after merging in master
* [AC-1683] Fix DB migrations for new Manage permission (#3307)
* [AC-1683] Update migration script and introduce V2 procedures and types
* [AC-1683] Update repository calls to use new V2 procedures / types
* [AC-1684] Update bulk add collection migration script to use new V2 type
* [AC-1683] Undo Manage changes to more original procedures
* [AC-1683] Restore whitespace changes
* [AC-1683] Clarify comments regarding explicit column lists
* [AC-1683] Update migration script dates
* [AC-1683] Split the migration script for readability
* [AC-1683] Re-name SelectReadOnlyArray_V2 to CollectionAccessSelectionType
* [AC-1648] [Flexible Collections] Bump migration scripts before feature branch merge (#3371)
* Bump dates on sql migration scripts
* Bump date on ef migrations
* feat: update OrganizationLicense (add property, update GetDataBytes, update VerifyData), refs AC-1721
* feat: update Organization.UpdateFromLicense and SignUpAsync to use value when permittable, refs AC-1721
* feat: Add cloud-only access for PutCollectionManagement endpoint, refs AC-172
* feat: add feature flag to organization entity for updating from license, refs AC-1721
* feat: updated license fixture with new version (14), refs AC-1721
* feat: disable validity checks for version 14, refs AC-1721
* fix: dotnet format, refs AC-1721
* feat: default org license LimitCollectionCreationDeletion to true, refs AC-1721
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
2023-12-08 14:53:53 -06:00
SmServiceAccounts = license . SmServiceAccounts ,
2024-01-17 22:33:35 +10:00
LimitCollectionCreationDeletion = license . LimitCollectionCreationDeletion ,
AllowAdminAccessToAllCollectionItems = license . AllowAdminAccessToAllCollectionItems ,
// This feature flag indicates that new organizations should be automatically onboarded to
// Flexible Collections enhancements
FlexibleCollections = flexibleCollectionsSignupEnabled ,
2022-08-29 16:06:55 -04:00
} ;
2021-07-08 17:05:32 +02:00
var result = await SignUpAsync ( organization , owner . Id , ownerKey , collectionName , false ) ;
2022-08-29 16:06:55 -04:00
2017-08-16 15:43:11 -04:00
var dir = $"{_globalSettings.LicenseDirectory}/organization" ;
Directory . CreateDirectory ( dir ) ;
2022-06-30 12:19:15 -04:00
await using var fs = new FileStream ( Path . Combine ( dir , $"{organization.Id}.json" ) , FileMode . Create ) ;
2022-01-21 09:36:25 -05:00
await JsonSerializer . SerializeAsync ( fs , license , JsonHelpers . Indented ) ;
2024-02-15 00:41:51 +10:00
return ( result . organization , result . organizationUser ) ;
2022-08-29 16:06:55 -04:00
}
2024-01-17 22:33:35 +10:00
/// <summary>
/// Private helper method to create a new organization.
/// This is common code used by both the cloud and self-hosted methods.
/// </summary>
2024-02-15 00:41:51 +10:00
private async Task < ( Organization organization , OrganizationUser organizationUser , Collection defaultCollection ) > SignUpAsync ( Organization organization ,
2017-08-14 20:57:45 -04:00
Guid ownerId , string ownerKey , string collectionName , bool withPayment )
2022-08-29 16:06:55 -04:00
{
2021-05-06 14:53:12 -05:00
try
2017-08-14 20:57:45 -04:00
{
2022-02-07 09:43:00 +01:00
await _organizationRepository . CreateAsync ( organization ) ;
2021-07-08 17:05:32 +02:00
await _organizationApiKeyRepository . CreateAsync ( new OrganizationApiKey
2022-02-07 09:43:00 +01:00
{
OrganizationId = organization . Id ,
ApiKey = CoreHelpers . SecureRandomString ( 30 ) ,
Type = OrganizationApiKeyType . Default ,
RevisionDate = DateTime . UtcNow ,
2022-08-29 16:06:55 -04:00
} ) ;
2022-02-07 09:43:00 +01:00
await _applicationCacheService . UpsertOrganizationAbilityAsync ( organization ) ;
2024-02-15 00:41:51 +10:00
// ownerId == default if the org is created by a provider - in this case it's created without an
// owner and the first owner is immediately invited afterwards
2020-03-27 14:36:37 -04:00
OrganizationUser orgUser = null ;
if ( ownerId ! = default )
2017-08-16 15:43:11 -04:00
{
2017-11-06 08:12:36 -05:00
orgUser = new OrganizationUser
2022-08-29 16:06:55 -04:00
{
2021-07-08 17:05:32 +02:00
OrganizationId = organization . Id ,
2017-11-06 08:12:36 -05:00
UserId = ownerId ,
Key = ownerKey ,
2023-07-24 23:05:05 +01:00
AccessSecretsManager = organization . UseSecretsManager ,
2017-11-06 08:12:36 -05:00
Type = OrganizationUserType . Owner ,
Status = OrganizationUserStatusType . Confirmed ,
2024-01-22 08:56:20 +10:00
// If using Flexible Collections, AccessAll is deprecated and set to false.
// If not using Flexible Collections, set AccessAll to true (previous behavior)
AccessAll = ! organization . FlexibleCollections ,
2017-11-06 08:12:36 -05:00
CreationDate = organization . CreationDate ,
2019-02-08 23:53:09 -05:00
RevisionDate = organization . CreationDate
2017-11-06 08:12:36 -05:00
} ;
2024-02-12 08:50:41 +10:00
orgUser . SetNewId ( ) ;
2017-11-06 08:12:36 -05:00
2017-12-19 16:02:39 -05:00
await _organizationUserRepository . CreateAsync ( orgUser ) ;
2017-04-04 12:57:50 -04:00
2017-08-30 21:25:46 -04:00
var deviceIds = await GetUserDeviceIdsAsync ( orgUser . UserId . Value ) ;
await _pushRegistrationService . AddUserRegistrationOrganizationAsync ( deviceIds ,
organization . Id . ToString ( ) ) ;
await _pushNotificationService . PushSyncOrgKeysAsync ( ownerId ) ;
}
2017-08-30 21:08:05 -04:00
2024-02-15 00:41:51 +10:00
Collection defaultCollection = null ;
2024-02-12 08:50:41 +10:00
if ( ! string . IsNullOrWhiteSpace ( collectionName ) )
{
2024-02-15 00:41:51 +10:00
defaultCollection = new Collection
2024-02-12 08:50:41 +10:00
{
Name = collectionName ,
OrganizationId = organization . Id ,
CreationDate = organization . CreationDate ,
RevisionDate = organization . CreationDate
} ;
// If using Flexible Collections, give the owner Can Manage access over the default collection
List < CollectionAccessSelection > defaultOwnerAccess = null ;
2024-02-15 00:41:51 +10:00
if ( orgUser ! = null & & organization . FlexibleCollections )
2024-02-12 08:50:41 +10:00
{
defaultOwnerAccess =
[new CollectionAccessSelection { Id = orgUser.Id, HidePasswords = false, ReadOnly = false, Manage = true }] ;
}
await _collectionRepository . CreateAsync ( defaultCollection , null , defaultOwnerAccess ) ;
}
2024-02-15 00:41:51 +10:00
return ( organization , orgUser , defaultCollection ) ;
2022-08-29 16:06:55 -04:00
}
2017-08-14 20:57:45 -04:00
catch
2022-08-29 14:53:16 -04:00
{
2017-08-14 21:25:06 -04:00
if ( withPayment )
2022-08-29 15:53:48 -04:00
{
2021-11-17 11:46:35 +01:00
await _paymentService . CancelAndRecoverChargesAsync ( organization ) ;
2022-08-29 16:06:55 -04:00
}
2021-07-08 17:05:32 +02:00
if ( organization . Id ! = default ( Guid ) )
2022-08-29 16:06:55 -04:00
{
2021-07-08 17:05:32 +02:00
await _organizationRepository . DeleteAsync ( organization ) ;
await _applicationCacheService . DeleteOrganizationAbilityAsync ( organization . Id ) ;
}
2017-04-21 22:39:46 -04:00
2017-03-03 00:07:11 -05:00
throw ;
2022-08-29 16:06:55 -04:00
}
2017-08-14 20:57:45 -04:00
}
2020-07-22 09:38:39 -04:00
public async Task DeleteAsync ( Organization organization )
{
await ValidateDeleteOrganizationAsync ( organization ) ;
2021-09-23 06:36:08 -04:00
2020-03-27 14:36:37 -04:00
if ( ! string . IsNullOrWhiteSpace ( organization . GatewaySubscriptionId ) )
2022-08-29 16:06:55 -04:00
{
try
2022-08-29 15:53:48 -04:00
{
2021-11-17 11:46:35 +01:00
var eop = ! organization . ExpirationDate . HasValue | |
organization . ExpirationDate . Value > = DateTime . UtcNow ;
await _paymentService . CancelSubscriptionAsync ( organization , eop ) ;
await _referenceEventService . RaiseEventAsync (
2023-05-16 16:21:57 +02:00
new ReferenceEvent ( ReferenceEventType . DeleteAccount , organization , _currentContext ) ) ;
2022-08-29 15:53:48 -04:00
}
2020-03-27 14:36:37 -04:00
catch ( GatewayException ) { }
2022-08-29 16:06:55 -04:00
}
2021-11-17 11:46:35 +01:00
2022-07-14 15:58:48 -04:00
await _organizationRepository . DeleteAsync ( organization ) ;
await _applicationCacheService . DeleteOrganizationAbilityAsync ( organization . Id ) ;
}
2021-05-12 14:47:00 -05:00
public async Task EnableAsync ( Guid organizationId , DateTime ? expirationDate )
2022-08-29 16:06:55 -04:00
{
2021-05-12 14:47:00 -05:00
var org = await GetOrgById ( organizationId ) ;
if ( org ! = null & & ! org . Enabled & & org . Gateway . HasValue )
2022-08-29 16:06:55 -04:00
{
2021-05-12 14:47:00 -05:00
org . Enabled = true ;
org . ExpirationDate = expirationDate ;
2021-09-23 06:36:08 -04:00
org . RevisionDate = DateTime . UtcNow ;
2023-02-24 07:54:19 +10:00
await ReplaceAndUpdateCacheAsync ( org ) ;
2022-08-29 15:53:48 -04:00
}
}
2020-01-15 15:00:54 -05:00
2017-08-16 13:58:52 -04:00
public async Task DisableAsync ( Guid organizationId , DateTime ? expirationDate )
2022-08-29 16:06:55 -04:00
{
2017-08-16 13:58:52 -04:00
var org = await GetOrgById ( organizationId ) ;
if ( org ! = null & & org . Enabled )
2022-08-29 15:53:48 -04:00
{
2017-08-16 13:58:52 -04:00
org . Enabled = false ;
org . ExpirationDate = expirationDate ;
org . RevisionDate = DateTime . UtcNow ;
2023-02-24 07:54:19 +10:00
await ReplaceAndUpdateCacheAsync ( org ) ;
2017-08-14 21:25:06 -04:00
2017-08-16 15:43:11 -04:00
// TODO: send email to owners?
2018-09-07 14:00:56 -04:00
}
2022-08-29 16:06:55 -04:00
}
2017-04-11 10:52:28 -04:00
2017-12-19 16:02:39 -05:00
public async Task UpdateExpirationDateAsync ( Guid organizationId , DateTime ? expirationDate )
2022-08-29 16:06:55 -04:00
{
2017-12-19 16:02:39 -05:00
var org = await GetOrgById ( organizationId ) ;
if ( org ! = null )
2022-08-29 14:53:16 -04:00
{
2019-08-09 23:56:26 -04:00
org . ExpirationDate = expirationDate ;
org . RevisionDate = DateTime . UtcNow ;
2023-02-24 07:54:19 +10:00
await ReplaceAndUpdateCacheAsync ( org ) ;
2022-08-29 15:53:48 -04:00
}
2020-03-27 14:36:37 -04:00
}
2022-08-29 15:53:48 -04:00
2019-08-09 23:56:26 -04:00
public async Task EnableAsync ( Guid organizationId )
2022-08-29 16:06:55 -04:00
{
2019-08-09 23:56:26 -04:00
var org = await GetOrgById ( organizationId ) ;
2017-04-10 19:07:38 -04:00
if ( org ! = null & & ! org . Enabled )
2022-08-29 16:06:55 -04:00
{
2017-04-10 19:07:38 -04:00
org . Enabled = true ;
2023-02-24 07:54:19 +10:00
await ReplaceAndUpdateCacheAsync ( org ) ;
2019-08-09 23:56:26 -04:00
}
2022-08-29 16:06:55 -04:00
}
2019-08-09 23:56:26 -04:00
[AC-1179][AC-1737] Event log for collection management setting (#3377)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* fix: merge conflict resolution
* [AC-1174] CollectionUser and CollectionGroup authorization handlers (#3194)
* [AC-1174] Introduce BulkAuthorizationHandler.cs
* [AC-1174] Introduce CollectionUserAuthorizationHandler
* [AC-1174] Add CreateForNewCollection CollectionUser requirement
* [AC-1174] Add some more details to CollectionCustomization
* [AC-1174] Formatting
* [AC-1174] Add CollectionGroupOperation.cs
* [AC-1174] Introduce CollectionGroupAuthorizationHandler.cs
* [AC-1174] Cleanup CollectionFixture customization
Implement and use re-usable extension method to support seeded Guids
* [AC-1174] Introduce WithValueFromList AutoFixtureExtensions
Modify CollectionCustomization to use multiple organization Ids for auto generated test data
* [AC-1174] Simplify CollectionUserAuthorizationHandler.cs
Modify the authorization handler to only perform authorization logic. Validation logic will need to be handled by any calling commands/controllers instead.
* [AC-1174] Introduce shared CollectionAccessAuthorizationHandlerBase
A shared base authorization handler was created for both CollectionUser and CollectionGroup resources, as they share the same underlying management authorization logic.
* [AC-1174] Update CollectionUserAuthorizationHandler and CollectionGroupAuthorizationHandler to use the new CollectionAccessAuthorizationHandlerBase class
* [AC-1174] Formatting
* [AC-1174] Cleanup typo and redundant ToList() call
* [AC-1174] Add check for provider users
* [AC-1174] Reduce nested loops
* [AC-1174] Introduce ICollectionAccess.cs
* [AC-1174] Remove individual CollectionGroup and CollectionUser auth handlers and use base class instead
* [AC-1174] Tweak unit test to fail minimally
* [AC-1174] Reorganize authorization handlers in Core project
* [AC-1174] Introduce new AddCoreAuthorizationHandlers() extension method
* [AC-1174] Move CollectionAccessAuthorizationHandler into Api project
* [AC-1174] Move CollectionFixture to Vault folder
* [AC-1174] Rename operation to CreateUpdateDelete
* [AC-1174] Require single organization for collection access authorization handler
- Add requirement that all target collections must belong to the same organization
- Simplify logic related to multiple organizations
- Update tests and helpers
- Use ToHashSet to improve lookup time
* [AC-1174] Fix null reference exception
* [AC-1174] Throw bad request exception when collections belong to different organizations
* [AC-1174] Switch to CollectionAuthorizationHandler instead of CollectionAccessAuthorizationHandler to reduce complexity
* Fix improper merge conflict resolution
* fix: add permission check for collection management api, refs AC-1647 (#3252)
* [AC-1125] Enforce org setting for creating/deleting collections (#3241)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* feat: created collection auth handler/operations, added LimitCollectionCdOwnerAdmin to CurrentContentOrganization, refs AC-1125
* feat: create vault service collection extensions and register with base services, refs AC-1125
* feat: deprecated CurrentContext.CreateNewCollections, refs AC-1125
* feat: deprecate DeleteAnyCollection for single resource usages, refs AC-1125
* feat: move service registration to api, update references, refs AC-1125
* feat: add bulk delete authorization handler, refs AC-1125
* feat: always assign user and give manage access on create, refs AC-1125
* fix: updated CurrentContextOrganization type, refs AC-1125
* feat: combined existing collection authorization handlers/operations, refs AC-1125
* fix: OrganizationServiceTests -> CurrentContentOrganization typo, refs AC-1125
* fix: format, refs AC-1125
* fix: update collection controller tests, refs AC-1125
* fix: dotnet format, refs AC-1125
* feat: removed extra BulkAuthorizationHandler, refs AC-1125
* fix: dotnet format, refs AC-1125
* fix: change string to guid for org id, update bulk delete request model, refs AC-1125
* fix: remove delete many collection check, refs AC-1125
* fix: clean up collection auth handler, refs AC-1125
* fix: format fix for CollectionOperations, refs AC-1125
* fix: removed unnecessary owner check, add org null check to custom permission validation, refs AC-1125
* fix: remove unused methods in CurrentContext, refs AC-1125
* fix: removed obsolete test, fixed failling delete many test, refs AC-1125
* fix: CollectionAuthorizationHandlerTests fixes, refs AC-1125
* fix: OrganizationServiceTests fix broken test by mocking GetOrganization, refs AC-1125
* fix: CollectionAuthorizationHandler - remove unused repository, refs AC-1125
* feat: moved UserId null check to common method, refs AC-1125
* fix: updated auth handler tests to remove dependency on requirement for common code checks, refs AC-1125
* feat: updated conditionals/comments for create/delete methods within colleciton auth handler, refs AC-1125
* feat: added create/delete collection auth handler success methods, refs AC-1125
* fix: new up permissions to prevent excessive null checks, refs AC-1125
* fix: remove old reference to CreateNewCollections, refs AC-1125
* fix: typo within ViewAssignedCollections method, refs AC-1125
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
* refactor: remove organizationId from CollectionBulkDeleteRequestModel, refs AC-1649 (#3282)
* [AC-1174] Bulk Collection Management (#3229)
* [AC-1174] Update SelectionReadOnlyRequestModel to use Guid for Id property
* [AC-1174] Introduce initial bulk-access collection endpoint
* [AC-1174] Introduce BulkAddCollectionAccessCommand and validation logic/tests
* [AC-1174] Add CreateOrUpdateAccessMany method to CollectionRepository
* [AC-1174] Add event logs for bulk add collection access command
* [AC-1174] Add User_BumpAccountRevisionDateByCollectionIds and database migration script
* [AC-1174] Implement EF repository method
* [AC-1174] Improve null checks
* [AC-1174] Remove unnecessary BulkCollectionAccessRequestModel helpers
* [AC-1174] Add unit tests for new controller endpoint
* [AC-1174] Fix formatting
* [AC-1174] Remove comment
* [AC-1174] Remove redundant organizationId parameter
* [AC-1174] Ensure user and group Ids are distinct
* [AC-1174] Cleanup tests based on PR feedback
* [AC-1174] Formatting
* [AC-1174] Update CollectionGroup alias in the sproc
* [AC-1174] Add some additional comments to SQL sproc
* [AC-1174] Add comment explaining additional SaveChangesAsync call
---------
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
* [AC-1646] Rename LimitCollectionCdOwnerAdmin column (#3300)
* Rename LimitCollectionCdOwnerAdmin -> LimitCollectionCreationDeletion
* Rename and bump migration script
* [AC-1666] Removed EditAnyCollection from Create/Delete permission checks (#3301)
* fix: remove EditAnyCollection from Create/Delete permission check, refs AC-1666
* fix: updated comment, refs AC-1666
* [AC-1669] Bug - Remove obsolete assignUserId from CollectionService.SaveAsync(...) (#3312)
* fix: remove AssignUserId from CollectionService.SaveAsync, refs AC-1669
* fix: add manage access conditional before creating collection, refs AC-1669
* fix: move access logic for create/update, fix all tests, refs AC-1669
* fix: add CollectionAccessSelection fixture, update tests, update bad reqeuest message, refs AC-1669
* fix: format, refs AC-1669
* fix: update null params with specific arg.is null checks, refs Ac-1669
* fix: update attribute class name, refs AC-1669
* [AC-1713] [Flexible collections] Add feature flags to server (#3334)
* Add feature flags for FlexibleCollections and BulkCollectionAccess
* Flag new routes and behaviour
---------
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
* Add joint codeownership for auth handlers (#3346)
* feat: create new event type for collection management updates, refs AC-1179
* feat: add optional event type argument to update async service call, refs AC-1179
* feat: update put management collection call to update async with explicit event type, refs AC-1179
* [AC-1717] Update default values for LimitCollectionCreationDeletion (#3365)
* Change default value in organization create sproc to 1
* Drop old column name still present in some QA instances
* Set LimitCollectionCreationDeletion value in code based on feature flag
* Fix: add missing namespace after merging in master
* Fix: add missing namespace after merging in master
* [AC-1683] Fix DB migrations for new Manage permission (#3307)
* [AC-1683] Update migration script and introduce V2 procedures and types
* [AC-1683] Update repository calls to use new V2 procedures / types
* [AC-1684] Update bulk add collection migration script to use new V2 type
* [AC-1683] Undo Manage changes to more original procedures
* [AC-1683] Restore whitespace changes
* [AC-1683] Clarify comments regarding explicit column lists
* [AC-1683] Update migration script dates
* [AC-1683] Split the migration script for readability
* [AC-1683] Re-name SelectReadOnlyArray_V2 to CollectionAccessSelectionType
* [AC-1648] [Flexible Collections] Bump migration scripts before feature branch merge (#3371)
* Bump dates on sql migration scripts
* Bump date on ef migrations
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
2023-11-22 12:48:59 -06:00
public async Task UpdateAsync ( Organization organization , bool updateBilling = false , EventType eventType = EventType . Organization_Updated )
2022-08-29 16:06:55 -04:00
{
2017-08-12 22:16:42 -04:00
if ( organization . Id = = default ( Guid ) )
2017-04-26 16:14:15 -04:00
{
2017-08-12 22:16:42 -04:00
throw new ApplicationException ( "Cannot create org this way. Call SignUpAsync." ) ;
2017-04-26 16:14:15 -04:00
}
2017-08-12 22:16:42 -04:00
if ( ! string . IsNullOrWhiteSpace ( organization . Identifier ) )
{
2017-12-19 16:02:39 -05:00
var orgById = await _organizationRepository . GetByIdentifierAsync ( organization . Identifier ) ;
if ( orgById ! = null & & orgById . Id ! = organization . Id )
2017-08-12 22:16:42 -04:00
{
throw new BadRequestException ( "Identifier already in use by another organization." ) ;
2017-12-19 16:02:39 -05:00
}
2017-08-12 22:16:42 -04:00
}
[AC-1179][AC-1737] Event log for collection management setting (#3377)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* fix: merge conflict resolution
* [AC-1174] CollectionUser and CollectionGroup authorization handlers (#3194)
* [AC-1174] Introduce BulkAuthorizationHandler.cs
* [AC-1174] Introduce CollectionUserAuthorizationHandler
* [AC-1174] Add CreateForNewCollection CollectionUser requirement
* [AC-1174] Add some more details to CollectionCustomization
* [AC-1174] Formatting
* [AC-1174] Add CollectionGroupOperation.cs
* [AC-1174] Introduce CollectionGroupAuthorizationHandler.cs
* [AC-1174] Cleanup CollectionFixture customization
Implement and use re-usable extension method to support seeded Guids
* [AC-1174] Introduce WithValueFromList AutoFixtureExtensions
Modify CollectionCustomization to use multiple organization Ids for auto generated test data
* [AC-1174] Simplify CollectionUserAuthorizationHandler.cs
Modify the authorization handler to only perform authorization logic. Validation logic will need to be handled by any calling commands/controllers instead.
* [AC-1174] Introduce shared CollectionAccessAuthorizationHandlerBase
A shared base authorization handler was created for both CollectionUser and CollectionGroup resources, as they share the same underlying management authorization logic.
* [AC-1174] Update CollectionUserAuthorizationHandler and CollectionGroupAuthorizationHandler to use the new CollectionAccessAuthorizationHandlerBase class
* [AC-1174] Formatting
* [AC-1174] Cleanup typo and redundant ToList() call
* [AC-1174] Add check for provider users
* [AC-1174] Reduce nested loops
* [AC-1174] Introduce ICollectionAccess.cs
* [AC-1174] Remove individual CollectionGroup and CollectionUser auth handlers and use base class instead
* [AC-1174] Tweak unit test to fail minimally
* [AC-1174] Reorganize authorization handlers in Core project
* [AC-1174] Introduce new AddCoreAuthorizationHandlers() extension method
* [AC-1174] Move CollectionAccessAuthorizationHandler into Api project
* [AC-1174] Move CollectionFixture to Vault folder
* [AC-1174] Rename operation to CreateUpdateDelete
* [AC-1174] Require single organization for collection access authorization handler
- Add requirement that all target collections must belong to the same organization
- Simplify logic related to multiple organizations
- Update tests and helpers
- Use ToHashSet to improve lookup time
* [AC-1174] Fix null reference exception
* [AC-1174] Throw bad request exception when collections belong to different organizations
* [AC-1174] Switch to CollectionAuthorizationHandler instead of CollectionAccessAuthorizationHandler to reduce complexity
* Fix improper merge conflict resolution
* fix: add permission check for collection management api, refs AC-1647 (#3252)
* [AC-1125] Enforce org setting for creating/deleting collections (#3241)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* feat: created collection auth handler/operations, added LimitCollectionCdOwnerAdmin to CurrentContentOrganization, refs AC-1125
* feat: create vault service collection extensions and register with base services, refs AC-1125
* feat: deprecated CurrentContext.CreateNewCollections, refs AC-1125
* feat: deprecate DeleteAnyCollection for single resource usages, refs AC-1125
* feat: move service registration to api, update references, refs AC-1125
* feat: add bulk delete authorization handler, refs AC-1125
* feat: always assign user and give manage access on create, refs AC-1125
* fix: updated CurrentContextOrganization type, refs AC-1125
* feat: combined existing collection authorization handlers/operations, refs AC-1125
* fix: OrganizationServiceTests -> CurrentContentOrganization typo, refs AC-1125
* fix: format, refs AC-1125
* fix: update collection controller tests, refs AC-1125
* fix: dotnet format, refs AC-1125
* feat: removed extra BulkAuthorizationHandler, refs AC-1125
* fix: dotnet format, refs AC-1125
* fix: change string to guid for org id, update bulk delete request model, refs AC-1125
* fix: remove delete many collection check, refs AC-1125
* fix: clean up collection auth handler, refs AC-1125
* fix: format fix for CollectionOperations, refs AC-1125
* fix: removed unnecessary owner check, add org null check to custom permission validation, refs AC-1125
* fix: remove unused methods in CurrentContext, refs AC-1125
* fix: removed obsolete test, fixed failling delete many test, refs AC-1125
* fix: CollectionAuthorizationHandlerTests fixes, refs AC-1125
* fix: OrganizationServiceTests fix broken test by mocking GetOrganization, refs AC-1125
* fix: CollectionAuthorizationHandler - remove unused repository, refs AC-1125
* feat: moved UserId null check to common method, refs AC-1125
* fix: updated auth handler tests to remove dependency on requirement for common code checks, refs AC-1125
* feat: updated conditionals/comments for create/delete methods within colleciton auth handler, refs AC-1125
* feat: added create/delete collection auth handler success methods, refs AC-1125
* fix: new up permissions to prevent excessive null checks, refs AC-1125
* fix: remove old reference to CreateNewCollections, refs AC-1125
* fix: typo within ViewAssignedCollections method, refs AC-1125
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
* refactor: remove organizationId from CollectionBulkDeleteRequestModel, refs AC-1649 (#3282)
* [AC-1174] Bulk Collection Management (#3229)
* [AC-1174] Update SelectionReadOnlyRequestModel to use Guid for Id property
* [AC-1174] Introduce initial bulk-access collection endpoint
* [AC-1174] Introduce BulkAddCollectionAccessCommand and validation logic/tests
* [AC-1174] Add CreateOrUpdateAccessMany method to CollectionRepository
* [AC-1174] Add event logs for bulk add collection access command
* [AC-1174] Add User_BumpAccountRevisionDateByCollectionIds and database migration script
* [AC-1174] Implement EF repository method
* [AC-1174] Improve null checks
* [AC-1174] Remove unnecessary BulkCollectionAccessRequestModel helpers
* [AC-1174] Add unit tests for new controller endpoint
* [AC-1174] Fix formatting
* [AC-1174] Remove comment
* [AC-1174] Remove redundant organizationId parameter
* [AC-1174] Ensure user and group Ids are distinct
* [AC-1174] Cleanup tests based on PR feedback
* [AC-1174] Formatting
* [AC-1174] Update CollectionGroup alias in the sproc
* [AC-1174] Add some additional comments to SQL sproc
* [AC-1174] Add comment explaining additional SaveChangesAsync call
---------
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
* [AC-1646] Rename LimitCollectionCdOwnerAdmin column (#3300)
* Rename LimitCollectionCdOwnerAdmin -> LimitCollectionCreationDeletion
* Rename and bump migration script
* [AC-1666] Removed EditAnyCollection from Create/Delete permission checks (#3301)
* fix: remove EditAnyCollection from Create/Delete permission check, refs AC-1666
* fix: updated comment, refs AC-1666
* [AC-1669] Bug - Remove obsolete assignUserId from CollectionService.SaveAsync(...) (#3312)
* fix: remove AssignUserId from CollectionService.SaveAsync, refs AC-1669
* fix: add manage access conditional before creating collection, refs AC-1669
* fix: move access logic for create/update, fix all tests, refs AC-1669
* fix: add CollectionAccessSelection fixture, update tests, update bad reqeuest message, refs AC-1669
* fix: format, refs AC-1669
* fix: update null params with specific arg.is null checks, refs Ac-1669
* fix: update attribute class name, refs AC-1669
* [AC-1713] [Flexible collections] Add feature flags to server (#3334)
* Add feature flags for FlexibleCollections and BulkCollectionAccess
* Flag new routes and behaviour
---------
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
* Add joint codeownership for auth handlers (#3346)
* feat: create new event type for collection management updates, refs AC-1179
* feat: add optional event type argument to update async service call, refs AC-1179
* feat: update put management collection call to update async with explicit event type, refs AC-1179
* [AC-1717] Update default values for LimitCollectionCreationDeletion (#3365)
* Change default value in organization create sproc to 1
* Drop old column name still present in some QA instances
* Set LimitCollectionCreationDeletion value in code based on feature flag
* Fix: add missing namespace after merging in master
* Fix: add missing namespace after merging in master
* [AC-1683] Fix DB migrations for new Manage permission (#3307)
* [AC-1683] Update migration script and introduce V2 procedures and types
* [AC-1683] Update repository calls to use new V2 procedures / types
* [AC-1684] Update bulk add collection migration script to use new V2 type
* [AC-1683] Undo Manage changes to more original procedures
* [AC-1683] Restore whitespace changes
* [AC-1683] Clarify comments regarding explicit column lists
* [AC-1683] Update migration script dates
* [AC-1683] Split the migration script for readability
* [AC-1683] Re-name SelectReadOnlyArray_V2 to CollectionAccessSelectionType
* [AC-1648] [Flexible Collections] Bump migration scripts before feature branch merge (#3371)
* Bump dates on sql migration scripts
* Bump date on ef migrations
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
2023-11-22 12:48:59 -06:00
await ReplaceAndUpdateCacheAsync ( organization , eventType ) ;
2022-08-29 16:06:55 -04:00
2017-04-26 16:14:15 -04:00
if ( updateBilling & & ! string . IsNullOrWhiteSpace ( organization . GatewayCustomerId ) )
{
2017-12-19 16:02:39 -05:00
var customerService = new CustomerService ( ) ;
await customerService . UpdateAsync ( organization . GatewayCustomerId , new CustomerUpdateOptions
2022-08-29 15:53:48 -04:00
{
2017-12-19 16:02:39 -05:00
Email = organization . BillingEmail ,
Description = organization . BusinessName
} ) ;
2017-04-26 16:14:15 -04:00
}
2022-08-29 16:06:55 -04:00
}
2017-04-26 16:14:15 -04:00
2017-04-10 19:07:38 -04:00
public async Task UpdateTwoFactorProviderAsync ( Organization organization , TwoFactorProviderType type )
2022-08-29 16:06:55 -04:00
{
2020-03-27 14:36:37 -04:00
if ( ! type . ToString ( ) . Contains ( "Organization" ) )
2017-04-10 19:07:38 -04:00
{
throw new ArgumentException ( "Not an organization provider type." ) ;
}
2020-08-12 16:38:22 -04:00
if ( ! organization . Use2fa )
2022-08-29 14:53:16 -04:00
{
2020-08-12 16:38:22 -04:00
throw new BadRequestException ( "Organization cannot use 2FA." ) ;
}
2017-12-19 16:02:39 -05:00
var providers = organization . GetTwoFactorProviders ( ) ;
if ( ! providers ? . ContainsKey ( type ) ? ? true )
2022-08-29 16:06:55 -04:00
{
2017-12-19 16:02:39 -05:00
return ;
2022-08-29 15:53:48 -04:00
}
2017-04-10 19:07:38 -04:00
2019-01-29 14:41:37 -05:00
providers [ type ] . Enabled = true ;
organization . SetTwoFactorProviders ( providers ) ;
await UpdateAsync ( organization ) ;
2022-08-29 16:06:55 -04:00
}
2022-08-29 15:53:48 -04:00
2019-01-29 14:41:37 -05:00
public async Task DisableTwoFactorProviderAsync ( Organization organization , TwoFactorProviderType type )
2017-04-10 19:07:38 -04:00
{
if ( ! type . ToString ( ) . Contains ( "Organization" ) )
2022-08-29 16:06:55 -04:00
{
2017-04-10 19:07:38 -04:00
throw new ArgumentException ( "Not an organization provider type." ) ;
}
2018-04-02 23:18:26 -04:00
var providers = organization . GetTwoFactorProviders ( ) ;
if ( ! providers ? . ContainsKey ( type ) ? ? true )
{
2020-03-27 14:36:37 -04:00
return ;
2018-04-02 23:18:26 -04:00
}
providers . Remove ( type ) ;
organization . SetTwoFactorProviders ( providers ) ;
2020-08-12 16:38:22 -04:00
await UpdateAsync ( organization ) ;
2022-08-29 15:53:48 -04:00
}
2018-04-02 23:18:26 -04:00
public async Task < List < OrganizationUser > > InviteUsersAsync ( Guid organizationId , Guid ? invitingUserId ,
IEnumerable < ( OrganizationUserInvite invite , string externalId ) > invites )
2022-08-29 16:06:55 -04:00
{
2018-04-02 23:18:26 -04:00
var inviteTypes = new HashSet < OrganizationUserType > ( invites . Where ( i = > i . invite . Type . HasValue )
. Select ( i = > i . invite . Type . Value ) ) ;
2024-01-17 22:33:35 +10:00
2018-04-02 23:18:26 -04:00
if ( invitingUserId . HasValue & & inviteTypes . Count > 0 )
{
2023-05-17 14:17:37 +01:00
foreach ( var ( invite , _ ) in invites )
2022-08-29 15:53:48 -04:00
{
2023-05-17 14:17:37 +01:00
await ValidateOrganizationUserUpdatePermissions ( organizationId , invite . Type . Value , null , invite . Permissions ) ;
await ValidateOrganizationCustomPermissionsEnabledAsync ( organizationId , invite . Type . Value ) ;
2022-08-29 15:53:48 -04:00
}
2022-08-29 16:06:55 -04:00
}
2022-08-29 15:53:48 -04:00
2023-05-17 16:39:08 +01:00
var ( organizationUsers , events ) = await SaveUsersSendInvitesAsync ( organizationId , invites , systemUser : null ) ;
2022-11-09 12:13:29 +00:00
await _eventService . LogOrganizationUserEventsAsync ( events ) ;
return organizationUsers ;
}
public async Task < List < OrganizationUser > > InviteUsersAsync ( Guid organizationId , EventSystemUser systemUser ,
IEnumerable < ( OrganizationUserInvite invite , string externalId ) > invites )
{
2023-05-17 16:39:08 +01:00
var ( organizationUsers , events ) = await SaveUsersSendInvitesAsync ( organizationId , invites , systemUser ) ;
2022-11-09 12:13:29 +00:00
await _eventService . LogOrganizationUserEventsAsync ( events . Select ( e = > ( e . Item1 , e . Item2 , systemUser , e . Item3 ) ) ) ;
return organizationUsers ;
}
private async Task < ( List < OrganizationUser > organizationUsers , List < ( OrganizationUser , EventType , DateTime ? ) > events ) > SaveUsersSendInvitesAsync ( Guid organizationId ,
2023-05-17 16:39:08 +01:00
IEnumerable < ( OrganizationUserInvite invite , string externalId ) > invites , EventSystemUser ? systemUser )
2022-11-09 12:13:29 +00:00
{
var organization = await GetOrgById ( organizationId ) ;
var initialSeatCount = organization . Seats ;
if ( organization = = null | | invites . Any ( i = > i . invite . Emails = = null ) )
{
throw new NotFoundException ( ) ;
}
2024-01-22 08:56:20 +10:00
// If the organization is using Flexible Collections, prevent use of any deprecated permissions
if ( organization . FlexibleCollections & & invites . Any ( i = > i . invite . Type is OrganizationUserType . Manager ) )
{
throw new BadRequestException ( "The Manager role has been deprecated by collection enhancements. Use the collection Can Manage permission instead." ) ;
}
if ( organization . FlexibleCollections & & invites . Any ( i = > i . invite . AccessAll ) )
{
throw new BadRequestException ( "The AccessAll property has been deprecated by collection enhancements. Assign the user to collections instead." ) ;
}
// End Flexible Collections
2018-04-02 23:18:26 -04:00
var existingEmails = new HashSet < string > ( await _organizationUserRepository . SelectKnownEmailsAsync (
organizationId , invites . SelectMany ( i = > i . invite . Emails ) , false ) , StringComparer . InvariantCultureIgnoreCase ) ;
2023-08-05 07:51:12 +10:00
// Seat autoscaling
var initialSmSeatCount = organization . SmSeats ;
var newSeatsRequired = 0 ;
2018-04-02 23:18:26 -04:00
if ( organization . Seats . HasValue )
2022-08-29 16:06:55 -04:00
{
2023-02-24 07:54:19 +10:00
var occupiedSeats = await _organizationUserRepository . GetOccupiedSeatCountByOrganizationIdAsync ( organization . Id ) ;
2022-09-23 14:30:39 +10:00
var availableSeats = organization . Seats . Value - occupiedSeats ;
2018-04-02 23:18:26 -04:00
newSeatsRequired = invites . Sum ( i = > i . invite . Emails . Count ( ) ) - existingEmails . Count ( ) - availableSeats ;
}
2021-09-23 06:36:08 -04:00
if ( newSeatsRequired > 0 )
2021-05-17 09:43:02 -05:00
{
2023-11-20 09:05:35 -05:00
var ( canScale , failureReason ) = await CanScaleAsync ( organization , newSeatsRequired ) ;
2021-09-23 06:36:08 -04:00
if ( ! canScale )
2021-05-17 09:43:02 -05:00
{
throw new BadRequestException ( failureReason ) ;
}
2022-08-29 16:06:55 -04:00
}
2021-05-17 09:43:02 -05:00
2023-08-05 07:51:12 +10:00
// Secrets Manager seat autoscaling
SecretsManagerSubscriptionUpdate smSubscriptionUpdate = null ;
var inviteWithSmAccessCount = invites
. Where ( i = > i . invite . AccessSecretsManager )
. SelectMany ( i = > i . invite . Emails )
. Count ( email = > ! existingEmails . Contains ( email ) ) ;
var additionalSmSeatsRequired = await _countNewSmSeatsRequiredQuery . CountNewSmSeatsRequiredAsync ( organization . Id , inviteWithSmAccessCount ) ;
if ( additionalSmSeatsRequired > 0 )
{
2023-08-28 08:05:23 +10:00
smSubscriptionUpdate = new SecretsManagerSubscriptionUpdate ( organization , true )
. AdjustSeats ( additionalSmSeatsRequired ) ;
2023-08-05 07:51:12 +10:00
await _updateSecretsManagerSubscriptionCommand . ValidateUpdate ( smSubscriptionUpdate ) ;
}
2021-05-17 09:43:02 -05:00
var invitedAreAllOwners = invites . All ( i = > i . invite . Type = = OrganizationUserType . Owner ) ;
2023-05-17 16:39:08 +01:00
if ( ! invitedAreAllOwners & & ! await HasConfirmedOwnersExceptAsync ( organizationId , new Guid [ ] { } , includeProvider : true ) )
2022-08-29 16:06:55 -04:00
{
2021-07-08 17:05:32 +02:00
throw new BadRequestException ( "Organization must have at least one confirmed owner." ) ;
2022-08-29 15:53:48 -04:00
}
2021-05-17 09:43:02 -05:00
var orgUsers = new List < OrganizationUser > ( ) ;
2023-01-19 17:00:54 +01:00
var limitedCollectionOrgUsers = new List < ( OrganizationUser , IEnumerable < CollectionAccessSelection > ) > ( ) ;
var orgUserGroups = new List < ( OrganizationUser , IEnumerable < Guid > ) > ( ) ;
2021-09-28 16:18:44 -04:00
var orgUserInvitedCount = 0 ;
2021-09-23 06:36:08 -04:00
var exceptions = new List < Exception > ( ) ;
2021-09-28 16:18:44 -04:00
var events = new List < ( OrganizationUser , EventType , DateTime ? ) > ( ) ;
foreach ( var ( invite , externalId ) in invites )
2022-08-29 16:06:55 -04:00
{
2022-07-13 09:21:28 -04:00
// Prevent duplicate invitations
2021-09-23 06:36:08 -04:00
foreach ( var email in invite . Emails . Distinct ( ) )
{
2022-08-29 16:06:55 -04:00
try
2021-09-28 16:18:44 -04:00
{
// Make sure user is not already invited
if ( existingEmails . Contains ( email ) )
2022-08-29 16:06:55 -04:00
{
2021-09-28 16:18:44 -04:00
continue ;
2021-09-23 06:36:08 -04:00
}
var orgUser = new OrganizationUser
2022-08-29 16:06:55 -04:00
{
2021-05-17 09:43:02 -05:00
OrganizationId = organizationId ,
2021-09-23 06:36:08 -04:00
UserId = null ,
Email = email . ToLowerInvariant ( ) ,
Key = null ,
Type = invite . Type . Value ,
Status = OrganizationUserStatusType . Invited ,
AccessAll = invite . AccessAll ,
2023-01-31 18:38:53 +01:00
AccessSecretsManager = invite . AccessSecretsManager ,
2021-09-23 06:36:08 -04:00
ExternalId = externalId ,
CreationDate = DateTime . UtcNow ,
RevisionDate = DateTime . UtcNow ,
2021-05-17 09:43:02 -05:00
} ;
if ( invite . Permissions ! = null )
2022-08-29 16:06:55 -04:00
{
2022-01-21 09:36:25 -05:00
orgUser . Permissions = JsonSerializer . Serialize ( invite . Permissions , JsonHelpers . CamelCase ) ;
2022-08-29 16:06:55 -04:00
}
2021-09-23 06:36:08 -04:00
if ( ! orgUser . AccessAll & & invite . Collections . Any ( ) )
2021-05-17 09:43:02 -05:00
{
2021-09-23 06:36:08 -04:00
limitedCollectionOrgUsers . Add ( ( orgUser , invite . Collections ) ) ;
2021-05-17 09:43:02 -05:00
}
else
{
orgUsers . Add ( orgUser ) ;
}
2017-04-07 16:41:04 -04:00
2023-01-19 17:00:54 +01:00
if ( invite . Groups ! = null & & invite . Groups . Any ( ) )
{
orgUserGroups . Add ( ( orgUser , invite . Groups ) ) ;
}
2017-05-11 14:52:35 -04:00
events . Add ( ( orgUser , EventType . OrganizationUser_Invited , DateTime . UtcNow ) ) ;
orgUserInvitedCount + + ;
2022-08-29 15:53:48 -04:00
}
2021-07-08 17:05:32 +02:00
catch ( Exception e )
2022-08-29 15:53:48 -04:00
{
2021-09-23 06:36:08 -04:00
exceptions . Add ( e ) ;
2017-04-20 23:50:12 -04:00
}
2022-08-29 15:53:48 -04:00
}
2022-08-29 16:06:55 -04:00
}
2022-08-29 15:53:48 -04:00
2021-05-25 19:23:47 +02:00
if ( exceptions . Any ( ) )
2022-08-29 14:53:16 -04:00
{
2021-05-12 11:18:25 +02:00
throw new AggregateException ( "One or more errors occurred while inviting users." , exceptions ) ;
2022-08-29 15:53:48 -04:00
}
2021-09-23 06:36:08 -04:00
var prorationDate = DateTime . UtcNow ;
2022-08-29 16:06:55 -04:00
try
{
2021-05-17 09:43:02 -05:00
await _organizationUserRepository . CreateManyAsync ( orgUsers ) ;
2021-09-23 06:36:08 -04:00
foreach ( var ( orgUser , collections ) in limitedCollectionOrgUsers )
2022-08-29 16:06:55 -04:00
{
2021-05-12 11:18:25 +02:00
await _organizationUserRepository . CreateAsync ( orgUser , collections ) ;
2022-08-29 15:53:48 -04:00
}
2021-05-25 19:23:47 +02:00
2023-01-19 17:00:54 +01:00
foreach ( var ( orgUser , groups ) in orgUserGroups )
{
await _organizationUserRepository . UpdateGroupsAsync ( orgUser . Id , groups ) ;
}
2021-05-25 19:23:47 +02:00
if ( ! await _currentContext . ManageUsers ( organization . Id ) )
2021-05-12 11:18:25 +02:00
{
2021-05-25 19:23:47 +02:00
throw new BadRequestException ( "Cannot add seats. Cannot manage organization users." ) ;
2021-05-12 11:18:25 +02:00
}
2021-05-25 19:23:47 +02:00
2023-08-05 07:51:12 +10:00
if ( additionalSmSeatsRequired > 0 )
{
smSubscriptionUpdate . ProrationDate = prorationDate ;
await _updateSecretsManagerSubscriptionCommand . UpdateSubscriptionAsync ( smSubscriptionUpdate ) ;
}
2021-09-23 06:36:08 -04:00
await AutoAddSeatsAsync ( organization , newSeatsRequired , prorationDate ) ;
await SendInvitesAsync ( orgUsers . Concat ( limitedCollectionOrgUsers . Select ( u = > u . Item1 ) ) , organization ) ;
2022-08-29 14:53:16 -04:00
2019-10-07 16:23:38 -04:00
await _referenceEventService . RaiseEventAsync (
2023-05-16 16:21:57 +02:00
new ReferenceEvent ( ReferenceEventType . InvitedUsers , organization , _currentContext )
2022-08-29 16:06:55 -04:00
{
2021-09-23 06:36:08 -04:00
Users = orgUserInvitedCount
2022-08-29 16:06:55 -04:00
} ) ;
}
2021-09-23 06:36:08 -04:00
catch ( Exception e )
2022-08-29 14:53:16 -04:00
{
2021-09-23 06:36:08 -04:00
// Revert any added users.
2021-05-25 19:23:47 +02:00
var invitedOrgUserIds = orgUsers . Select ( u = > u . Id ) . Concat ( limitedCollectionOrgUsers . Select ( u = > u . Item1 . Id ) ) ;
await _organizationUserRepository . DeleteManyAsync ( invitedOrgUserIds ) ;
2023-08-05 07:51:12 +10:00
var currentOrganization = await _organizationRepository . GetByIdAsync ( organization . Id ) ;
// Revert autoscaling
if ( initialSeatCount . HasValue & & currentOrganization . Seats . HasValue & & currentOrganization . Seats . Value ! = initialSeatCount . Value )
{
await AdjustSeatsAsync ( organization , initialSeatCount . Value - currentOrganization . Seats . Value , prorationDate ) ;
}
2021-05-12 11:18:25 +02:00
2023-08-05 07:51:12 +10:00
// Revert SmSeat autoscaling
if ( initialSmSeatCount . HasValue & & currentOrganization . SmSeats . HasValue & &
currentOrganization . SmSeats . Value ! = initialSmSeatCount . Value )
2022-08-29 15:53:48 -04:00
{
2023-08-05 07:51:12 +10:00
var smSubscriptionUpdateRevert = new SecretsManagerSubscriptionUpdate ( currentOrganization , false )
{
SmSeats = initialSmSeatCount . Value ,
ProrationDate = prorationDate
} ;
await _updateSecretsManagerSubscriptionCommand . UpdateSubscriptionAsync ( smSubscriptionUpdateRevert ) ;
2022-08-29 15:53:48 -04:00
}
2022-08-29 14:53:16 -04:00
2021-09-23 06:36:08 -04:00
exceptions . Add ( e ) ;
2022-08-29 16:06:55 -04:00
}
2021-09-23 06:36:08 -04:00
if ( exceptions . Any ( ) )
2022-08-29 16:06:55 -04:00
{
2021-05-25 19:23:47 +02:00
throw new AggregateException ( "One or more errors occurred while inviting users." , exceptions ) ;
2022-08-29 15:53:48 -04:00
}
2022-11-09 12:13:29 +00:00
return ( orgUsers , events ) ;
2022-08-29 16:06:55 -04:00
}
2021-05-25 19:23:47 +02:00
public async Task < IEnumerable < Tuple < OrganizationUser , string > > > ResendInvitesAsync ( Guid organizationId , Guid ? invitingUserId ,
IEnumerable < Guid > organizationUsersId )
2022-08-29 16:06:55 -04:00
{
2021-05-25 19:23:47 +02:00
var orgUsers = await _organizationUserRepository . GetManyAsync ( organizationUsersId ) ;
var org = await GetOrgById ( organizationId ) ;
2022-08-29 16:06:55 -04:00
2019-10-07 16:23:38 -04:00
var result = new List < Tuple < OrganizationUser , string > > ( ) ;
2021-05-25 19:23:47 +02:00
foreach ( var orgUser in orgUsers )
2017-03-23 00:17:34 -04:00
{
2020-03-27 14:36:37 -04:00
if ( orgUser . Status ! = OrganizationUserStatusType . Invited | | orgUser . OrganizationId ! = organizationId )
2017-03-23 00:17:34 -04:00
{
result . Add ( Tuple . Create ( orgUser , "User invalid." ) ) ;
continue ;
}
2023-04-14 11:13:16 +01:00
await SendInviteAsync ( orgUser , org , false ) ;
2019-10-07 16:23:38 -04:00
result . Add ( Tuple . Create ( orgUser , "" ) ) ;
2017-03-23 00:17:34 -04:00
}
2021-05-17 09:43:02 -05:00
return result ;
}
2021-12-16 15:35:09 +01:00
2023-04-14 11:13:16 +01:00
public async Task ResendInviteAsync ( Guid organizationId , Guid ? invitingUserId , Guid organizationUserId , bool initOrganization = false )
2022-08-29 16:06:55 -04:00
{
2022-05-10 17:12:09 -04:00
var orgUser = await _organizationUserRepository . GetByIdAsync ( organizationUserId ) ;
if ( orgUser = = null | | orgUser . OrganizationId ! = organizationId | |
orgUser . Status ! = OrganizationUserStatusType . Invited )
2022-08-29 16:06:55 -04:00
{
2022-05-10 17:12:09 -04:00
throw new BadRequestException ( "User invalid." ) ;
2017-03-23 00:17:34 -04:00
}
2020-07-15 12:38:45 -04:00
var org = await GetOrgById ( orgUser . OrganizationId ) ;
2023-04-14 11:13:16 +01:00
await SendInviteAsync ( orgUser , org , initOrganization ) ;
2022-08-29 16:06:55 -04:00
}
2022-05-10 17:12:09 -04:00
private async Task SendInvitesAsync ( IEnumerable < OrganizationUser > orgUsers , Organization organization )
2022-08-29 16:06:55 -04:00
{
2023-12-18 11:16:17 -05:00
var orgInvitesInfo = await BuildOrganizationInvitesInfoAsync ( orgUsers , organization ) ;
await _mailService . SendOrganizationInviteEmailsAsync ( orgInvitesInfo ) ;
}
private async Task SendInviteAsync ( OrganizationUser orgUser , Organization organization , bool initOrganization )
{
// convert single org user into array of 1 org user
var orgUsers = new [ ] { orgUser } ;
var orgInvitesInfo = await BuildOrganizationInvitesInfoAsync ( orgUsers , organization , initOrganization ) ;
await _mailService . SendOrganizationInviteEmailsAsync ( orgInvitesInfo ) ;
}
private async Task < OrganizationInvitesInfo > BuildOrganizationInvitesInfoAsync (
IEnumerable < OrganizationUser > orgUsers ,
Organization organization ,
bool initOrganization = false )
{
// Materialize the sequence into a list to avoid multiple enumeration warnings
var orgUsersList = orgUsers . ToList ( ) ;
// Email links must include information about the org and user for us to make routing decisions client side
// Given an org user, determine if existing BW user exists
var orgUserEmails = orgUsersList . Select ( ou = > ou . Email ) . ToList ( ) ;
var existingUsers = await _userRepository . GetManyByEmailsAsync ( orgUserEmails ) ;
// hash existing users emails list for O(1) lookups
var existingUserEmailsHashSet = new HashSet < string > ( existingUsers . Select ( u = > u . Email ) ) ;
// Create a dictionary of org user guids and bools for whether or not they have an existing BW user
var orgUserHasExistingUserDict = orgUsersList . ToDictionary (
ou = > ou . Id ,
ou = > existingUserEmailsHashSet . Contains ( ou . Email )
) ;
// Determine if org has SSO enabled and if user is required to login with SSO
// Note: we only want to call the DB after checking if the org can use SSO per plan and if they have any policies enabled.
2023-12-18 19:34:56 -05:00
var orgSsoEnabled = organization . UseSso & & ( await _ssoConfigRepository . GetByOrganizationIdAsync ( organization . Id ) ) ? . Enabled = = true ;
2023-12-18 11:16:17 -05:00
// Even though the require SSO policy can be turned on regardless of SSO being enabled, for this logic, we only
// need to check the policy if the org has SSO enabled.
var orgSsoLoginRequiredPolicyEnabled = orgSsoEnabled & &
organization . UsePolicies & &
2024-01-11 09:58:15 -05:00
( await _policyRepository . GetByOrganizationIdTypeAsync ( organization . Id , PolicyType . RequireSso ) ) ? . Enabled = = true ;
2023-12-18 11:16:17 -05:00
// Generate the list of org users and expiring tokens
// create helper function to create expiring tokens
Auth/PM-3275 - Changes to support TDE User without MP being able to Set a Password + misc refactoring (#3242)
* PM-3275 - Add new GetMasterPasswordPolicy endpoint which will allow authenticated clients to get an enabled MP org policy if it exists for the purposes of enforcing those policy requirements when setting a password.
* PM-3275 - AccountsController.cs - PostSetPasswordAsync - (1) Convert UserService.setPasswordAsync into new SetInitialMasterPasswordCommand (2) Refactor SetInitialMasterPasswordCommand to only accept post SSO users who are in the invited state
(3) Add TODOs for more cleanup work and more commands
* PM-3275 - Update AccountsControllerTests.cs to add new SetInitialMasterPasswordCommand
* PM-3275 - UserService.cs - Remove non implemented ChangePasswordAsync method
* PM-3275 - The new SetInitialMasterPasswordCommand leveraged the OrganizationService.cs AcceptUserAsync method so while I was in here I converted the AcceptUserAsync methods into a new AcceptOrgUserCommand.cs and turned the private method which accepted an existing org user public for use in the SetInitialMasterPasswordCommand
* PM-3275 - Dotnet format
* PM-3275 - Test SetInitialMasterPasswordCommand
* Dotnet format
* PM-3275 - In process AcceptOrgUserCommandTests.cs
* PM-3275 - Migrate changes from AC-244 / #3199 over into new AcceptOrgUserCommand
* PM-3275 - AcceptOrgUserCommand.cs - create data protector specifically for this command
* PM-3275 - Add TODO for renaming / removing overloading of methods to improve readability / clarity
* PM-3275 - AcceptOrgUserCommand.cs - refactor AcceptOrgUserAsync by OrgId to retrieve orgUser with _organizationUserRepository.GetByOrganizationAsync which gets a single user instead of a collection
* PM-3275 - AcceptOrgUserCommand.cs - update name in TODO for evaluation later
* PM-3275 / PM-1196 - (1) Slightly refactor SsoEmail2faSessionTokenable to provide public static GetTokenLifeTime() method for testing (2) Add missed tests to SsoEmail2faSessionTokenable in preparation for building tests for new OrgUserInviteTokenable.cs
* PM-3275 / PM-1196 - Removing SsoEmail2faSessionTokenable.cs changes + tests as I've handled that separately in a new PR (#3270) for newly created task PM-3925
* PM-3275 - ExpiringTokenable.cs - add clarifying comments to help distinguish between the Valid property and the TokenIsValid method.
* PM-3275 - Create OrgUserInviteTokenable.cs and add tests in OrgUserInviteTokenableTests.cs
* PM-3275 - OrganizationService.cs - Refactor Org User Invite methods to use new OrgUserInviteTokenable instead of manual creation of a token
* PM-3275 - OrgUserInviteTokenable.cs - clarify backwards compat note
* PM-3275 - AcceptOrgUserCommand.cs - Add TODOs + minor name refactor
* PM-3275 - AcceptOrgUserCommand.cs - replace method overloading with more easily readable names.
* PM-3275 - AcceptOrgUserCommand.cs - Update ValidateOrgUserInviteToken to add new token validation while maintaining backwards compatibility for 1 release.
* dotnet format
* PM-3275 - AcceptOrgUserCommand.cs - Move private method below where it is used
* PM-3275 - ServiceCollectionExtensions.cs - Must register IDataProtectorTokenFactory<OrgUserInviteTokenable> for new tokenable
* PM-3275 - OrgUserInviteTokenable needed access to global settings to set its token lifetime to the _globalSettings.OrganizationInviteExpirationHours value. Creating a factory seemed the most straightforward way to encapsulate the desired creation logic. Unsure if in the correct location in ServiceCollectionExtensions.cs but will figure that out later.
* PM-3275 - In process work of creating AcceptOrgUserCommandTests.cs
* PM-3275 - Remove no longer relevant AcceptOrgUser tests from OrganizationServiceTests.cs
* PM-3275 - Register OrgUserInviteTokenableFactory alongside tokenizer
* PM-3275 - AcceptOrgUserCommandTests.cs - AcceptOrgUserAsync basic test suite completed.
* PM-3275 - AcceptOrgUserCommandTests.cs - tweak test names
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Remove old tests from OrganizationServiceTests as no longer needed to reference (2) Add summary for SetupCommonAcceptOrgUserMocks (3) Get AcceptOrgUserByToken_OldToken_AcceptsUserAndVerifiesEmail passing
* PM-3275 - Create interface for OrgUserInviteTokenableFactory b/c that's the right thing to do + enables test substitution
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Start work on AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail (2) Create and use SetupCommonAcceptOrgUserByTokenMocks() (3) Create generic FakeDataProtectorTokenFactory for tokenable testing
* PM-3275 - (1) Get AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail test passing (2) Move FakeDataProtectorTokenFactory to own file
* PM-3275 - AcceptOrgUserCommandTests.cs - Finish up tests for AcceptOrgUserByTokenAsync
* PM-3275 - Add pseudo section comments
* PM-3275 - Clean up unused params on AcceptOrgUserByToken_EmailMismatch_ThrowsBadRequest test
* PM-3275 - (1) Tests written for AcceptOrgUserByOrgSsoIdAsync (2) Refactor happy path assertions into helper function AssertValidAcceptedOrgUser to reduce code duplication
* PM-3275 - Finish up testing AcceptOrgUserCommandTests.cs by adding tests for AcceptOrgUserByOrgIdAsync
* PM-3275 - Tweaking test naming to ensure consistency.
* PM-3275 - Bugfix - OrgUserInviteTokenableFactory implementation required when declaring singleton service in ServiceCollectionExtensions.cs
* PM-3275 - Resolve failing OrganizationServiceTests.cs
* dotnet format
* PM-3275 - PoliciesController.cs - GetMasterPasswordPolicy bugfix - for orgs without a MP policy, policy comes back as null and we should return notFound in that case.
* PM-3275 - Add PoliciesControllerTests.cs specifically for new GetMasterPasswordPolicy(...) endpoint.
* PM-3275 - dotnet format PoliciesControllerTests.cs
* PM-3275 - PoliciesController.cs - (1) Add tech debt task number (2) Properly flag endpoint as deprecated
* PM-3275 - Add new hasManageResetPasswordPermission property to ProfileResponseModel.cs primarily for sync so that we can condition client side if TDE user obtains elevated permissions
* PM-3275 - Fix AccountsControllerTests.cs
* PM-3275 - OrgUserInviteTokenable.cs - clarify TODO
* PM-3275 - AcceptOrgUserCommand.cs - Refactor token validation to use short circuiting to only run old token validation if new token validation fails.
* PM-3275 - OrgUserInviteTokenable.cs - (1) Add new static methods to centralize validation logic to avoid repetition (2) Add new token validation method so we can avoid having to pass in a full org user (and hitting the db to do so)
* PM-3275 - Realized that the old token validation was used in the PoliciesController.cs (existing user clicks invite link in email and goes to log in) and UserService.cs (user clicks invite link in email and registers for a new acct). Added tech debt item for cleaning up backwards compatibility in future.
* dotnet format
* PM-3275 - (1) AccountsController.cs - Update PostSetPasswordAsync SetPasswordRequestModel to allow null keys for the case where we have a TDE user who obtains elevated permissions - they already have a user public and user encrypted private key saved in the db. (2) AccountsControllerTests.cs - test PostSetPasswordAsync scenarios to ensure changes will work as expected.
* PM-3275 - PR review feedback - (1) set CurrentContext to private (2) Refactor GetProfile to use variables to improve clarity and simplify debugging.
* PM-3275 - SyncController.cs - PR Review Feedback - Set current context as private instead of protected.
* PM-3275 - CurrentContextExtensions.cs - PR Feedback - move parenthesis up from own line.
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - Replace unnecessary variable
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - PR Feedback - Add expected outcome statement to test name
* PM-3275 - Set Initial Password command and tests - PR Feedback changes - (1) Rename orgIdentifier --> OrgSsoIdentifier for clarity (2) Update SetInitialMasterPasswordAsync to not allow null orgSsoId with explicit message saying this vs letting null org trigger invalid organization (3) Add test to cover this new scenario.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Move summary from implementation to interface to better respect standards and the fact that the interface is the more seen piece of code.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, rename AcceptOrgUserByTokenAsync -> AcceptOrgUserByEmailTokenAsync + replace generic name token with emailToken
* PM-3275 - OrganizationService.cs - Per PR feedback, remove dupe line
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove new lines in error messages for consistency.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Per PR feedback, adjust formatting of constructor for improved readability.
* PM-3275 - CurrentContextExtensions.cs - Refactor AnyOrgUserHasManageResetPasswordPermission per PR feedback to remove unnecessary var.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove completed TODO
* PM-3275 - PoliciesController.cs - Per PR feedback, update GetByInvitedUser param to be guid instead of string.
* PM-3275 - OrgUserInviteTokenable.cs - per PR feedback, add tech debt item info.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, use const purpose from tokenable instead of magic string.
* PM-3275 - Restore non duplicate line to fix tests
* PM-3275 - Per PR feedback, revert all sync controller changes as the ProfileResponseModel.organizations array has org objects which have permissions which have the ManageResetPassword permission. So, I have the information that I need clientside already to determine if the user has the ManageResetPassword in any org.
* PM-3275 - PoliciesControllerTests.cs - Update imports as the PoliciesController was moved under the admin console team's domain.
* PM-3275 - Resolve issues from merge conflict resolutions to get solution building.
* PM-3275 / PM-4633 - PoliciesController.cs - use orgUserId to look up user instead of orgId. Oops.
* Fix user service tests
* Resolve merge conflict
2023-11-02 11:02:25 -04:00
( OrganizationUser , ExpiringToken ) MakeOrgUserExpiringTokenPair ( OrganizationUser orgUser )
2022-08-29 15:53:48 -04:00
{
Auth/PM-3275 - Changes to support TDE User without MP being able to Set a Password + misc refactoring (#3242)
* PM-3275 - Add new GetMasterPasswordPolicy endpoint which will allow authenticated clients to get an enabled MP org policy if it exists for the purposes of enforcing those policy requirements when setting a password.
* PM-3275 - AccountsController.cs - PostSetPasswordAsync - (1) Convert UserService.setPasswordAsync into new SetInitialMasterPasswordCommand (2) Refactor SetInitialMasterPasswordCommand to only accept post SSO users who are in the invited state
(3) Add TODOs for more cleanup work and more commands
* PM-3275 - Update AccountsControllerTests.cs to add new SetInitialMasterPasswordCommand
* PM-3275 - UserService.cs - Remove non implemented ChangePasswordAsync method
* PM-3275 - The new SetInitialMasterPasswordCommand leveraged the OrganizationService.cs AcceptUserAsync method so while I was in here I converted the AcceptUserAsync methods into a new AcceptOrgUserCommand.cs and turned the private method which accepted an existing org user public for use in the SetInitialMasterPasswordCommand
* PM-3275 - Dotnet format
* PM-3275 - Test SetInitialMasterPasswordCommand
* Dotnet format
* PM-3275 - In process AcceptOrgUserCommandTests.cs
* PM-3275 - Migrate changes from AC-244 / #3199 over into new AcceptOrgUserCommand
* PM-3275 - AcceptOrgUserCommand.cs - create data protector specifically for this command
* PM-3275 - Add TODO for renaming / removing overloading of methods to improve readability / clarity
* PM-3275 - AcceptOrgUserCommand.cs - refactor AcceptOrgUserAsync by OrgId to retrieve orgUser with _organizationUserRepository.GetByOrganizationAsync which gets a single user instead of a collection
* PM-3275 - AcceptOrgUserCommand.cs - update name in TODO for evaluation later
* PM-3275 / PM-1196 - (1) Slightly refactor SsoEmail2faSessionTokenable to provide public static GetTokenLifeTime() method for testing (2) Add missed tests to SsoEmail2faSessionTokenable in preparation for building tests for new OrgUserInviteTokenable.cs
* PM-3275 / PM-1196 - Removing SsoEmail2faSessionTokenable.cs changes + tests as I've handled that separately in a new PR (#3270) for newly created task PM-3925
* PM-3275 - ExpiringTokenable.cs - add clarifying comments to help distinguish between the Valid property and the TokenIsValid method.
* PM-3275 - Create OrgUserInviteTokenable.cs and add tests in OrgUserInviteTokenableTests.cs
* PM-3275 - OrganizationService.cs - Refactor Org User Invite methods to use new OrgUserInviteTokenable instead of manual creation of a token
* PM-3275 - OrgUserInviteTokenable.cs - clarify backwards compat note
* PM-3275 - AcceptOrgUserCommand.cs - Add TODOs + minor name refactor
* PM-3275 - AcceptOrgUserCommand.cs - replace method overloading with more easily readable names.
* PM-3275 - AcceptOrgUserCommand.cs - Update ValidateOrgUserInviteToken to add new token validation while maintaining backwards compatibility for 1 release.
* dotnet format
* PM-3275 - AcceptOrgUserCommand.cs - Move private method below where it is used
* PM-3275 - ServiceCollectionExtensions.cs - Must register IDataProtectorTokenFactory<OrgUserInviteTokenable> for new tokenable
* PM-3275 - OrgUserInviteTokenable needed access to global settings to set its token lifetime to the _globalSettings.OrganizationInviteExpirationHours value. Creating a factory seemed the most straightforward way to encapsulate the desired creation logic. Unsure if in the correct location in ServiceCollectionExtensions.cs but will figure that out later.
* PM-3275 - In process work of creating AcceptOrgUserCommandTests.cs
* PM-3275 - Remove no longer relevant AcceptOrgUser tests from OrganizationServiceTests.cs
* PM-3275 - Register OrgUserInviteTokenableFactory alongside tokenizer
* PM-3275 - AcceptOrgUserCommandTests.cs - AcceptOrgUserAsync basic test suite completed.
* PM-3275 - AcceptOrgUserCommandTests.cs - tweak test names
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Remove old tests from OrganizationServiceTests as no longer needed to reference (2) Add summary for SetupCommonAcceptOrgUserMocks (3) Get AcceptOrgUserByToken_OldToken_AcceptsUserAndVerifiesEmail passing
* PM-3275 - Create interface for OrgUserInviteTokenableFactory b/c that's the right thing to do + enables test substitution
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Start work on AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail (2) Create and use SetupCommonAcceptOrgUserByTokenMocks() (3) Create generic FakeDataProtectorTokenFactory for tokenable testing
* PM-3275 - (1) Get AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail test passing (2) Move FakeDataProtectorTokenFactory to own file
* PM-3275 - AcceptOrgUserCommandTests.cs - Finish up tests for AcceptOrgUserByTokenAsync
* PM-3275 - Add pseudo section comments
* PM-3275 - Clean up unused params on AcceptOrgUserByToken_EmailMismatch_ThrowsBadRequest test
* PM-3275 - (1) Tests written for AcceptOrgUserByOrgSsoIdAsync (2) Refactor happy path assertions into helper function AssertValidAcceptedOrgUser to reduce code duplication
* PM-3275 - Finish up testing AcceptOrgUserCommandTests.cs by adding tests for AcceptOrgUserByOrgIdAsync
* PM-3275 - Tweaking test naming to ensure consistency.
* PM-3275 - Bugfix - OrgUserInviteTokenableFactory implementation required when declaring singleton service in ServiceCollectionExtensions.cs
* PM-3275 - Resolve failing OrganizationServiceTests.cs
* dotnet format
* PM-3275 - PoliciesController.cs - GetMasterPasswordPolicy bugfix - for orgs without a MP policy, policy comes back as null and we should return notFound in that case.
* PM-3275 - Add PoliciesControllerTests.cs specifically for new GetMasterPasswordPolicy(...) endpoint.
* PM-3275 - dotnet format PoliciesControllerTests.cs
* PM-3275 - PoliciesController.cs - (1) Add tech debt task number (2) Properly flag endpoint as deprecated
* PM-3275 - Add new hasManageResetPasswordPermission property to ProfileResponseModel.cs primarily for sync so that we can condition client side if TDE user obtains elevated permissions
* PM-3275 - Fix AccountsControllerTests.cs
* PM-3275 - OrgUserInviteTokenable.cs - clarify TODO
* PM-3275 - AcceptOrgUserCommand.cs - Refactor token validation to use short circuiting to only run old token validation if new token validation fails.
* PM-3275 - OrgUserInviteTokenable.cs - (1) Add new static methods to centralize validation logic to avoid repetition (2) Add new token validation method so we can avoid having to pass in a full org user (and hitting the db to do so)
* PM-3275 - Realized that the old token validation was used in the PoliciesController.cs (existing user clicks invite link in email and goes to log in) and UserService.cs (user clicks invite link in email and registers for a new acct). Added tech debt item for cleaning up backwards compatibility in future.
* dotnet format
* PM-3275 - (1) AccountsController.cs - Update PostSetPasswordAsync SetPasswordRequestModel to allow null keys for the case where we have a TDE user who obtains elevated permissions - they already have a user public and user encrypted private key saved in the db. (2) AccountsControllerTests.cs - test PostSetPasswordAsync scenarios to ensure changes will work as expected.
* PM-3275 - PR review feedback - (1) set CurrentContext to private (2) Refactor GetProfile to use variables to improve clarity and simplify debugging.
* PM-3275 - SyncController.cs - PR Review Feedback - Set current context as private instead of protected.
* PM-3275 - CurrentContextExtensions.cs - PR Feedback - move parenthesis up from own line.
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - Replace unnecessary variable
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - PR Feedback - Add expected outcome statement to test name
* PM-3275 - Set Initial Password command and tests - PR Feedback changes - (1) Rename orgIdentifier --> OrgSsoIdentifier for clarity (2) Update SetInitialMasterPasswordAsync to not allow null orgSsoId with explicit message saying this vs letting null org trigger invalid organization (3) Add test to cover this new scenario.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Move summary from implementation to interface to better respect standards and the fact that the interface is the more seen piece of code.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, rename AcceptOrgUserByTokenAsync -> AcceptOrgUserByEmailTokenAsync + replace generic name token with emailToken
* PM-3275 - OrganizationService.cs - Per PR feedback, remove dupe line
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove new lines in error messages for consistency.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Per PR feedback, adjust formatting of constructor for improved readability.
* PM-3275 - CurrentContextExtensions.cs - Refactor AnyOrgUserHasManageResetPasswordPermission per PR feedback to remove unnecessary var.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove completed TODO
* PM-3275 - PoliciesController.cs - Per PR feedback, update GetByInvitedUser param to be guid instead of string.
* PM-3275 - OrgUserInviteTokenable.cs - per PR feedback, add tech debt item info.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, use const purpose from tokenable instead of magic string.
* PM-3275 - Restore non duplicate line to fix tests
* PM-3275 - Per PR feedback, revert all sync controller changes as the ProfileResponseModel.organizations array has org objects which have permissions which have the ManageResetPassword permission. So, I have the information that I need clientside already to determine if the user has the ManageResetPassword in any org.
* PM-3275 - PoliciesControllerTests.cs - Update imports as the PoliciesController was moved under the admin console team's domain.
* PM-3275 - Resolve issues from merge conflict resolutions to get solution building.
* PM-3275 / PM-4633 - PoliciesController.cs - use orgUserId to look up user instead of orgId. Oops.
* Fix user service tests
* Resolve merge conflict
2023-11-02 11:02:25 -04:00
var orgUserInviteTokenable = _orgUserInviteTokenableFactory . CreateToken ( orgUser ) ;
var protectedToken = _orgUserInviteTokenDataFactory . Protect ( orgUserInviteTokenable ) ;
return ( orgUser , new ExpiringToken ( protectedToken , orgUserInviteTokenable . ExpirationDate ) ) ;
2022-08-29 15:53:48 -04:00
}
2020-10-13 15:00:33 -05:00
Auth/PM-3275 - Changes to support TDE User without MP being able to Set a Password + misc refactoring (#3242)
* PM-3275 - Add new GetMasterPasswordPolicy endpoint which will allow authenticated clients to get an enabled MP org policy if it exists for the purposes of enforcing those policy requirements when setting a password.
* PM-3275 - AccountsController.cs - PostSetPasswordAsync - (1) Convert UserService.setPasswordAsync into new SetInitialMasterPasswordCommand (2) Refactor SetInitialMasterPasswordCommand to only accept post SSO users who are in the invited state
(3) Add TODOs for more cleanup work and more commands
* PM-3275 - Update AccountsControllerTests.cs to add new SetInitialMasterPasswordCommand
* PM-3275 - UserService.cs - Remove non implemented ChangePasswordAsync method
* PM-3275 - The new SetInitialMasterPasswordCommand leveraged the OrganizationService.cs AcceptUserAsync method so while I was in here I converted the AcceptUserAsync methods into a new AcceptOrgUserCommand.cs and turned the private method which accepted an existing org user public for use in the SetInitialMasterPasswordCommand
* PM-3275 - Dotnet format
* PM-3275 - Test SetInitialMasterPasswordCommand
* Dotnet format
* PM-3275 - In process AcceptOrgUserCommandTests.cs
* PM-3275 - Migrate changes from AC-244 / #3199 over into new AcceptOrgUserCommand
* PM-3275 - AcceptOrgUserCommand.cs - create data protector specifically for this command
* PM-3275 - Add TODO for renaming / removing overloading of methods to improve readability / clarity
* PM-3275 - AcceptOrgUserCommand.cs - refactor AcceptOrgUserAsync by OrgId to retrieve orgUser with _organizationUserRepository.GetByOrganizationAsync which gets a single user instead of a collection
* PM-3275 - AcceptOrgUserCommand.cs - update name in TODO for evaluation later
* PM-3275 / PM-1196 - (1) Slightly refactor SsoEmail2faSessionTokenable to provide public static GetTokenLifeTime() method for testing (2) Add missed tests to SsoEmail2faSessionTokenable in preparation for building tests for new OrgUserInviteTokenable.cs
* PM-3275 / PM-1196 - Removing SsoEmail2faSessionTokenable.cs changes + tests as I've handled that separately in a new PR (#3270) for newly created task PM-3925
* PM-3275 - ExpiringTokenable.cs - add clarifying comments to help distinguish between the Valid property and the TokenIsValid method.
* PM-3275 - Create OrgUserInviteTokenable.cs and add tests in OrgUserInviteTokenableTests.cs
* PM-3275 - OrganizationService.cs - Refactor Org User Invite methods to use new OrgUserInviteTokenable instead of manual creation of a token
* PM-3275 - OrgUserInviteTokenable.cs - clarify backwards compat note
* PM-3275 - AcceptOrgUserCommand.cs - Add TODOs + minor name refactor
* PM-3275 - AcceptOrgUserCommand.cs - replace method overloading with more easily readable names.
* PM-3275 - AcceptOrgUserCommand.cs - Update ValidateOrgUserInviteToken to add new token validation while maintaining backwards compatibility for 1 release.
* dotnet format
* PM-3275 - AcceptOrgUserCommand.cs - Move private method below where it is used
* PM-3275 - ServiceCollectionExtensions.cs - Must register IDataProtectorTokenFactory<OrgUserInviteTokenable> for new tokenable
* PM-3275 - OrgUserInviteTokenable needed access to global settings to set its token lifetime to the _globalSettings.OrganizationInviteExpirationHours value. Creating a factory seemed the most straightforward way to encapsulate the desired creation logic. Unsure if in the correct location in ServiceCollectionExtensions.cs but will figure that out later.
* PM-3275 - In process work of creating AcceptOrgUserCommandTests.cs
* PM-3275 - Remove no longer relevant AcceptOrgUser tests from OrganizationServiceTests.cs
* PM-3275 - Register OrgUserInviteTokenableFactory alongside tokenizer
* PM-3275 - AcceptOrgUserCommandTests.cs - AcceptOrgUserAsync basic test suite completed.
* PM-3275 - AcceptOrgUserCommandTests.cs - tweak test names
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Remove old tests from OrganizationServiceTests as no longer needed to reference (2) Add summary for SetupCommonAcceptOrgUserMocks (3) Get AcceptOrgUserByToken_OldToken_AcceptsUserAndVerifiesEmail passing
* PM-3275 - Create interface for OrgUserInviteTokenableFactory b/c that's the right thing to do + enables test substitution
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Start work on AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail (2) Create and use SetupCommonAcceptOrgUserByTokenMocks() (3) Create generic FakeDataProtectorTokenFactory for tokenable testing
* PM-3275 - (1) Get AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail test passing (2) Move FakeDataProtectorTokenFactory to own file
* PM-3275 - AcceptOrgUserCommandTests.cs - Finish up tests for AcceptOrgUserByTokenAsync
* PM-3275 - Add pseudo section comments
* PM-3275 - Clean up unused params on AcceptOrgUserByToken_EmailMismatch_ThrowsBadRequest test
* PM-3275 - (1) Tests written for AcceptOrgUserByOrgSsoIdAsync (2) Refactor happy path assertions into helper function AssertValidAcceptedOrgUser to reduce code duplication
* PM-3275 - Finish up testing AcceptOrgUserCommandTests.cs by adding tests for AcceptOrgUserByOrgIdAsync
* PM-3275 - Tweaking test naming to ensure consistency.
* PM-3275 - Bugfix - OrgUserInviteTokenableFactory implementation required when declaring singleton service in ServiceCollectionExtensions.cs
* PM-3275 - Resolve failing OrganizationServiceTests.cs
* dotnet format
* PM-3275 - PoliciesController.cs - GetMasterPasswordPolicy bugfix - for orgs without a MP policy, policy comes back as null and we should return notFound in that case.
* PM-3275 - Add PoliciesControllerTests.cs specifically for new GetMasterPasswordPolicy(...) endpoint.
* PM-3275 - dotnet format PoliciesControllerTests.cs
* PM-3275 - PoliciesController.cs - (1) Add tech debt task number (2) Properly flag endpoint as deprecated
* PM-3275 - Add new hasManageResetPasswordPermission property to ProfileResponseModel.cs primarily for sync so that we can condition client side if TDE user obtains elevated permissions
* PM-3275 - Fix AccountsControllerTests.cs
* PM-3275 - OrgUserInviteTokenable.cs - clarify TODO
* PM-3275 - AcceptOrgUserCommand.cs - Refactor token validation to use short circuiting to only run old token validation if new token validation fails.
* PM-3275 - OrgUserInviteTokenable.cs - (1) Add new static methods to centralize validation logic to avoid repetition (2) Add new token validation method so we can avoid having to pass in a full org user (and hitting the db to do so)
* PM-3275 - Realized that the old token validation was used in the PoliciesController.cs (existing user clicks invite link in email and goes to log in) and UserService.cs (user clicks invite link in email and registers for a new acct). Added tech debt item for cleaning up backwards compatibility in future.
* dotnet format
* PM-3275 - (1) AccountsController.cs - Update PostSetPasswordAsync SetPasswordRequestModel to allow null keys for the case where we have a TDE user who obtains elevated permissions - they already have a user public and user encrypted private key saved in the db. (2) AccountsControllerTests.cs - test PostSetPasswordAsync scenarios to ensure changes will work as expected.
* PM-3275 - PR review feedback - (1) set CurrentContext to private (2) Refactor GetProfile to use variables to improve clarity and simplify debugging.
* PM-3275 - SyncController.cs - PR Review Feedback - Set current context as private instead of protected.
* PM-3275 - CurrentContextExtensions.cs - PR Feedback - move parenthesis up from own line.
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - Replace unnecessary variable
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - PR Feedback - Add expected outcome statement to test name
* PM-3275 - Set Initial Password command and tests - PR Feedback changes - (1) Rename orgIdentifier --> OrgSsoIdentifier for clarity (2) Update SetInitialMasterPasswordAsync to not allow null orgSsoId with explicit message saying this vs letting null org trigger invalid organization (3) Add test to cover this new scenario.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Move summary from implementation to interface to better respect standards and the fact that the interface is the more seen piece of code.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, rename AcceptOrgUserByTokenAsync -> AcceptOrgUserByEmailTokenAsync + replace generic name token with emailToken
* PM-3275 - OrganizationService.cs - Per PR feedback, remove dupe line
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove new lines in error messages for consistency.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Per PR feedback, adjust formatting of constructor for improved readability.
* PM-3275 - CurrentContextExtensions.cs - Refactor AnyOrgUserHasManageResetPasswordPermission per PR feedback to remove unnecessary var.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove completed TODO
* PM-3275 - PoliciesController.cs - Per PR feedback, update GetByInvitedUser param to be guid instead of string.
* PM-3275 - OrgUserInviteTokenable.cs - per PR feedback, add tech debt item info.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, use const purpose from tokenable instead of magic string.
* PM-3275 - Restore non duplicate line to fix tests
* PM-3275 - Per PR feedback, revert all sync controller changes as the ProfileResponseModel.organizations array has org objects which have permissions which have the ManageResetPassword permission. So, I have the information that I need clientside already to determine if the user has the ManageResetPassword in any org.
* PM-3275 - PoliciesControllerTests.cs - Update imports as the PoliciesController was moved under the admin console team's domain.
* PM-3275 - Resolve issues from merge conflict resolutions to get solution building.
* PM-3275 / PM-4633 - PoliciesController.cs - use orgUserId to look up user instead of orgId. Oops.
* Fix user service tests
* Resolve merge conflict
2023-11-02 11:02:25 -04:00
var orgUsersWithExpTokens = orgUsers . Select ( MakeOrgUserExpiringTokenPair ) ;
2023-09-07 14:36:54 +01:00
2023-12-18 11:16:17 -05:00
return new OrganizationInvitesInfo (
organization ,
orgSsoEnabled ,
orgSsoLoginRequiredPolicyEnabled ,
Auth/PM-3275 - Changes to support TDE User without MP being able to Set a Password + misc refactoring (#3242)
* PM-3275 - Add new GetMasterPasswordPolicy endpoint which will allow authenticated clients to get an enabled MP org policy if it exists for the purposes of enforcing those policy requirements when setting a password.
* PM-3275 - AccountsController.cs - PostSetPasswordAsync - (1) Convert UserService.setPasswordAsync into new SetInitialMasterPasswordCommand (2) Refactor SetInitialMasterPasswordCommand to only accept post SSO users who are in the invited state
(3) Add TODOs for more cleanup work and more commands
* PM-3275 - Update AccountsControllerTests.cs to add new SetInitialMasterPasswordCommand
* PM-3275 - UserService.cs - Remove non implemented ChangePasswordAsync method
* PM-3275 - The new SetInitialMasterPasswordCommand leveraged the OrganizationService.cs AcceptUserAsync method so while I was in here I converted the AcceptUserAsync methods into a new AcceptOrgUserCommand.cs and turned the private method which accepted an existing org user public for use in the SetInitialMasterPasswordCommand
* PM-3275 - Dotnet format
* PM-3275 - Test SetInitialMasterPasswordCommand
* Dotnet format
* PM-3275 - In process AcceptOrgUserCommandTests.cs
* PM-3275 - Migrate changes from AC-244 / #3199 over into new AcceptOrgUserCommand
* PM-3275 - AcceptOrgUserCommand.cs - create data protector specifically for this command
* PM-3275 - Add TODO for renaming / removing overloading of methods to improve readability / clarity
* PM-3275 - AcceptOrgUserCommand.cs - refactor AcceptOrgUserAsync by OrgId to retrieve orgUser with _organizationUserRepository.GetByOrganizationAsync which gets a single user instead of a collection
* PM-3275 - AcceptOrgUserCommand.cs - update name in TODO for evaluation later
* PM-3275 / PM-1196 - (1) Slightly refactor SsoEmail2faSessionTokenable to provide public static GetTokenLifeTime() method for testing (2) Add missed tests to SsoEmail2faSessionTokenable in preparation for building tests for new OrgUserInviteTokenable.cs
* PM-3275 / PM-1196 - Removing SsoEmail2faSessionTokenable.cs changes + tests as I've handled that separately in a new PR (#3270) for newly created task PM-3925
* PM-3275 - ExpiringTokenable.cs - add clarifying comments to help distinguish between the Valid property and the TokenIsValid method.
* PM-3275 - Create OrgUserInviteTokenable.cs and add tests in OrgUserInviteTokenableTests.cs
* PM-3275 - OrganizationService.cs - Refactor Org User Invite methods to use new OrgUserInviteTokenable instead of manual creation of a token
* PM-3275 - OrgUserInviteTokenable.cs - clarify backwards compat note
* PM-3275 - AcceptOrgUserCommand.cs - Add TODOs + minor name refactor
* PM-3275 - AcceptOrgUserCommand.cs - replace method overloading with more easily readable names.
* PM-3275 - AcceptOrgUserCommand.cs - Update ValidateOrgUserInviteToken to add new token validation while maintaining backwards compatibility for 1 release.
* dotnet format
* PM-3275 - AcceptOrgUserCommand.cs - Move private method below where it is used
* PM-3275 - ServiceCollectionExtensions.cs - Must register IDataProtectorTokenFactory<OrgUserInviteTokenable> for new tokenable
* PM-3275 - OrgUserInviteTokenable needed access to global settings to set its token lifetime to the _globalSettings.OrganizationInviteExpirationHours value. Creating a factory seemed the most straightforward way to encapsulate the desired creation logic. Unsure if in the correct location in ServiceCollectionExtensions.cs but will figure that out later.
* PM-3275 - In process work of creating AcceptOrgUserCommandTests.cs
* PM-3275 - Remove no longer relevant AcceptOrgUser tests from OrganizationServiceTests.cs
* PM-3275 - Register OrgUserInviteTokenableFactory alongside tokenizer
* PM-3275 - AcceptOrgUserCommandTests.cs - AcceptOrgUserAsync basic test suite completed.
* PM-3275 - AcceptOrgUserCommandTests.cs - tweak test names
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Remove old tests from OrganizationServiceTests as no longer needed to reference (2) Add summary for SetupCommonAcceptOrgUserMocks (3) Get AcceptOrgUserByToken_OldToken_AcceptsUserAndVerifiesEmail passing
* PM-3275 - Create interface for OrgUserInviteTokenableFactory b/c that's the right thing to do + enables test substitution
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Start work on AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail (2) Create and use SetupCommonAcceptOrgUserByTokenMocks() (3) Create generic FakeDataProtectorTokenFactory for tokenable testing
* PM-3275 - (1) Get AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail test passing (2) Move FakeDataProtectorTokenFactory to own file
* PM-3275 - AcceptOrgUserCommandTests.cs - Finish up tests for AcceptOrgUserByTokenAsync
* PM-3275 - Add pseudo section comments
* PM-3275 - Clean up unused params on AcceptOrgUserByToken_EmailMismatch_ThrowsBadRequest test
* PM-3275 - (1) Tests written for AcceptOrgUserByOrgSsoIdAsync (2) Refactor happy path assertions into helper function AssertValidAcceptedOrgUser to reduce code duplication
* PM-3275 - Finish up testing AcceptOrgUserCommandTests.cs by adding tests for AcceptOrgUserByOrgIdAsync
* PM-3275 - Tweaking test naming to ensure consistency.
* PM-3275 - Bugfix - OrgUserInviteTokenableFactory implementation required when declaring singleton service in ServiceCollectionExtensions.cs
* PM-3275 - Resolve failing OrganizationServiceTests.cs
* dotnet format
* PM-3275 - PoliciesController.cs - GetMasterPasswordPolicy bugfix - for orgs without a MP policy, policy comes back as null and we should return notFound in that case.
* PM-3275 - Add PoliciesControllerTests.cs specifically for new GetMasterPasswordPolicy(...) endpoint.
* PM-3275 - dotnet format PoliciesControllerTests.cs
* PM-3275 - PoliciesController.cs - (1) Add tech debt task number (2) Properly flag endpoint as deprecated
* PM-3275 - Add new hasManageResetPasswordPermission property to ProfileResponseModel.cs primarily for sync so that we can condition client side if TDE user obtains elevated permissions
* PM-3275 - Fix AccountsControllerTests.cs
* PM-3275 - OrgUserInviteTokenable.cs - clarify TODO
* PM-3275 - AcceptOrgUserCommand.cs - Refactor token validation to use short circuiting to only run old token validation if new token validation fails.
* PM-3275 - OrgUserInviteTokenable.cs - (1) Add new static methods to centralize validation logic to avoid repetition (2) Add new token validation method so we can avoid having to pass in a full org user (and hitting the db to do so)
* PM-3275 - Realized that the old token validation was used in the PoliciesController.cs (existing user clicks invite link in email and goes to log in) and UserService.cs (user clicks invite link in email and registers for a new acct). Added tech debt item for cleaning up backwards compatibility in future.
* dotnet format
* PM-3275 - (1) AccountsController.cs - Update PostSetPasswordAsync SetPasswordRequestModel to allow null keys for the case where we have a TDE user who obtains elevated permissions - they already have a user public and user encrypted private key saved in the db. (2) AccountsControllerTests.cs - test PostSetPasswordAsync scenarios to ensure changes will work as expected.
* PM-3275 - PR review feedback - (1) set CurrentContext to private (2) Refactor GetProfile to use variables to improve clarity and simplify debugging.
* PM-3275 - SyncController.cs - PR Review Feedback - Set current context as private instead of protected.
* PM-3275 - CurrentContextExtensions.cs - PR Feedback - move parenthesis up from own line.
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - Replace unnecessary variable
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - PR Feedback - Add expected outcome statement to test name
* PM-3275 - Set Initial Password command and tests - PR Feedback changes - (1) Rename orgIdentifier --> OrgSsoIdentifier for clarity (2) Update SetInitialMasterPasswordAsync to not allow null orgSsoId with explicit message saying this vs letting null org trigger invalid organization (3) Add test to cover this new scenario.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Move summary from implementation to interface to better respect standards and the fact that the interface is the more seen piece of code.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, rename AcceptOrgUserByTokenAsync -> AcceptOrgUserByEmailTokenAsync + replace generic name token with emailToken
* PM-3275 - OrganizationService.cs - Per PR feedback, remove dupe line
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove new lines in error messages for consistency.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Per PR feedback, adjust formatting of constructor for improved readability.
* PM-3275 - CurrentContextExtensions.cs - Refactor AnyOrgUserHasManageResetPasswordPermission per PR feedback to remove unnecessary var.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove completed TODO
* PM-3275 - PoliciesController.cs - Per PR feedback, update GetByInvitedUser param to be guid instead of string.
* PM-3275 - OrgUserInviteTokenable.cs - per PR feedback, add tech debt item info.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, use const purpose from tokenable instead of magic string.
* PM-3275 - Restore non duplicate line to fix tests
* PM-3275 - Per PR feedback, revert all sync controller changes as the ProfileResponseModel.organizations array has org objects which have permissions which have the ManageResetPassword permission. So, I have the information that I need clientside already to determine if the user has the ManageResetPassword in any org.
* PM-3275 - PoliciesControllerTests.cs - Update imports as the PoliciesController was moved under the admin console team's domain.
* PM-3275 - Resolve issues from merge conflict resolutions to get solution building.
* PM-3275 / PM-4633 - PoliciesController.cs - use orgUserId to look up user instead of orgId. Oops.
* Fix user service tests
* Resolve merge conflict
2023-11-02 11:02:25 -04:00
orgUsersWithExpTokens ,
2023-12-18 11:16:17 -05:00
orgUserHasExistingUserDict ,
Auth/PM-3275 - Changes to support TDE User without MP being able to Set a Password + misc refactoring (#3242)
* PM-3275 - Add new GetMasterPasswordPolicy endpoint which will allow authenticated clients to get an enabled MP org policy if it exists for the purposes of enforcing those policy requirements when setting a password.
* PM-3275 - AccountsController.cs - PostSetPasswordAsync - (1) Convert UserService.setPasswordAsync into new SetInitialMasterPasswordCommand (2) Refactor SetInitialMasterPasswordCommand to only accept post SSO users who are in the invited state
(3) Add TODOs for more cleanup work and more commands
* PM-3275 - Update AccountsControllerTests.cs to add new SetInitialMasterPasswordCommand
* PM-3275 - UserService.cs - Remove non implemented ChangePasswordAsync method
* PM-3275 - The new SetInitialMasterPasswordCommand leveraged the OrganizationService.cs AcceptUserAsync method so while I was in here I converted the AcceptUserAsync methods into a new AcceptOrgUserCommand.cs and turned the private method which accepted an existing org user public for use in the SetInitialMasterPasswordCommand
* PM-3275 - Dotnet format
* PM-3275 - Test SetInitialMasterPasswordCommand
* Dotnet format
* PM-3275 - In process AcceptOrgUserCommandTests.cs
* PM-3275 - Migrate changes from AC-244 / #3199 over into new AcceptOrgUserCommand
* PM-3275 - AcceptOrgUserCommand.cs - create data protector specifically for this command
* PM-3275 - Add TODO for renaming / removing overloading of methods to improve readability / clarity
* PM-3275 - AcceptOrgUserCommand.cs - refactor AcceptOrgUserAsync by OrgId to retrieve orgUser with _organizationUserRepository.GetByOrganizationAsync which gets a single user instead of a collection
* PM-3275 - AcceptOrgUserCommand.cs - update name in TODO for evaluation later
* PM-3275 / PM-1196 - (1) Slightly refactor SsoEmail2faSessionTokenable to provide public static GetTokenLifeTime() method for testing (2) Add missed tests to SsoEmail2faSessionTokenable in preparation for building tests for new OrgUserInviteTokenable.cs
* PM-3275 / PM-1196 - Removing SsoEmail2faSessionTokenable.cs changes + tests as I've handled that separately in a new PR (#3270) for newly created task PM-3925
* PM-3275 - ExpiringTokenable.cs - add clarifying comments to help distinguish between the Valid property and the TokenIsValid method.
* PM-3275 - Create OrgUserInviteTokenable.cs and add tests in OrgUserInviteTokenableTests.cs
* PM-3275 - OrganizationService.cs - Refactor Org User Invite methods to use new OrgUserInviteTokenable instead of manual creation of a token
* PM-3275 - OrgUserInviteTokenable.cs - clarify backwards compat note
* PM-3275 - AcceptOrgUserCommand.cs - Add TODOs + minor name refactor
* PM-3275 - AcceptOrgUserCommand.cs - replace method overloading with more easily readable names.
* PM-3275 - AcceptOrgUserCommand.cs - Update ValidateOrgUserInviteToken to add new token validation while maintaining backwards compatibility for 1 release.
* dotnet format
* PM-3275 - AcceptOrgUserCommand.cs - Move private method below where it is used
* PM-3275 - ServiceCollectionExtensions.cs - Must register IDataProtectorTokenFactory<OrgUserInviteTokenable> for new tokenable
* PM-3275 - OrgUserInviteTokenable needed access to global settings to set its token lifetime to the _globalSettings.OrganizationInviteExpirationHours value. Creating a factory seemed the most straightforward way to encapsulate the desired creation logic. Unsure if in the correct location in ServiceCollectionExtensions.cs but will figure that out later.
* PM-3275 - In process work of creating AcceptOrgUserCommandTests.cs
* PM-3275 - Remove no longer relevant AcceptOrgUser tests from OrganizationServiceTests.cs
* PM-3275 - Register OrgUserInviteTokenableFactory alongside tokenizer
* PM-3275 - AcceptOrgUserCommandTests.cs - AcceptOrgUserAsync basic test suite completed.
* PM-3275 - AcceptOrgUserCommandTests.cs - tweak test names
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Remove old tests from OrganizationServiceTests as no longer needed to reference (2) Add summary for SetupCommonAcceptOrgUserMocks (3) Get AcceptOrgUserByToken_OldToken_AcceptsUserAndVerifiesEmail passing
* PM-3275 - Create interface for OrgUserInviteTokenableFactory b/c that's the right thing to do + enables test substitution
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Start work on AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail (2) Create and use SetupCommonAcceptOrgUserByTokenMocks() (3) Create generic FakeDataProtectorTokenFactory for tokenable testing
* PM-3275 - (1) Get AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail test passing (2) Move FakeDataProtectorTokenFactory to own file
* PM-3275 - AcceptOrgUserCommandTests.cs - Finish up tests for AcceptOrgUserByTokenAsync
* PM-3275 - Add pseudo section comments
* PM-3275 - Clean up unused params on AcceptOrgUserByToken_EmailMismatch_ThrowsBadRequest test
* PM-3275 - (1) Tests written for AcceptOrgUserByOrgSsoIdAsync (2) Refactor happy path assertions into helper function AssertValidAcceptedOrgUser to reduce code duplication
* PM-3275 - Finish up testing AcceptOrgUserCommandTests.cs by adding tests for AcceptOrgUserByOrgIdAsync
* PM-3275 - Tweaking test naming to ensure consistency.
* PM-3275 - Bugfix - OrgUserInviteTokenableFactory implementation required when declaring singleton service in ServiceCollectionExtensions.cs
* PM-3275 - Resolve failing OrganizationServiceTests.cs
* dotnet format
* PM-3275 - PoliciesController.cs - GetMasterPasswordPolicy bugfix - for orgs without a MP policy, policy comes back as null and we should return notFound in that case.
* PM-3275 - Add PoliciesControllerTests.cs specifically for new GetMasterPasswordPolicy(...) endpoint.
* PM-3275 - dotnet format PoliciesControllerTests.cs
* PM-3275 - PoliciesController.cs - (1) Add tech debt task number (2) Properly flag endpoint as deprecated
* PM-3275 - Add new hasManageResetPasswordPermission property to ProfileResponseModel.cs primarily for sync so that we can condition client side if TDE user obtains elevated permissions
* PM-3275 - Fix AccountsControllerTests.cs
* PM-3275 - OrgUserInviteTokenable.cs - clarify TODO
* PM-3275 - AcceptOrgUserCommand.cs - Refactor token validation to use short circuiting to only run old token validation if new token validation fails.
* PM-3275 - OrgUserInviteTokenable.cs - (1) Add new static methods to centralize validation logic to avoid repetition (2) Add new token validation method so we can avoid having to pass in a full org user (and hitting the db to do so)
* PM-3275 - Realized that the old token validation was used in the PoliciesController.cs (existing user clicks invite link in email and goes to log in) and UserService.cs (user clicks invite link in email and registers for a new acct). Added tech debt item for cleaning up backwards compatibility in future.
* dotnet format
* PM-3275 - (1) AccountsController.cs - Update PostSetPasswordAsync SetPasswordRequestModel to allow null keys for the case where we have a TDE user who obtains elevated permissions - they already have a user public and user encrypted private key saved in the db. (2) AccountsControllerTests.cs - test PostSetPasswordAsync scenarios to ensure changes will work as expected.
* PM-3275 - PR review feedback - (1) set CurrentContext to private (2) Refactor GetProfile to use variables to improve clarity and simplify debugging.
* PM-3275 - SyncController.cs - PR Review Feedback - Set current context as private instead of protected.
* PM-3275 - CurrentContextExtensions.cs - PR Feedback - move parenthesis up from own line.
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - Replace unnecessary variable
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - PR Feedback - Add expected outcome statement to test name
* PM-3275 - Set Initial Password command and tests - PR Feedback changes - (1) Rename orgIdentifier --> OrgSsoIdentifier for clarity (2) Update SetInitialMasterPasswordAsync to not allow null orgSsoId with explicit message saying this vs letting null org trigger invalid organization (3) Add test to cover this new scenario.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Move summary from implementation to interface to better respect standards and the fact that the interface is the more seen piece of code.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, rename AcceptOrgUserByTokenAsync -> AcceptOrgUserByEmailTokenAsync + replace generic name token with emailToken
* PM-3275 - OrganizationService.cs - Per PR feedback, remove dupe line
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove new lines in error messages for consistency.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Per PR feedback, adjust formatting of constructor for improved readability.
* PM-3275 - CurrentContextExtensions.cs - Refactor AnyOrgUserHasManageResetPasswordPermission per PR feedback to remove unnecessary var.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove completed TODO
* PM-3275 - PoliciesController.cs - Per PR feedback, update GetByInvitedUser param to be guid instead of string.
* PM-3275 - OrgUserInviteTokenable.cs - per PR feedback, add tech debt item info.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, use const purpose from tokenable instead of magic string.
* PM-3275 - Restore non duplicate line to fix tests
* PM-3275 - Per PR feedback, revert all sync controller changes as the ProfileResponseModel.organizations array has org objects which have permissions which have the ManageResetPassword permission. So, I have the information that I need clientside already to determine if the user has the ManageResetPassword in any org.
* PM-3275 - PoliciesControllerTests.cs - Update imports as the PoliciesController was moved under the admin console team's domain.
* PM-3275 - Resolve issues from merge conflict resolutions to get solution building.
* PM-3275 / PM-4633 - PoliciesController.cs - use orgUserId to look up user instead of orgId. Oops.
* Fix user service tests
* Resolve merge conflict
2023-11-02 11:02:25 -04:00
initOrganization
) ;
2021-09-23 06:36:08 -04:00
}
2021-05-25 19:23:47 +02:00
2017-03-23 00:17:34 -04:00
public async Task < OrganizationUser > ConfirmUserAsync ( Guid organizationId , Guid organizationUserId , string key ,
Guid confirmingUserId , IUserService userService )
{
var result = await ConfirmUsersAsync ( organizationId , new Dictionary < Guid , string > ( ) { { organizationUserId , key } } ,
confirmingUserId , userService ) ;
2017-03-04 21:28:41 -05:00
2021-05-25 19:23:47 +02:00
if ( ! result . Any ( ) )
2017-09-08 17:14:15 -04:00
{
2021-05-25 19:23:47 +02:00
throw new BadRequestException ( "User not valid." ) ;
}
2021-09-23 06:36:08 -04:00
2021-05-25 19:23:47 +02:00
var ( orgUser , error ) = result [ 0 ] ;
if ( error ! = "" )
{
throw new BadRequestException ( error ) ;
2022-08-29 16:06:55 -04:00
}
2021-05-25 19:23:47 +02:00
return orgUser ;
2022-08-29 16:06:55 -04:00
}
2022-08-29 14:53:16 -04:00
2021-05-25 19:23:47 +02:00
public async Task < List < Tuple < OrganizationUser , string > > > ConfirmUsersAsync ( Guid organizationId , Dictionary < Guid , string > keys ,
Guid confirmingUserId , IUserService userService )
2022-08-29 16:06:55 -04:00
{
2021-05-25 19:23:47 +02:00
var organizationUsers = await _organizationUserRepository . GetManyAsync ( keys . Keys ) ;
var validOrganizationUsers = organizationUsers
. Where ( u = > u . Status = = OrganizationUserStatusType . Accepted & & u . OrganizationId = = organizationId & & u . UserId ! = null )
. ToList ( ) ;
2022-08-29 16:06:55 -04:00
2021-05-25 19:23:47 +02:00
if ( ! validOrganizationUsers . Any ( ) )
{
return new List < Tuple < OrganizationUser , string > > ( ) ;
}
var validOrganizationUserIds = validOrganizationUsers . Select ( u = > u . UserId . Value ) . ToList ( ) ;
2021-09-23 06:36:08 -04:00
2021-05-25 19:23:47 +02:00
var organization = await GetOrgById ( organizationId ) ;
var policies = await _policyRepository . GetManyByOrganizationIdAsync ( organizationId ) ;
var usersOrgs = await _organizationUserRepository . GetManyByManyUsersAsync ( validOrganizationUserIds ) ;
var users = await _userRepository . GetManyAsync ( validOrganizationUserIds ) ;
var keyedFilteredUsers = validOrganizationUsers . ToDictionary ( u = > u . UserId . Value , u = > u ) ;
var keyedOrganizationUsers = usersOrgs . GroupBy ( u = > u . UserId . Value )
. ToDictionary ( u = > u . Key , u = > u . ToList ( ) ) ;
var succeededUsers = new List < OrganizationUser > ( ) ;
var result = new List < Tuple < OrganizationUser , string > > ( ) ;
foreach ( var user in users )
2022-08-29 16:06:55 -04:00
{
2021-08-10 12:16:10 -04:00
if ( ! keyedFilteredUsers . ContainsKey ( user . Id ) )
2022-08-29 14:53:16 -04:00
{
2021-08-10 12:16:10 -04:00
continue ;
2022-08-29 15:53:48 -04:00
}
2021-08-10 12:16:10 -04:00
var orgUser = keyedFilteredUsers [ user . Id ] ;
var orgUsers = keyedOrganizationUsers . GetValueOrDefault ( user . Id , new List < OrganizationUser > ( ) ) ;
try
2022-08-29 16:06:55 -04:00
{
2021-08-10 12:16:10 -04:00
if ( organization . PlanType = = PlanType . Free & & ( orgUser . Type = = OrganizationUserType . Admin
| | orgUser . Type = = OrganizationUserType . Owner ) )
2022-08-29 15:53:48 -04:00
{
2021-08-10 12:16:10 -04:00
// Since free organizations only supports a few users there is not much point in avoiding N+1 queries for this.
var adminCount = await _organizationUserRepository . GetCountByFreeOrganizationAdminUserAsync ( user . Id ) ;
if ( adminCount > 0 )
2021-05-25 19:23:47 +02:00
{
throw new BadRequestException ( "User can only be an admin of one free organization." ) ;
}
2022-08-29 16:06:55 -04:00
}
2021-05-25 19:23:47 +02:00
await CheckPolicies ( policies , organizationId , user , orgUsers , userService ) ;
orgUser . Status = OrganizationUserStatusType . Confirmed ;
orgUser . Key = keys [ orgUser . Id ] ;
orgUser . Email = null ;
2021-09-23 06:36:08 -04:00
2021-05-25 19:23:47 +02:00
await _eventService . LogOrganizationUserEventAsync ( orgUser , EventType . OrganizationUser_Confirmed ) ;
await _mailService . SendOrganizationConfirmedEmailAsync ( organization . Name , user . Email ) ;
await DeleteAndPushUserRegistrationAsync ( organizationId , user . Id ) ;
succeededUsers . Add ( orgUser ) ;
result . Add ( Tuple . Create ( orgUser , "" ) ) ;
2022-08-29 14:53:16 -04:00
}
2021-05-25 19:23:47 +02:00
catch ( BadRequestException e )
2022-08-29 16:06:55 -04:00
{
2021-05-25 19:23:47 +02:00
result . Add ( Tuple . Create ( orgUser , e . Message ) ) ;
2022-08-29 16:06:55 -04:00
}
}
2021-05-25 19:23:47 +02:00
await _organizationUserRepository . ReplaceManyAsync ( succeededUsers ) ;
2017-09-08 17:14:15 -04:00
2021-05-25 19:23:47 +02:00
return result ;
2022-08-29 16:06:55 -04:00
}
2021-05-25 19:23:47 +02:00
2023-11-20 09:05:35 -05:00
internal async Task < ( bool canScale , string failureReason ) > CanScaleAsync (
Organization organization ,
2021-10-25 10:19:37 -05:00
int seatsToAdd )
2022-08-29 16:06:55 -04:00
{
2021-09-23 06:36:08 -04:00
var failureReason = "" ;
if ( _globalSettings . SelfHosted )
2022-08-29 16:06:55 -04:00
{
2021-09-23 06:36:08 -04:00
failureReason = "Cannot autoscale on self-hosted instance." ;
2021-05-25 19:23:47 +02:00
return ( false , failureReason ) ;
}
2021-10-25 10:19:37 -05:00
if ( seatsToAdd < 1 )
2021-09-23 06:36:08 -04:00
{
return ( true , failureReason ) ;
}
2023-11-20 09:05:35 -05:00
var provider = await _providerRepository . GetByOrganizationIdAsync ( organization . Id ) ;
if ( provider is { Enabled : true , Type : ProviderType . Reseller } )
{
return ( false , "Seat limit has been reached. Contact your provider to purchase additional seats." ) ;
}
2021-09-23 06:36:08 -04:00
if ( organization . Seats . HasValue & &
organization . MaxAutoscaleSeats . HasValue & &
organization . MaxAutoscaleSeats . Value < organization . Seats . Value + seatsToAdd )
{
2022-09-23 14:30:39 +10:00
return ( false , $"Seat limit has been reached." ) ;
2021-09-23 06:36:08 -04:00
}
return ( true , failureReason ) ;
}
public async Task AutoAddSeatsAsync ( Organization organization , int seatsToAdd , DateTime ? prorationDate = null )
2022-08-29 16:06:55 -04:00
{
2021-09-23 06:36:08 -04:00
if ( seatsToAdd < 1 | | ! organization . Seats . HasValue )
2022-08-29 16:06:55 -04:00
{
2021-09-23 06:36:08 -04:00
return ;
}
2023-11-20 09:05:35 -05:00
var ( canScale , failureMessage ) = await CanScaleAsync ( organization , seatsToAdd ) ;
2021-10-25 10:19:37 -05:00
if ( ! canScale )
2021-09-23 06:36:08 -04:00
{
throw new BadRequestException ( failureMessage ) ;
2022-08-29 15:53:48 -04:00
}
2021-09-23 06:36:08 -04:00
2023-01-26 11:51:26 -05:00
var providerOrg = await this . _providerOrganizationRepository . GetByOrganizationId ( organization . Id ) ;
IEnumerable < string > ownerEmails ;
if ( providerOrg ! = null )
{
ownerEmails = ( await _providerUserRepository . GetManyDetailsByProviderAsync ( providerOrg . ProviderId , ProviderUserStatusType . Confirmed ) )
. Select ( u = > u . Email ) . Distinct ( ) ;
}
else
{
ownerEmails = ( await _organizationUserRepository . GetManyByMinimumRoleAsync ( organization . Id ,
OrganizationUserType . Owner ) ) . Select ( u = > u . Email ) . Distinct ( ) ;
}
2021-09-23 06:36:08 -04:00
var initialSeatCount = organization . Seats . Value ;
2021-10-07 08:05:02 -05:00
await AdjustSeatsAsync ( organization , seatsToAdd , prorationDate , ownerEmails ) ;
2021-09-23 06:36:08 -04:00
2021-05-25 19:23:47 +02:00
if ( ! organization . OwnersNotifiedOfAutoscaling . HasValue )
2022-08-29 15:53:48 -04:00
{
2021-05-25 19:23:47 +02:00
await _mailService . SendOrganizationAutoscaledEmailAsync ( organization , initialSeatCount ,
2021-09-23 06:36:08 -04:00
ownerEmails ) ;
2021-05-25 19:23:47 +02:00
organization . OwnersNotifiedOfAutoscaling = DateTime . UtcNow ;
await _organizationRepository . UpsertAsync ( organization ) ;
2020-03-09 15:13:40 -04:00
}
2022-08-29 16:06:55 -04:00
}
2020-03-09 15:13:40 -04:00
2020-10-27 10:28:41 -04:00
private async Task CheckPolicies ( ICollection < Policy > policies , Guid organizationId , User user ,
ICollection < OrganizationUser > userOrgs , IUserService userService )
2022-08-29 16:06:55 -04:00
{
2020-10-20 02:48:10 -04:00
var usingTwoFactorPolicy = policies . Any ( p = > p . Type = = PolicyType . TwoFactorAuthentication & & p . Enabled ) ;
if ( usingTwoFactorPolicy & & ! await userService . TwoFactorIsEnabledAsync ( user ) )
2022-08-29 14:53:16 -04:00
{
2020-10-20 02:48:10 -04:00
throw new BadRequestException ( "User does not have two-step login enabled." ) ;
}
2017-03-09 23:58:43 -05:00
2019-03-05 23:24:14 -05:00
var usingSingleOrgPolicy = policies . Any ( p = > p . Type = = PolicyType . SingleOrg & & p . Enabled ) ;
2022-08-03 07:09:22 +10:00
if ( usingSingleOrgPolicy )
2022-08-29 16:06:55 -04:00
{
2019-03-05 23:24:14 -05:00
if ( userOrgs . Any ( ou = > ou . OrganizationId ! = organizationId & & ou . Status ! = OrganizationUserStatusType . Invited ) )
2022-08-29 15:53:48 -04:00
{
2017-03-09 23:58:43 -05:00
throw new BadRequestException ( "User is a member of another organization." ) ;
2022-08-29 15:53:48 -04:00
}
2017-03-09 23:58:43 -05:00
}
2022-08-29 16:06:55 -04:00
}
2017-03-09 23:58:43 -05:00
2021-01-12 11:02:39 -05:00
public async Task SaveUserAsync ( OrganizationUser user , Guid ? savingUserId ,
2024-02-08 07:44:36 -06:00
ICollection < CollectionAccessSelection > collections ,
2023-01-19 17:00:54 +01:00
IEnumerable < Guid > groups )
2022-08-29 16:06:55 -04:00
{
2021-01-12 11:02:39 -05:00
if ( user . Id . Equals ( default ( Guid ) ) )
2021-05-17 09:43:02 -05:00
{
2021-01-12 11:02:39 -05:00
throw new BadRequestException ( "Invite the user first." ) ;
}
2021-07-08 17:05:32 +02:00
var originalUser = await _organizationUserRepository . GetByIdAsync ( user . Id ) ;
if ( user . Equals ( originalUser ) )
2022-08-29 15:53:48 -04:00
{
2021-07-08 17:05:32 +02:00
throw new BadRequestException ( "Please make changes before saving." ) ;
2017-09-27 22:37:13 -04:00
}
2020-03-27 14:36:37 -04:00
if ( savingUserId . HasValue )
2021-09-23 06:36:08 -04:00
{
2023-05-17 14:17:37 +01:00
await ValidateOrganizationUserUpdatePermissions ( user . OrganizationId , user . Type , originalUser . Type , user . GetPermissions ( ) ) ;
2017-03-29 21:26:19 -04:00
}
2022-12-06 09:50:08 +00:00
await ValidateOrganizationCustomPermissionsEnabledAsync ( user . OrganizationId , user . Type ) ;
2017-05-11 14:52:35 -04:00
if ( user . Type ! = OrganizationUserType . Owner & &
2017-12-01 16:00:30 -05:00
! await HasConfirmedOwnersExceptAsync ( user . OrganizationId , new [ ] { user . Id } ) )
2022-08-29 15:53:48 -04:00
{
2017-12-01 16:00:30 -05:00
throw new BadRequestException ( "Organization must have at least one confirmed owner." ) ;
2022-08-29 14:53:16 -04:00
}
2017-03-09 23:58:43 -05:00
2024-01-22 08:56:20 +10:00
// If the organization is using Flexible Collections, prevent use of any deprecated permissions
var organizationAbility = await _applicationCacheService . GetOrganizationAbilityAsync ( user . OrganizationId ) ;
if ( organizationAbility ? . FlexibleCollections = = true & & user . Type = = OrganizationUserType . Manager )
{
throw new BadRequestException ( "The Manager role has been deprecated by collection enhancements. Use the collection Can Manage permission instead." ) ;
}
if ( organizationAbility ? . FlexibleCollections = = true & & user . AccessAll )
{
throw new BadRequestException ( "The AccessAll property has been deprecated by collection enhancements. Assign the user to collections instead." ) ;
}
2024-02-08 07:44:36 -06:00
if ( organizationAbility ? . FlexibleCollections = = true & & collections ? . Any ( ) = = true )
{
var invalidAssociations = collections . Where ( cas = > cas . Manage & & ( cas . ReadOnly | | cas . HidePasswords ) ) ;
if ( invalidAssociations . Any ( ) )
{
throw new BadRequestException ( "The Manage property is mutually exclusive and cannot be true while the ReadOnly or HidePasswords properties are also true." ) ;
}
}
2024-01-22 08:56:20 +10:00
// End Flexible Collections
2023-08-05 07:51:12 +10:00
// Only autoscale (if required) after all validation has passed so that we know it's a valid request before
// updating Stripe
if ( ! originalUser . AccessSecretsManager & & user . AccessSecretsManager )
{
var additionalSmSeatsRequired = await _countNewSmSeatsRequiredQuery . CountNewSmSeatsRequiredAsync ( user . OrganizationId , 1 ) ;
if ( additionalSmSeatsRequired > 0 )
{
var organization = await _organizationRepository . GetByIdAsync ( user . OrganizationId ) ;
2023-08-28 08:05:23 +10:00
var update = new SecretsManagerSubscriptionUpdate ( organization , true )
. AdjustSeats ( additionalSmSeatsRequired ) ;
2023-08-05 07:51:12 +10:00
await _updateSecretsManagerSubscriptionCommand . UpdateSubscriptionAsync ( update ) ;
}
}
2023-12-04 12:41:03 +00:00
if ( user . AccessAll )
{
// We don't need any collections if we're flagged to have all access.
collections = new List < CollectionAccessSelection > ( ) ;
}
2017-03-23 00:17:34 -04:00
await _organizationUserRepository . ReplaceAsync ( user , collections ) ;
2023-01-19 17:00:54 +01:00
if ( groups ! = null )
{
await _organizationUserRepository . UpdateGroupsAsync ( user . Id , groups ) ;
}
2020-03-27 14:36:37 -04:00
await _eventService . LogOrganizationUserEventAsync ( user , EventType . OrganizationUser_Updated ) ;
2022-08-29 16:06:55 -04:00
}
2017-03-23 00:17:34 -04:00
2022-10-31 09:58:21 +00:00
[Obsolete("IDeleteOrganizationUserCommand should be used instead. To be removed by EC-607.")]
2020-03-27 14:36:37 -04:00
public async Task DeleteUserAsync ( Guid organizationId , Guid organizationUserId , Guid ? deletingUserId )
2022-11-09 12:13:29 +00:00
{
var orgUser = await RepositoryDeleteUserAsync ( organizationId , organizationUserId , deletingUserId ) ;
await _eventService . LogOrganizationUserEventAsync ( orgUser , EventType . OrganizationUser_Removed ) ;
}
[Obsolete("IDeleteOrganizationUserCommand should be used instead. To be removed by EC-607.")]
public async Task DeleteUserAsync ( Guid organizationId , Guid organizationUserId ,
EventSystemUser systemUser )
{
var orgUser = await RepositoryDeleteUserAsync ( organizationId , organizationUserId , null ) ;
await _eventService . LogOrganizationUserEventAsync ( orgUser , EventType . OrganizationUser_Removed , systemUser ) ;
}
private async Task < OrganizationUser > RepositoryDeleteUserAsync ( Guid organizationId , Guid organizationUserId , Guid ? deletingUserId )
2022-08-29 16:06:55 -04:00
{
2017-04-18 15:27:54 -04:00
var orgUser = await _organizationUserRepository . GetByIdAsync ( organizationUserId ) ;
2021-07-16 14:17:24 -04:00
if ( orgUser = = null | | orgUser . OrganizationId ! = organizationId )
2017-04-18 15:27:54 -04:00
{
throw new BadRequestException ( "User not valid." ) ;
}
2021-05-17 10:10:44 +02:00
if ( deletingUserId . HasValue & & orgUser . UserId = = deletingUserId . Value )
2017-09-27 22:37:13 -04:00
{
2021-05-17 10:10:44 +02:00
throw new BadRequestException ( "You cannot remove yourself." ) ;
2017-09-27 22:37:13 -04:00
}
2021-09-23 06:36:08 -04:00
if ( orgUser . Type = = OrganizationUserType . Owner & & deletingUserId . HasValue & &
! await _currentContext . OrganizationOwner ( organizationId ) )
2017-03-29 21:26:19 -04:00
{
throw new BadRequestException ( "Only owners can delete other owners." ) ;
}
2023-05-17 16:39:08 +01:00
if ( ! await HasConfirmedOwnersExceptAsync ( organizationId , new [ ] { organizationUserId } , includeProvider : true ) )
2022-08-29 15:53:48 -04:00
{
2017-12-01 16:00:30 -05:00
throw new BadRequestException ( "Organization must have at least one confirmed owner." ) ;
2022-08-29 15:53:48 -04:00
}
2017-05-26 22:52:50 -04:00
2020-03-27 14:36:37 -04:00
await _organizationUserRepository . DeleteAsync ( orgUser ) ;
2017-04-12 10:07:27 -04:00
if ( orgUser . UserId . HasValue )
2022-08-29 14:53:16 -04:00
{
2017-04-12 10:07:27 -04:00
await DeleteAndPushUserRegistrationAsync ( organizationId , orgUser . UserId . Value ) ;
}
2022-11-09 12:13:29 +00:00
return orgUser ;
2022-08-29 16:06:55 -04:00
}
2017-04-12 10:07:27 -04:00
2021-09-23 06:36:08 -04:00
public async Task DeleteUserAsync ( Guid organizationId , Guid userId )
2022-08-29 16:06:55 -04:00
{
2017-12-01 16:00:30 -05:00
var orgUser = await _organizationUserRepository . GetByOrganizationAsync ( organizationId , userId ) ;
if ( orgUser = = null )
2017-04-12 10:07:27 -04:00
{
2017-12-01 16:00:30 -05:00
throw new NotFoundException ( ) ;
2022-08-29 15:53:48 -04:00
}
2017-05-26 22:52:50 -04:00
2021-05-17 10:10:44 +02:00
if ( ! await HasConfirmedOwnersExceptAsync ( organizationId , new [ ] { orgUser . Id } ) )
2022-08-29 15:53:48 -04:00
{
2021-05-17 10:10:44 +02:00
throw new BadRequestException ( "Organization must have at least one confirmed owner." ) ;
2022-08-29 14:53:16 -04:00
}
2017-03-23 00:17:34 -04:00
2021-05-25 19:23:47 +02:00
await _organizationUserRepository . DeleteAsync ( orgUser ) ;
2021-05-17 10:10:44 +02:00
await _eventService . LogOrganizationUserEventAsync ( orgUser , EventType . OrganizationUser_Removed ) ;
if ( orgUser . UserId . HasValue )
{
await DeleteAndPushUserRegistrationAsync ( organizationId , orgUser . UserId . Value ) ;
}
2022-08-29 16:06:55 -04:00
}
2021-05-17 10:10:44 +02:00
2021-05-25 19:23:47 +02:00
public async Task < List < Tuple < OrganizationUser , string > > > DeleteUsersAsync ( Guid organizationId ,
IEnumerable < Guid > organizationUsersId ,
Guid ? deletingUserId )
2021-05-17 10:10:44 +02:00
{
2021-05-25 19:23:47 +02:00
var orgUsers = await _organizationUserRepository . GetManyAsync ( organizationUsersId ) ;
var filteredUsers = orgUsers . Where ( u = > u . OrganizationId = = organizationId )
. ToList ( ) ;
2021-05-17 10:10:44 +02:00
2021-05-25 19:23:47 +02:00
if ( ! filteredUsers . Any ( ) )
2021-05-17 10:10:44 +02:00
{
2021-07-08 17:05:32 +02:00
throw new BadRequestException ( "Users invalid." ) ;
2021-05-17 10:10:44 +02:00
}
2021-05-25 19:23:47 +02:00
if ( ! await HasConfirmedOwnersExceptAsync ( organizationId , organizationUsersId ) )
2021-05-17 10:10:44 +02:00
{
2021-05-25 19:23:47 +02:00
throw new BadRequestException ( "Organization must have at least one confirmed owner." ) ;
2022-08-29 15:53:48 -04:00
}
2021-05-25 19:23:47 +02:00
var deletingUserIsOwner = false ;
if ( deletingUserId . HasValue )
2022-08-29 15:53:48 -04:00
{
2021-05-25 19:23:47 +02:00
deletingUserIsOwner = await _currentContext . OrganizationOwner ( organizationId ) ;
}
2021-05-17 10:10:44 +02:00
2021-05-25 19:23:47 +02:00
var result = new List < Tuple < OrganizationUser , string > > ( ) ;
var deletedUserIds = new List < Guid > ( ) ;
foreach ( var orgUser in filteredUsers )
2022-08-29 16:06:55 -04:00
{
try
2022-08-29 15:53:48 -04:00
{
2021-05-25 19:23:47 +02:00
if ( deletingUserId . HasValue & & orgUser . UserId = = deletingUserId )
{
2021-11-09 16:37:32 +01:00
throw new BadRequestException ( "You cannot remove yourself." ) ;
2022-08-29 15:53:48 -04:00
}
2022-06-16 15:59:57 -04:00
if ( orgUser . Type = = OrganizationUserType . Owner & & deletingUserId . HasValue & & ! deletingUserIsOwner )
2022-08-29 15:53:48 -04:00
{
2021-05-25 19:23:47 +02:00
throw new BadRequestException ( "Only owners can delete other owners." ) ;
}
await _eventService . LogOrganizationUserEventAsync ( orgUser , EventType . OrganizationUser_Removed ) ;
if ( orgUser . UserId . HasValue )
2021-05-17 10:10:44 +02:00
{
2021-05-25 19:23:47 +02:00
await DeleteAndPushUserRegistrationAsync ( organizationId , orgUser . UserId . Value ) ;
2021-05-17 10:10:44 +02:00
}
2021-08-05 08:50:41 -04:00
result . Add ( Tuple . Create ( orgUser , "" ) ) ;
deletedUserIds . Add ( orgUser . Id ) ;
2022-08-29 16:06:55 -04:00
}
2021-08-05 08:50:41 -04:00
catch ( BadRequestException e )
2022-08-29 16:06:55 -04:00
{
2021-05-25 19:23:47 +02:00
result . Add ( Tuple . Create ( orgUser , e . Message ) ) ;
2021-05-17 10:10:44 +02:00
}
2021-07-08 17:05:32 +02:00
await _organizationUserRepository . DeleteManyAsync ( deletedUserIds ) ;
2017-12-01 16:00:30 -05:00
}
2021-05-17 09:43:02 -05:00
2021-01-30 17:56:37 -05:00
return result ;
2022-08-29 16:06:55 -04:00
}
2022-06-08 08:44:28 -05:00
public async Task < bool > HasConfirmedOwnersExceptAsync ( Guid organizationId , IEnumerable < Guid > organizationUsersId , bool includeProvider = true )
2022-08-29 16:06:55 -04:00
{
2021-03-30 09:48:52 -05:00
var confirmedOwners = await GetConfirmedOwnersAsync ( organizationId ) ;
2021-05-17 10:10:44 +02:00
var confirmedOwnersIds = confirmedOwners . Select ( u = > u . Id ) ;
2021-03-30 09:48:52 -05:00
bool hasOtherOwner = confirmedOwnersIds . Except ( organizationUsersId ) . Any ( ) ;
2021-08-05 08:50:41 -04:00
if ( ! hasOtherOwner & & includeProvider )
2021-03-30 09:48:52 -05:00
{
2023-05-17 16:39:08 +01:00
return ( await _providerUserRepository . GetManyByOrganizationAsync ( organizationId , ProviderUserStatusType . Confirmed ) ) . Any ( ) ;
2021-03-30 09:48:52 -05:00
}
2021-08-05 08:50:41 -04:00
return hasOtherOwner ;
2022-08-29 16:06:55 -04:00
}
2021-09-23 06:36:08 -04:00
2021-05-19 09:40:32 -05:00
public async Task UpdateUserResetPasswordEnrollmentAsync ( Guid organizationId , Guid userId , string resetPasswordKey , Guid ? callingUserId )
2022-08-29 16:06:55 -04:00
{
2021-05-19 09:40:32 -05:00
// Org User must be the same as the calling user and the organization ID associated with the user must match passed org ID
var orgUser = await _organizationUserRepository . GetByOrganizationAsync ( organizationId , userId ) ;
if ( ! callingUserId . HasValue | | orgUser = = null | | orgUser . UserId ! = callingUserId . Value | |
2021-03-30 09:48:52 -05:00
orgUser . OrganizationId ! = organizationId )
2021-05-19 09:40:32 -05:00
{
throw new BadRequestException ( "User not valid." ) ;
}
2021-09-23 06:36:08 -04:00
2021-07-08 10:48:43 -05:00
// Make sure the organization has the ability to use password reset
var org = await _organizationRepository . GetByIdAsync ( organizationId ) ;
if ( org = = null | | ! org . UseResetPassword )
{
2022-03-07 16:53:30 -05:00
throw new BadRequestException ( "Organization does not allow password reset enrollment." ) ;
2022-08-29 15:53:48 -04:00
}
2021-07-08 10:48:43 -05:00
// Make sure the organization has the policy enabled
2021-05-19 09:40:32 -05:00
var resetPasswordPolicy =
2021-07-08 10:48:43 -05:00
await _policyRepository . GetByOrganizationIdTypeAsync ( organizationId , PolicyType . ResetPassword ) ;
if ( resetPasswordPolicy = = null | | ! resetPasswordPolicy . Enabled )
{
throw new BadRequestException ( "Organization does not have the password reset policy enabled." ) ;
}
2017-12-01 16:00:30 -05:00
2021-05-17 09:43:02 -05:00
// Block the user from withdrawal if auto enrollment is enabled
if ( resetPasswordKey = = null & & resetPasswordPolicy . Data ! = null )
2022-08-29 15:53:48 -04:00
{
2021-03-30 09:48:52 -05:00
var data = JsonSerializer . Deserialize < ResetPasswordDataModel > ( resetPasswordPolicy . Data , JsonHelpers . IgnoreCase ) ;
2022-08-29 14:53:16 -04:00
2017-08-15 16:11:08 -04:00
if ( data ? . AutoEnrollEnabled ? ? false )
2022-08-29 14:53:16 -04:00
{
2017-08-30 11:23:55 -04:00
throw new BadRequestException ( "Due to an Enterprise Policy, you are not allowed to withdraw from Password Reset." ) ;
2022-08-29 14:53:16 -04:00
}
2017-08-30 11:23:55 -04:00
}
2020-08-18 17:00:21 -04:00
orgUser . ResetPasswordKey = resetPasswordKey ;
await _organizationUserRepository . ReplaceAsync ( orgUser ) ;
await _eventService . LogOrganizationUserEventAsync ( orgUser , resetPasswordKey ! = null ?
EventType . OrganizationUser_ResetPassword_Enroll : EventType . OrganizationUser_ResetPassword_Withdraw ) ;
2022-08-29 16:06:55 -04:00
}
2017-08-15 16:11:08 -04:00
public async Task < OrganizationUser > InviteUserAsync ( Guid organizationId , Guid ? invitingUserId , string email ,
2024-02-08 07:44:36 -06:00
OrganizationUserType type , bool accessAll , string externalId , ICollection < CollectionAccessSelection > collections ,
2023-01-19 17:00:54 +01:00
IEnumerable < Guid > groups )
2022-11-09 12:13:29 +00:00
{
2024-02-08 07:44:36 -06:00
// Validate Collection associations if org is using latest collection enhancements
var organizationAbility = await _applicationCacheService . GetOrganizationAbilityAsync ( organizationId ) ;
if ( organizationAbility ? . FlexibleCollections ? ? false )
{
var invalidAssociations = collections ? . Where ( cas = > cas . Manage & & ( cas . ReadOnly | | cas . HidePasswords ) ) ;
if ( invalidAssociations ? . Any ( ) ? ? false )
{
throw new BadRequestException ( "The Manage property is mutually exclusive and cannot be true while the ReadOnly or HidePasswords properties are also true." ) ;
}
}
2023-01-19 17:00:54 +01:00
return await SaveUserSendInviteAsync ( organizationId , invitingUserId , systemUser : null , email , type , accessAll , externalId , collections , groups ) ;
2022-11-09 12:13:29 +00:00
}
public async Task < OrganizationUser > InviteUserAsync ( Guid organizationId , EventSystemUser systemUser , string email ,
2023-01-19 17:00:54 +01:00
OrganizationUserType type , bool accessAll , string externalId , IEnumerable < CollectionAccessSelection > collections ,
IEnumerable < Guid > groups )
2022-11-09 12:13:29 +00:00
{
2024-02-08 07:44:36 -06:00
// Collection associations validation not required as they are always an empty list - created via system user (scim)
2023-01-19 17:00:54 +01:00
return await SaveUserSendInviteAsync ( organizationId , invitingUserId : null , systemUser , email , type , accessAll , externalId , collections , groups ) ;
2022-11-09 12:13:29 +00:00
}
private async Task < OrganizationUser > SaveUserSendInviteAsync ( Guid organizationId , Guid ? invitingUserId , EventSystemUser ? systemUser , string email ,
2023-01-19 17:00:54 +01:00
OrganizationUserType type , bool accessAll , string externalId , IEnumerable < CollectionAccessSelection > collections , IEnumerable < Guid > groups )
2022-08-29 16:06:55 -04:00
{
2021-01-30 17:56:37 -05:00
var invite = new OrganizationUserInvite ( )
2022-08-29 16:06:55 -04:00
{
2021-01-30 17:56:37 -05:00
Emails = new List < string > { email } ,
Type = type ,
AccessAll = accessAll ,
Collections = collections ,
2023-01-19 17:00:54 +01:00
Groups = groups
2022-08-29 16:06:55 -04:00
} ;
2022-11-09 12:13:29 +00:00
var results = systemUser . HasValue ? await InviteUsersAsync ( organizationId , systemUser . Value ,
new ( OrganizationUserInvite , string ) [ ] { ( invite , externalId ) } ) : await InviteUsersAsync ( organizationId , invitingUserId ,
2021-01-30 17:56:37 -05:00
new ( OrganizationUserInvite , string ) [ ] { ( invite , externalId ) } ) ;
2017-05-13 12:00:40 -04:00
var result = results . FirstOrDefault ( ) ;
2021-01-30 17:56:37 -05:00
if ( result = = null )
2022-08-29 16:06:55 -04:00
{
2021-01-30 17:56:37 -05:00
throw new BadRequestException ( "This user has already been invited." ) ;
}
return result ;
2022-08-29 16:06:55 -04:00
}
2021-01-30 17:56:37 -05:00
2017-05-16 00:11:21 -04:00
public async Task ImportAsync ( Guid organizationId ,
Guid ? importingUserId ,
IEnumerable < ImportedGroup > groups ,
IEnumerable < ImportedOrganizationUser > newUsers ,
IEnumerable < string > removeUserExternalIds ,
bool overwriteExisting )
2022-08-29 16:06:55 -04:00
{
2017-05-16 00:11:21 -04:00
var organization = await GetOrgById ( organizationId ) ;
if ( organization = = null )
2017-05-13 12:00:40 -04:00
{
throw new NotFoundException ( ) ;
}
2017-05-20 15:31:16 -04:00
if ( ! organization . UseDirectory )
2022-08-29 15:53:48 -04:00
{
2017-05-20 15:31:16 -04:00
throw new BadRequestException ( "Organization cannot use directory syncing." ) ;
2022-08-29 15:53:48 -04:00
}
2017-05-13 12:00:40 -04:00
2017-05-18 10:41:47 -04:00
var newUsersSet = new HashSet < string > ( newUsers ? . Select ( u = > u . ExternalId ) ? ? new List < string > ( ) ) ;
var existingUsers = await _organizationUserRepository . GetManyDetailsByOrganizationAsync ( organizationId ) ;
var existingExternalUsers = existingUsers . Where ( u = > ! string . IsNullOrWhiteSpace ( u . ExternalId ) ) . ToList ( ) ;
var existingExternalUsersIdDict = existingExternalUsers . ToDictionary ( u = > u . ExternalId , u = > u . Id ) ;
2017-05-13 12:00:40 -04:00
2017-05-16 00:11:21 -04:00
// Users
2017-11-13 12:09:39 -05:00
2017-05-18 10:41:47 -04:00
// Remove Users
2021-05-17 09:43:02 -05:00
if ( removeUserExternalIds ? . Any ( ) ? ? false )
2022-08-29 16:06:55 -04:00
{
2021-05-17 09:43:02 -05:00
var removeUsersSet = new HashSet < string > ( removeUserExternalIds ) ;
var existingUsersDict = existingExternalUsers . ToDictionary ( u = > u . ExternalId ) ;
2017-05-13 14:14:20 -04:00
2021-05-17 09:43:02 -05:00
await _organizationUserRepository . DeleteManyAsync ( removeUsersSet
. Except ( newUsersSet )
. Where ( u = > existingUsersDict . ContainsKey ( u ) & & existingUsersDict [ u ] . Type ! = OrganizationUserType . Owner )
. Select ( u = > existingUsersDict [ u ] . Id ) ) ;
2022-08-29 16:06:55 -04:00
}
2022-08-29 15:53:48 -04:00
2020-03-27 14:36:37 -04:00
if ( overwriteExisting )
2022-08-29 16:06:55 -04:00
{
2021-05-17 09:43:02 -05:00
// Remove existing external users that are not in new user set
var usersToDelete = existingExternalUsers . Where ( u = >
u . Type ! = OrganizationUserType . Owner & &
! newUsersSet . Contains ( u . ExternalId ) & &
2017-05-18 10:41:47 -04:00
existingExternalUsersIdDict . ContainsKey ( u . ExternalId ) ) ;
2021-05-17 09:43:02 -05:00
await _organizationUserRepository . DeleteManyAsync ( usersToDelete . Select ( u = > u . Id ) ) ;
foreach ( var deletedUser in usersToDelete )
2022-08-29 16:06:55 -04:00
{
2021-05-17 09:43:02 -05:00
existingExternalUsersIdDict . Remove ( deletedUser . ExternalId ) ;
2017-05-13 12:00:40 -04:00
}
2022-08-29 16:06:55 -04:00
}
2017-05-13 12:00:40 -04:00
2020-03-27 14:36:37 -04:00
if ( newUsers ? . Any ( ) ? ? false )
2022-08-29 16:06:55 -04:00
{
2020-03-27 14:36:37 -04:00
// Marry existing users
2017-11-10 15:22:19 -05:00
var existingUsersEmailsDict = existingUsers
2020-03-27 14:36:37 -04:00
. Where ( u = > string . IsNullOrWhiteSpace ( u . ExternalId ) )
2017-11-10 15:22:19 -05:00
. ToDictionary ( u = > u . Email ) ;
var newUsersEmailsDict = newUsers . ToDictionary ( u = > u . Email ) ;
var usersToAttach = existingUsersEmailsDict . Keys . Intersect ( newUsersEmailsDict . Keys ) . ToList ( ) ;
var usersToUpsert = new List < OrganizationUser > ( ) ;
2020-03-27 14:36:37 -04:00
foreach ( var user in usersToAttach )
2019-05-06 21:31:20 -04:00
{
2021-05-17 09:43:02 -05:00
var orgUserDetails = existingUsersEmailsDict [ user ] ;
var orgUser = await _organizationUserRepository . GetByIdAsync ( orgUserDetails . Id ) ;
if ( orgUser ! = null )
2019-05-06 21:31:20 -04:00
{
2021-05-17 09:43:02 -05:00
orgUser . ExternalId = newUsersEmailsDict [ user ] . ExternalId ;
2017-05-15 14:41:20 -04:00
usersToUpsert . Add ( orgUser ) ;
2021-05-17 09:43:02 -05:00
existingExternalUsersIdDict . Add ( orgUser . ExternalId , orgUser . Id ) ;
2019-05-06 21:31:20 -04:00
}
}
2017-05-15 14:41:20 -04:00
await _organizationUserRepository . UpsertManyAsync ( usersToUpsert ) ;
2017-11-10 15:22:19 -05:00
2020-03-27 14:36:37 -04:00
// Add new users
2017-11-10 15:22:19 -05:00
var existingUsersSet = new HashSet < string > ( existingExternalUsersIdDict . Keys ) ;
var usersToAdd = newUsersSet . Except ( existingUsersSet ) . ToList ( ) ;
2017-05-13 12:00:40 -04:00
2020-03-27 14:36:37 -04:00
var seatsAvailable = int . MaxValue ;
var enoughSeatsAvailable = true ;
if ( organization . Seats . HasValue )
2022-08-29 16:06:55 -04:00
{
2023-02-24 07:54:19 +10:00
var occupiedSeats = await _organizationUserRepository . GetOccupiedSeatCountByOrganizationIdAsync ( organization . Id ) ;
2022-09-23 14:30:39 +10:00
seatsAvailable = organization . Seats . Value - occupiedSeats ;
2020-03-27 14:36:37 -04:00
enoughSeatsAvailable = seatsAvailable > = usersToAdd . Count ;
2022-08-29 16:06:55 -04:00
}
2022-08-29 15:53:48 -04:00
2020-03-27 14:36:37 -04:00
var userInvites = new List < ( OrganizationUserInvite , string ) > ( ) ;
foreach ( var user in newUsers )
2022-08-29 16:06:55 -04:00
{
2020-03-27 14:36:37 -04:00
if ( ! usersToAdd . Contains ( user . ExternalId ) | | string . IsNullOrWhiteSpace ( user . Email ) )
2017-05-13 12:00:40 -04:00
{
2017-05-15 14:41:20 -04:00
continue ;
2017-05-13 12:00:40 -04:00
}
2021-05-17 09:43:02 -05:00
try
2021-03-25 08:42:04 -05:00
{
2021-05-17 09:43:02 -05:00
var invite = new OrganizationUserInvite
2022-08-29 15:53:48 -04:00
{
2021-05-17 09:43:02 -05:00
Emails = new List < string > { user . Email } ,
Type = OrganizationUserType . User ,
AccessAll = false ,
2023-01-19 17:00:54 +01:00
Collections = new List < CollectionAccessSelection > ( ) ,
2022-08-29 16:06:55 -04:00
} ;
2021-05-17 09:43:02 -05:00
userInvites . Add ( ( invite , user . ExternalId ) ) ;
2017-05-13 12:00:40 -04:00
}
2021-05-17 09:43:02 -05:00
catch ( BadRequestException )
{
// Thrown when the user is already invited to the organization
continue ;
}
2017-05-13 12:00:40 -04:00
}
2021-05-17 09:43:02 -05:00
var invitedUsers = await InviteUsersAsync ( organizationId , importingUserId , userInvites ) ;
foreach ( var invitedUser in invitedUsers )
2022-08-29 16:06:55 -04:00
{
2021-05-17 09:43:02 -05:00
existingExternalUsersIdDict . Add ( invitedUser . ExternalId , invitedUser . Id ) ;
2022-08-29 16:06:55 -04:00
}
}
2017-11-13 12:09:39 -05:00
2021-05-17 09:43:02 -05:00
// Groups
2020-03-27 14:36:37 -04:00
if ( groups ? . Any ( ) ? ? false )
2022-08-29 16:06:55 -04:00
{
2020-03-27 14:36:37 -04:00
if ( ! organization . UseGroups )
2017-05-13 12:00:40 -04:00
{
2017-05-20 15:31:16 -04:00
throw new BadRequestException ( "Organization cannot use groups." ) ;
}
2017-05-15 14:41:20 -04:00
var groupsDict = groups . ToDictionary ( g = > g . Group . ExternalId ) ;
2017-05-18 10:41:47 -04:00
var existingGroups = await _groupRepository . GetManyByOrganizationIdAsync ( organizationId ) ;
2017-05-15 14:41:20 -04:00
var existingExternalGroups = existingGroups
2017-05-18 10:41:47 -04:00
. Where ( u = > ! string . IsNullOrWhiteSpace ( u . ExternalId ) ) . ToList ( ) ;
var existingExternalGroupsDict = existingExternalGroups . ToDictionary ( g = > g . ExternalId ) ;
2017-05-15 14:41:20 -04:00
2020-03-27 14:36:37 -04:00
var newGroups = groups
2017-05-15 14:41:20 -04:00
. Where ( g = > ! existingExternalGroupsDict . ContainsKey ( g . Group . ExternalId ) )
. Select ( g = > g . Group ) ;
2017-05-13 12:00:40 -04:00
2017-05-15 14:41:20 -04:00
foreach ( var group in newGroups )
2022-08-29 15:53:48 -04:00
{
2017-05-15 14:41:20 -04:00
group . CreationDate = group . RevisionDate = DateTime . UtcNow ;
2017-05-13 14:14:20 -04:00
2017-05-18 10:41:47 -04:00
await _groupRepository . CreateAsync ( group ) ;
2017-05-15 16:37:56 -04:00
await UpdateUsersAsync ( group , groupsDict [ group . ExternalId ] . ExternalUserIds ,
existingExternalUsersIdDict ) ;
2022-08-29 15:53:48 -04:00
}
2017-05-15 16:37:56 -04:00
var updateGroups = existingExternalGroups
. Where ( g = > groupsDict . ContainsKey ( g . ExternalId ) )
. ToList ( ) ;
2017-05-15 14:41:20 -04:00
2020-03-27 14:36:37 -04:00
if ( updateGroups . Any ( ) )
2022-08-29 14:53:16 -04:00
{
2017-05-16 00:11:21 -04:00
var groupUsers = await _groupRepository . GetManyGroupUsersByOrganizationIdAsync ( organizationId ) ;
2017-05-15 16:37:56 -04:00
var existingGroupUsers = groupUsers
. GroupBy ( gu = > gu . GroupId )
. ToDictionary ( g = > g . Key , g = > new HashSet < Guid > ( g . Select ( gr = > gr . OrganizationUserId ) ) ) ;
2022-08-29 14:53:16 -04:00
2020-03-27 14:36:37 -04:00
foreach ( var group in updateGroups )
2022-08-29 16:06:55 -04:00
{
2019-05-14 11:16:30 -04:00
var updatedGroup = groupsDict [ group . ExternalId ] . Group ;
2020-03-27 14:36:37 -04:00
if ( group . Name ! = updatedGroup . Name )
2022-08-29 15:53:48 -04:00
{
2017-05-15 16:37:56 -04:00
group . RevisionDate = DateTime . UtcNow ;
2020-03-27 14:36:37 -04:00
group . Name = updatedGroup . Name ;
2022-08-29 16:06:55 -04:00
2017-05-15 16:37:56 -04:00
await _groupRepository . ReplaceAsync ( group ) ;
2017-05-15 15:01:16 -04:00
}
2022-08-29 16:06:55 -04:00
2019-05-14 11:16:30 -04:00
await UpdateUsersAsync ( group , groupsDict [ group . ExternalId ] . ExternalUserIds ,
existingExternalUsersIdDict ,
2017-05-15 16:37:56 -04:00
existingGroupUsers . ContainsKey ( group . Id ) ? existingGroupUsers [ group . Id ] : null ) ;
2017-05-13 12:00:40 -04:00
}
}
2022-08-29 14:53:16 -04:00
}
2021-08-17 13:12:55 -04:00
await _referenceEventService . RaiseEventAsync (
2023-05-16 16:21:57 +02:00
new ReferenceEvent ( ReferenceEventType . DirectorySynced , organization , _currentContext ) ) ;
2022-08-29 16:06:55 -04:00
}
2020-08-26 14:12:04 -04:00
public async Task DeleteSsoUserAsync ( Guid userId , Guid ? organizationId )
2022-08-29 16:06:55 -04:00
{
2020-08-26 14:12:04 -04:00
await _ssoUserRepository . DeleteAsync ( userId , organizationId ) ;
if ( organizationId . HasValue )
{
var organizationUser = await _organizationUserRepository . GetByOrganizationAsync ( organizationId . Value , userId ) ;
if ( organizationUser ! = null )
{
await _eventService . LogOrganizationUserEventAsync ( organizationUser , EventType . OrganizationUser_UnlinkedSso ) ;
}
}
2022-08-29 16:06:55 -04:00
}
2021-05-19 09:40:32 -05:00
2017-05-15 15:01:16 -04:00
public async Task < Organization > UpdateOrganizationKeysAsync ( Guid orgId , string publicKey , string privateKey )
2022-08-29 16:06:55 -04:00
{
2020-03-27 14:36:37 -04:00
if ( ! await _currentContext . ManageResetPassword ( orgId ) )
2017-05-15 14:41:20 -04:00
{
2020-03-27 14:36:37 -04:00
throw new UnauthorizedAccessException ( ) ;
2017-03-29 21:26:19 -04:00
}
2017-08-11 08:57:31 -04:00
2017-11-14 08:39:16 -05:00
// If the keys already exist, error out
var org = await _organizationRepository . GetByIdAsync ( orgId ) ;
if ( org . PublicKey ! = null & & org . PrivateKey ! = null )
2021-05-17 10:10:44 +02:00
{
2017-12-19 16:02:39 -05:00
throw new BadRequestException ( "Organization Keys already exist" ) ;
2017-08-11 08:57:31 -04:00
}
2017-12-19 16:02:39 -05:00
// Update org with generated public/private key
org . PublicKey = publicKey ;
2021-05-19 09:40:32 -05:00
org . PrivateKey = privateKey ;
2017-12-01 16:00:30 -05:00
await UpdateAsync ( org ) ;
2022-08-29 16:06:55 -04:00
2017-05-13 12:00:40 -04:00
return org ;
2022-08-29 16:06:55 -04:00
}
2017-12-19 16:02:39 -05:00
private async Task UpdateUsersAsync ( Group group , HashSet < string > groupUsers ,
Dictionary < string , Guid > existingUsersIdDict , HashSet < Guid > existingUsers = null )
2022-08-29 16:06:55 -04:00
{
2017-12-19 16:02:39 -05:00
var availableUsers = groupUsers . Intersect ( existingUsersIdDict . Keys ) ;
var users = new HashSet < Guid > ( availableUsers . Select ( u = > existingUsersIdDict [ u ] ) ) ;
if ( existingUsers ! = null & & existingUsers . Count = = users . Count & & users . SetEquals ( existingUsers ) )
{
return ;
}
2017-08-11 08:57:31 -04:00
await _groupRepository . UpdateUsersAsync ( group . Id , users ) ;
2022-08-29 16:06:55 -04:00
}
2022-05-10 17:12:09 -04:00
private async Task < IEnumerable < OrganizationUser > > GetConfirmedOwnersAsync ( Guid organizationId )
2022-08-29 16:06:55 -04:00
{
2017-12-19 16:02:39 -05:00
var owners = await _organizationUserRepository . GetManyByOrganizationAsync ( organizationId ,
2017-05-13 12:00:40 -04:00
OrganizationUserType . Owner ) ;
2017-12-19 16:02:39 -05:00
return owners . Where ( o = > o . Status = = OrganizationUserStatusType . Confirmed ) ;
2022-08-29 16:06:55 -04:00
}
2017-12-19 16:02:39 -05:00
private async Task DeleteAndPushUserRegistrationAsync ( Guid organizationId , Guid userId )
2022-08-29 16:06:55 -04:00
{
2017-12-19 16:02:39 -05:00
var deviceIds = await GetUserDeviceIdsAsync ( userId ) ;
await _pushRegistrationService . DeleteUserRegistrationOrganizationAsync ( deviceIds ,
organizationId . ToString ( ) ) ;
await _pushNotificationService . PushSyncOrgKeysAsync ( userId ) ;
2022-08-29 16:06:55 -04:00
}
2020-08-11 14:19:56 -04:00
private async Task < IEnumerable < string > > GetUserDeviceIdsAsync ( Guid userId )
2022-08-29 16:06:55 -04:00
{
2019-03-21 21:36:03 -04:00
var devices = await _deviceRepository . GetManyByUserIdAsync ( userId ) ;
return devices . Where ( d = > ! string . IsNullOrWhiteSpace ( d . PushToken ) ) . Select ( d = > d . Id . ToString ( ) ) ;
2022-08-29 16:06:55 -04:00
}
2023-02-24 07:54:19 +10:00
public async Task ReplaceAndUpdateCacheAsync ( Organization org , EventType ? orgEvent = null )
2022-08-29 16:06:55 -04:00
{
2019-03-21 21:36:03 -04:00
await _organizationRepository . ReplaceAsync ( org ) ;
await _applicationCacheService . UpsertOrganizationAbilityAsync ( org ) ;
2022-08-29 16:06:55 -04:00
2020-03-27 14:36:37 -04:00
if ( orgEvent . HasValue )
2017-12-19 16:02:39 -05:00
{
await _eventService . LogOrganizationEventAsync ( org , orgEvent . Value ) ;
}
2022-08-29 16:06:55 -04:00
}
2019-03-21 21:36:03 -04:00
private async Task < Organization > GetOrgById ( Guid id )
2022-08-29 16:06:55 -04:00
{
2019-03-21 21:36:03 -04:00
return await _organizationRepository . GetByIdAsync ( id ) ;
2022-08-29 16:06:55 -04:00
}
2019-03-21 21:36:03 -04:00
2023-07-24 23:05:05 +01:00
private static void ValidatePlan ( Models . StaticStore . Plan plan , int additionalSeats , string productType )
2022-08-29 16:06:55 -04:00
{
2023-11-03 15:32:30 -04:00
if ( plan is null )
2019-03-21 21:36:03 -04:00
{
2023-11-03 15:32:30 -04:00
throw new BadRequestException ( $"{productType} Plan was null." ) ;
2019-03-21 21:36:03 -04:00
}
2023-07-24 23:05:05 +01:00
if ( plan . Disabled )
2019-03-21 21:36:03 -04:00
{
2023-07-24 23:05:05 +01:00
throw new BadRequestException ( $"{productType} Plan not found." ) ;
2019-03-21 21:36:03 -04:00
}
2023-07-24 23:05:05 +01:00
if ( additionalSeats < 0 )
{
throw new BadRequestException ( $"You can't subtract {productType} seats!" ) ;
}
}
public void ValidatePasswordManagerPlan ( Models . StaticStore . Plan plan , OrganizationUpgrade upgrade )
{
ValidatePlan ( plan , upgrade . AdditionalSeats , "Password Manager" ) ;
2023-10-17 15:56:35 +01:00
if ( plan . PasswordManager . BaseSeats + upgrade . AdditionalSeats < = 0 )
2019-03-21 21:36:03 -04:00
{
2023-07-24 23:05:05 +01:00
throw new BadRequestException ( $"You do not have any Password Manager seats!" ) ;
2021-01-12 11:02:39 -05:00
}
2021-07-01 14:31:05 +02:00
if ( upgrade . AdditionalSeats < 0 )
2021-01-12 11:02:39 -05:00
{
2023-07-24 23:05:05 +01:00
throw new BadRequestException ( $"You can't subtract Password Manager seats!" ) ;
}
2023-10-17 15:56:35 +01:00
if ( ! plan . PasswordManager . HasAdditionalStorageOption & & upgrade . AdditionalStorageGb > 0 )
2023-07-24 23:05:05 +01:00
{
throw new BadRequestException ( "Plan does not allow additional storage." ) ;
}
if ( upgrade . AdditionalStorageGb < 0 )
{
throw new BadRequestException ( "You can't subtract storage!" ) ;
}
2023-10-17 15:56:35 +01:00
if ( ! plan . PasswordManager . HasPremiumAccessOption & & upgrade . PremiumAccessAddon )
2023-07-24 23:05:05 +01:00
{
throw new BadRequestException ( "This plan does not allow you to buy the premium access addon." ) ;
2021-01-12 11:02:39 -05:00
}
2023-10-17 15:56:35 +01:00
if ( ! plan . PasswordManager . HasAdditionalSeatsOption & & upgrade . AdditionalSeats > 0 )
2022-08-29 14:53:16 -04:00
{
2021-07-08 17:05:32 +02:00
throw new BadRequestException ( "Plan does not allow additional users." ) ;
2021-01-12 11:02:39 -05:00
}
2023-10-17 15:56:35 +01:00
if ( plan . PasswordManager . HasAdditionalSeatsOption & & plan . PasswordManager . MaxAdditionalSeats . HasValue & &
upgrade . AdditionalSeats > plan . PasswordManager . MaxAdditionalSeats . Value )
2021-01-12 11:02:39 -05:00
{
throw new BadRequestException ( $"Selected plan allows a maximum of " +
2023-10-17 15:56:35 +01:00
$"{plan.PasswordManager.MaxAdditionalSeats.GetValueOrDefault(0)} additional users." ) ;
2023-07-24 23:05:05 +01:00
}
}
public void ValidateSecretsManagerPlan ( Models . StaticStore . Plan plan , OrganizationUpgrade upgrade )
{
2023-10-17 15:56:35 +01:00
if ( plan . SupportsSecretsManager = = false )
{
throw new BadRequestException ( "Invalid Secrets Manager plan selected." ) ;
}
2023-07-24 23:05:05 +01:00
ValidatePlan ( plan , upgrade . AdditionalSmSeats . GetValueOrDefault ( ) , "Secrets Manager" ) ;
2023-10-17 15:56:35 +01:00
if ( plan . SecretsManager . BaseSeats + upgrade . AdditionalSmSeats < = 0 )
{
throw new BadRequestException ( $"You do not have any Secrets Manager seats!" ) ;
}
if ( ! plan . SecretsManager . HasAdditionalServiceAccountOption & & upgrade . AdditionalServiceAccounts > 0 )
2023-07-24 23:05:05 +01:00
{
throw new BadRequestException ( "Plan does not allow additional Service Accounts." ) ;
}
2023-11-03 18:26:47 -04:00
if ( ( plan . Product = = ProductType . TeamsStarter & &
upgrade . AdditionalSmSeats . GetValueOrDefault ( ) > plan . PasswordManager . BaseSeats ) | |
( plan . Product ! = ProductType . TeamsStarter & &
upgrade . AdditionalSmSeats . GetValueOrDefault ( ) > upgrade . AdditionalSeats ) )
2023-07-24 23:05:05 +01:00
{
throw new BadRequestException ( "You cannot have more Secrets Manager seats than Password Manager seats." ) ;
}
if ( upgrade . AdditionalServiceAccounts . GetValueOrDefault ( ) < 0 )
{
throw new BadRequestException ( "You can't subtract Service Accounts!" ) ;
}
2023-10-17 15:56:35 +01:00
switch ( plan . SecretsManager . HasAdditionalSeatsOption )
2023-07-24 23:05:05 +01:00
{
case false when upgrade . AdditionalSmSeats > 0 :
throw new BadRequestException ( "Plan does not allow additional users." ) ;
2023-10-17 15:56:35 +01:00
case true when plan . SecretsManager . MaxAdditionalSeats . HasValue & &
upgrade . AdditionalSmSeats > plan . SecretsManager . MaxAdditionalSeats . Value :
2023-07-24 23:05:05 +01:00
throw new BadRequestException ( $"Selected plan allows a maximum of " +
2023-10-17 15:56:35 +01:00
$"{plan.SecretsManager.MaxAdditionalSeats.GetValueOrDefault(0)} additional users." ) ;
2021-01-12 11:02:39 -05:00
}
2022-08-29 16:06:55 -04:00
}
2021-01-12 11:02:39 -05:00
2023-09-01 09:10:02 +01:00
public async Task ValidateOrganizationUserUpdatePermissions ( Guid organizationId , OrganizationUserType newType , OrganizationUserType ? oldType , Permissions permissions )
2022-08-29 16:06:55 -04:00
{
2021-01-12 11:02:39 -05:00
if ( await _currentContext . OrganizationOwner ( organizationId ) )
2022-08-29 16:06:55 -04:00
{
2021-01-12 11:02:39 -05:00
return ;
2022-08-29 14:53:16 -04:00
}
2021-01-12 11:02:39 -05:00
2021-07-01 14:31:05 +02:00
if ( oldType = = OrganizationUserType . Owner | | newType = = OrganizationUserType . Owner )
2021-01-12 11:02:39 -05:00
{
throw new BadRequestException ( "Only an Owner can configure another Owner's account." ) ;
}
2021-11-09 16:37:32 +01:00
if ( await _currentContext . OrganizationAdmin ( organizationId ) )
{
return ;
}
2022-06-16 15:59:57 -04:00
2022-07-25 10:47:44 +10:00
if ( ! await _currentContext . ManageUsers ( organizationId ) )
2022-08-29 16:06:55 -04:00
{
2022-07-25 10:47:44 +10:00
throw new BadRequestException ( "Your account does not have permission to manage users." ) ;
2022-06-16 15:59:57 -04:00
}
2022-07-25 10:47:44 +10:00
if ( oldType = = OrganizationUserType . Admin | | newType = = OrganizationUserType . Admin )
2022-08-29 15:53:48 -04:00
{
2022-06-16 15:59:57 -04:00
throw new BadRequestException ( "Custom users can not manage Admins or Owners." ) ;
2022-08-29 16:06:55 -04:00
}
2023-05-17 14:17:37 +01:00
if ( newType = = OrganizationUserType . Custom & & ! await ValidateCustomPermissionsGrant ( organizationId , permissions ) )
{
throw new BadRequestException ( "Custom users can only grant the same custom permissions that they have." ) ;
}
2022-06-16 15:59:57 -04:00
}
2022-12-06 09:50:08 +00:00
private async Task ValidateOrganizationCustomPermissionsEnabledAsync ( Guid organizationId , OrganizationUserType newType )
{
if ( newType ! = OrganizationUserType . Custom )
{
return ;
}
var organization = await _organizationRepository . GetByIdAsync ( organizationId ) ;
if ( organization = = null )
{
throw new NotFoundException ( ) ;
}
if ( ! organization . UseCustomPermissions )
{
throw new BadRequestException ( "To enable custom permissions the organization must be on an Enterprise plan." ) ;
}
}
2023-05-17 14:17:37 +01:00
private async Task < bool > ValidateCustomPermissionsGrant ( Guid organizationId , Permissions permissions )
{
[AC-1373] Flexible Collections (#3245)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* fix: merge conflict resolution
* [AC-1174] CollectionUser and CollectionGroup authorization handlers (#3194)
* [AC-1174] Introduce BulkAuthorizationHandler.cs
* [AC-1174] Introduce CollectionUserAuthorizationHandler
* [AC-1174] Add CreateForNewCollection CollectionUser requirement
* [AC-1174] Add some more details to CollectionCustomization
* [AC-1174] Formatting
* [AC-1174] Add CollectionGroupOperation.cs
* [AC-1174] Introduce CollectionGroupAuthorizationHandler.cs
* [AC-1174] Cleanup CollectionFixture customization
Implement and use re-usable extension method to support seeded Guids
* [AC-1174] Introduce WithValueFromList AutoFixtureExtensions
Modify CollectionCustomization to use multiple organization Ids for auto generated test data
* [AC-1174] Simplify CollectionUserAuthorizationHandler.cs
Modify the authorization handler to only perform authorization logic. Validation logic will need to be handled by any calling commands/controllers instead.
* [AC-1174] Introduce shared CollectionAccessAuthorizationHandlerBase
A shared base authorization handler was created for both CollectionUser and CollectionGroup resources, as they share the same underlying management authorization logic.
* [AC-1174] Update CollectionUserAuthorizationHandler and CollectionGroupAuthorizationHandler to use the new CollectionAccessAuthorizationHandlerBase class
* [AC-1174] Formatting
* [AC-1174] Cleanup typo and redundant ToList() call
* [AC-1174] Add check for provider users
* [AC-1174] Reduce nested loops
* [AC-1174] Introduce ICollectionAccess.cs
* [AC-1174] Remove individual CollectionGroup and CollectionUser auth handlers and use base class instead
* [AC-1174] Tweak unit test to fail minimally
* [AC-1174] Reorganize authorization handlers in Core project
* [AC-1174] Introduce new AddCoreAuthorizationHandlers() extension method
* [AC-1174] Move CollectionAccessAuthorizationHandler into Api project
* [AC-1174] Move CollectionFixture to Vault folder
* [AC-1174] Rename operation to CreateUpdateDelete
* [AC-1174] Require single organization for collection access authorization handler
- Add requirement that all target collections must belong to the same organization
- Simplify logic related to multiple organizations
- Update tests and helpers
- Use ToHashSet to improve lookup time
* [AC-1174] Fix null reference exception
* [AC-1174] Throw bad request exception when collections belong to different organizations
* [AC-1174] Switch to CollectionAuthorizationHandler instead of CollectionAccessAuthorizationHandler to reduce complexity
* Fix improper merge conflict resolution
* fix: add permission check for collection management api, refs AC-1647 (#3252)
* [AC-1125] Enforce org setting for creating/deleting collections (#3241)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* feat: created collection auth handler/operations, added LimitCollectionCdOwnerAdmin to CurrentContentOrganization, refs AC-1125
* feat: create vault service collection extensions and register with base services, refs AC-1125
* feat: deprecated CurrentContext.CreateNewCollections, refs AC-1125
* feat: deprecate DeleteAnyCollection for single resource usages, refs AC-1125
* feat: move service registration to api, update references, refs AC-1125
* feat: add bulk delete authorization handler, refs AC-1125
* feat: always assign user and give manage access on create, refs AC-1125
* fix: updated CurrentContextOrganization type, refs AC-1125
* feat: combined existing collection authorization handlers/operations, refs AC-1125
* fix: OrganizationServiceTests -> CurrentContentOrganization typo, refs AC-1125
* fix: format, refs AC-1125
* fix: update collection controller tests, refs AC-1125
* fix: dotnet format, refs AC-1125
* feat: removed extra BulkAuthorizationHandler, refs AC-1125
* fix: dotnet format, refs AC-1125
* fix: change string to guid for org id, update bulk delete request model, refs AC-1125
* fix: remove delete many collection check, refs AC-1125
* fix: clean up collection auth handler, refs AC-1125
* fix: format fix for CollectionOperations, refs AC-1125
* fix: removed unnecessary owner check, add org null check to custom permission validation, refs AC-1125
* fix: remove unused methods in CurrentContext, refs AC-1125
* fix: removed obsolete test, fixed failling delete many test, refs AC-1125
* fix: CollectionAuthorizationHandlerTests fixes, refs AC-1125
* fix: OrganizationServiceTests fix broken test by mocking GetOrganization, refs AC-1125
* fix: CollectionAuthorizationHandler - remove unused repository, refs AC-1125
* feat: moved UserId null check to common method, refs AC-1125
* fix: updated auth handler tests to remove dependency on requirement for common code checks, refs AC-1125
* feat: updated conditionals/comments for create/delete methods within colleciton auth handler, refs AC-1125
* feat: added create/delete collection auth handler success methods, refs AC-1125
* fix: new up permissions to prevent excessive null checks, refs AC-1125
* fix: remove old reference to CreateNewCollections, refs AC-1125
* fix: typo within ViewAssignedCollections method, refs AC-1125
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
* refactor: remove organizationId from CollectionBulkDeleteRequestModel, refs AC-1649 (#3282)
* [AC-1174] Bulk Collection Management (#3229)
* [AC-1174] Update SelectionReadOnlyRequestModel to use Guid for Id property
* [AC-1174] Introduce initial bulk-access collection endpoint
* [AC-1174] Introduce BulkAddCollectionAccessCommand and validation logic/tests
* [AC-1174] Add CreateOrUpdateAccessMany method to CollectionRepository
* [AC-1174] Add event logs for bulk add collection access command
* [AC-1174] Add User_BumpAccountRevisionDateByCollectionIds and database migration script
* [AC-1174] Implement EF repository method
* [AC-1174] Improve null checks
* [AC-1174] Remove unnecessary BulkCollectionAccessRequestModel helpers
* [AC-1174] Add unit tests for new controller endpoint
* [AC-1174] Fix formatting
* [AC-1174] Remove comment
* [AC-1174] Remove redundant organizationId parameter
* [AC-1174] Ensure user and group Ids are distinct
* [AC-1174] Cleanup tests based on PR feedback
* [AC-1174] Formatting
* [AC-1174] Update CollectionGroup alias in the sproc
* [AC-1174] Add some additional comments to SQL sproc
* [AC-1174] Add comment explaining additional SaveChangesAsync call
---------
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
* [AC-1646] Rename LimitCollectionCdOwnerAdmin column (#3300)
* Rename LimitCollectionCdOwnerAdmin -> LimitCollectionCreationDeletion
* Rename and bump migration script
* [AC-1666] Removed EditAnyCollection from Create/Delete permission checks (#3301)
* fix: remove EditAnyCollection from Create/Delete permission check, refs AC-1666
* fix: updated comment, refs AC-1666
* [AC-1669] Bug - Remove obsolete assignUserId from CollectionService.SaveAsync(...) (#3312)
* fix: remove AssignUserId from CollectionService.SaveAsync, refs AC-1669
* fix: add manage access conditional before creating collection, refs AC-1669
* fix: move access logic for create/update, fix all tests, refs AC-1669
* fix: add CollectionAccessSelection fixture, update tests, update bad reqeuest message, refs AC-1669
* fix: format, refs AC-1669
* fix: update null params with specific arg.is null checks, refs Ac-1669
* fix: update attribute class name, refs AC-1669
* [AC-1713] [Flexible collections] Add feature flags to server (#3334)
* Add feature flags for FlexibleCollections and BulkCollectionAccess
* Flag new routes and behaviour
---------
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
* Add joint codeownership for auth handlers (#3346)
* [AC-1717] Update default values for LimitCollectionCreationDeletion (#3365)
* Change default value in organization create sproc to 1
* Drop old column name still present in some QA instances
* Set LimitCollectionCreationDeletion value in code based on feature flag
* Fix: add missing namespace after merging in master
* Fix: add missing namespace after merging in master
* [AC-1683] Fix DB migrations for new Manage permission (#3307)
* [AC-1683] Update migration script and introduce V2 procedures and types
* [AC-1683] Update repository calls to use new V2 procedures / types
* [AC-1684] Update bulk add collection migration script to use new V2 type
* [AC-1683] Undo Manage changes to more original procedures
* [AC-1683] Restore whitespace changes
* [AC-1683] Clarify comments regarding explicit column lists
* [AC-1683] Update migration script dates
* [AC-1683] Split the migration script for readability
* [AC-1683] Re-name SelectReadOnlyArray_V2 to CollectionAccessSelectionType
* [AC-1648] [Flexible Collections] Bump migration scripts before feature branch merge (#3371)
* Bump dates on sql migration scripts
* Bump date on ef migrations
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
Co-authored-by: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com>
Co-authored-by: Vincent Salucci <vincesalucci21@gmail.com>
Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
2023-11-01 19:30:52 +10:00
if ( permissions = = null | | await _currentContext . OrganizationAdmin ( organizationId ) )
2023-05-17 14:17:37 +01:00
{
return true ;
}
if ( permissions . ManageUsers & & ! await _currentContext . ManageUsers ( organizationId ) )
{
return false ;
}
if ( permissions . AccessReports & & ! await _currentContext . AccessReports ( organizationId ) )
{
return false ;
}
if ( permissions . ManageGroups & & ! await _currentContext . ManageGroups ( organizationId ) )
{
return false ;
}
if ( permissions . ManagePolicies & & ! await _currentContext . ManagePolicies ( organizationId ) )
{
return false ;
}
if ( permissions . ManageScim & & ! await _currentContext . ManageScim ( organizationId ) )
{
return false ;
}
if ( permissions . ManageSso & & ! await _currentContext . ManageSso ( organizationId ) )
{
return false ;
}
if ( permissions . AccessEventLogs & & ! await _currentContext . AccessEventLogs ( organizationId ) )
{
return false ;
}
if ( permissions . AccessImportExport & & ! await _currentContext . AccessImportExport ( organizationId ) )
{
return false ;
}
[AC-1373] Flexible Collections (#3245)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* fix: merge conflict resolution
* [AC-1174] CollectionUser and CollectionGroup authorization handlers (#3194)
* [AC-1174] Introduce BulkAuthorizationHandler.cs
* [AC-1174] Introduce CollectionUserAuthorizationHandler
* [AC-1174] Add CreateForNewCollection CollectionUser requirement
* [AC-1174] Add some more details to CollectionCustomization
* [AC-1174] Formatting
* [AC-1174] Add CollectionGroupOperation.cs
* [AC-1174] Introduce CollectionGroupAuthorizationHandler.cs
* [AC-1174] Cleanup CollectionFixture customization
Implement and use re-usable extension method to support seeded Guids
* [AC-1174] Introduce WithValueFromList AutoFixtureExtensions
Modify CollectionCustomization to use multiple organization Ids for auto generated test data
* [AC-1174] Simplify CollectionUserAuthorizationHandler.cs
Modify the authorization handler to only perform authorization logic. Validation logic will need to be handled by any calling commands/controllers instead.
* [AC-1174] Introduce shared CollectionAccessAuthorizationHandlerBase
A shared base authorization handler was created for both CollectionUser and CollectionGroup resources, as they share the same underlying management authorization logic.
* [AC-1174] Update CollectionUserAuthorizationHandler and CollectionGroupAuthorizationHandler to use the new CollectionAccessAuthorizationHandlerBase class
* [AC-1174] Formatting
* [AC-1174] Cleanup typo and redundant ToList() call
* [AC-1174] Add check for provider users
* [AC-1174] Reduce nested loops
* [AC-1174] Introduce ICollectionAccess.cs
* [AC-1174] Remove individual CollectionGroup and CollectionUser auth handlers and use base class instead
* [AC-1174] Tweak unit test to fail minimally
* [AC-1174] Reorganize authorization handlers in Core project
* [AC-1174] Introduce new AddCoreAuthorizationHandlers() extension method
* [AC-1174] Move CollectionAccessAuthorizationHandler into Api project
* [AC-1174] Move CollectionFixture to Vault folder
* [AC-1174] Rename operation to CreateUpdateDelete
* [AC-1174] Require single organization for collection access authorization handler
- Add requirement that all target collections must belong to the same organization
- Simplify logic related to multiple organizations
- Update tests and helpers
- Use ToHashSet to improve lookup time
* [AC-1174] Fix null reference exception
* [AC-1174] Throw bad request exception when collections belong to different organizations
* [AC-1174] Switch to CollectionAuthorizationHandler instead of CollectionAccessAuthorizationHandler to reduce complexity
* Fix improper merge conflict resolution
* fix: add permission check for collection management api, refs AC-1647 (#3252)
* [AC-1125] Enforce org setting for creating/deleting collections (#3241)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* feat: created collection auth handler/operations, added LimitCollectionCdOwnerAdmin to CurrentContentOrganization, refs AC-1125
* feat: create vault service collection extensions and register with base services, refs AC-1125
* feat: deprecated CurrentContext.CreateNewCollections, refs AC-1125
* feat: deprecate DeleteAnyCollection for single resource usages, refs AC-1125
* feat: move service registration to api, update references, refs AC-1125
* feat: add bulk delete authorization handler, refs AC-1125
* feat: always assign user and give manage access on create, refs AC-1125
* fix: updated CurrentContextOrganization type, refs AC-1125
* feat: combined existing collection authorization handlers/operations, refs AC-1125
* fix: OrganizationServiceTests -> CurrentContentOrganization typo, refs AC-1125
* fix: format, refs AC-1125
* fix: update collection controller tests, refs AC-1125
* fix: dotnet format, refs AC-1125
* feat: removed extra BulkAuthorizationHandler, refs AC-1125
* fix: dotnet format, refs AC-1125
* fix: change string to guid for org id, update bulk delete request model, refs AC-1125
* fix: remove delete many collection check, refs AC-1125
* fix: clean up collection auth handler, refs AC-1125
* fix: format fix for CollectionOperations, refs AC-1125
* fix: removed unnecessary owner check, add org null check to custom permission validation, refs AC-1125
* fix: remove unused methods in CurrentContext, refs AC-1125
* fix: removed obsolete test, fixed failling delete many test, refs AC-1125
* fix: CollectionAuthorizationHandlerTests fixes, refs AC-1125
* fix: OrganizationServiceTests fix broken test by mocking GetOrganization, refs AC-1125
* fix: CollectionAuthorizationHandler - remove unused repository, refs AC-1125
* feat: moved UserId null check to common method, refs AC-1125
* fix: updated auth handler tests to remove dependency on requirement for common code checks, refs AC-1125
* feat: updated conditionals/comments for create/delete methods within colleciton auth handler, refs AC-1125
* feat: added create/delete collection auth handler success methods, refs AC-1125
* fix: new up permissions to prevent excessive null checks, refs AC-1125
* fix: remove old reference to CreateNewCollections, refs AC-1125
* fix: typo within ViewAssignedCollections method, refs AC-1125
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
* refactor: remove organizationId from CollectionBulkDeleteRequestModel, refs AC-1649 (#3282)
* [AC-1174] Bulk Collection Management (#3229)
* [AC-1174] Update SelectionReadOnlyRequestModel to use Guid for Id property
* [AC-1174] Introduce initial bulk-access collection endpoint
* [AC-1174] Introduce BulkAddCollectionAccessCommand and validation logic/tests
* [AC-1174] Add CreateOrUpdateAccessMany method to CollectionRepository
* [AC-1174] Add event logs for bulk add collection access command
* [AC-1174] Add User_BumpAccountRevisionDateByCollectionIds and database migration script
* [AC-1174] Implement EF repository method
* [AC-1174] Improve null checks
* [AC-1174] Remove unnecessary BulkCollectionAccessRequestModel helpers
* [AC-1174] Add unit tests for new controller endpoint
* [AC-1174] Fix formatting
* [AC-1174] Remove comment
* [AC-1174] Remove redundant organizationId parameter
* [AC-1174] Ensure user and group Ids are distinct
* [AC-1174] Cleanup tests based on PR feedback
* [AC-1174] Formatting
* [AC-1174] Update CollectionGroup alias in the sproc
* [AC-1174] Add some additional comments to SQL sproc
* [AC-1174] Add comment explaining additional SaveChangesAsync call
---------
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
* [AC-1646] Rename LimitCollectionCdOwnerAdmin column (#3300)
* Rename LimitCollectionCdOwnerAdmin -> LimitCollectionCreationDeletion
* Rename and bump migration script
* [AC-1666] Removed EditAnyCollection from Create/Delete permission checks (#3301)
* fix: remove EditAnyCollection from Create/Delete permission check, refs AC-1666
* fix: updated comment, refs AC-1666
* [AC-1669] Bug - Remove obsolete assignUserId from CollectionService.SaveAsync(...) (#3312)
* fix: remove AssignUserId from CollectionService.SaveAsync, refs AC-1669
* fix: add manage access conditional before creating collection, refs AC-1669
* fix: move access logic for create/update, fix all tests, refs AC-1669
* fix: add CollectionAccessSelection fixture, update tests, update bad reqeuest message, refs AC-1669
* fix: format, refs AC-1669
* fix: update null params with specific arg.is null checks, refs Ac-1669
* fix: update attribute class name, refs AC-1669
* [AC-1713] [Flexible collections] Add feature flags to server (#3334)
* Add feature flags for FlexibleCollections and BulkCollectionAccess
* Flag new routes and behaviour
---------
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
* Add joint codeownership for auth handlers (#3346)
* [AC-1717] Update default values for LimitCollectionCreationDeletion (#3365)
* Change default value in organization create sproc to 1
* Drop old column name still present in some QA instances
* Set LimitCollectionCreationDeletion value in code based on feature flag
* Fix: add missing namespace after merging in master
* Fix: add missing namespace after merging in master
* [AC-1683] Fix DB migrations for new Manage permission (#3307)
* [AC-1683] Update migration script and introduce V2 procedures and types
* [AC-1683] Update repository calls to use new V2 procedures / types
* [AC-1684] Update bulk add collection migration script to use new V2 type
* [AC-1683] Undo Manage changes to more original procedures
* [AC-1683] Restore whitespace changes
* [AC-1683] Clarify comments regarding explicit column lists
* [AC-1683] Update migration script dates
* [AC-1683] Split the migration script for readability
* [AC-1683] Re-name SelectReadOnlyArray_V2 to CollectionAccessSelectionType
* [AC-1648] [Flexible Collections] Bump migration scripts before feature branch merge (#3371)
* Bump dates on sql migration scripts
* Bump date on ef migrations
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
Co-authored-by: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com>
Co-authored-by: Vincent Salucci <vincesalucci21@gmail.com>
Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
2023-11-01 19:30:52 +10:00
if ( permissions . DeleteAssignedCollections & & ! await _currentContext . DeleteAssignedCollections ( organizationId ) )
2023-05-17 14:17:37 +01:00
{
return false ;
}
[AC-1373] Flexible Collections (#3245)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* fix: merge conflict resolution
* [AC-1174] CollectionUser and CollectionGroup authorization handlers (#3194)
* [AC-1174] Introduce BulkAuthorizationHandler.cs
* [AC-1174] Introduce CollectionUserAuthorizationHandler
* [AC-1174] Add CreateForNewCollection CollectionUser requirement
* [AC-1174] Add some more details to CollectionCustomization
* [AC-1174] Formatting
* [AC-1174] Add CollectionGroupOperation.cs
* [AC-1174] Introduce CollectionGroupAuthorizationHandler.cs
* [AC-1174] Cleanup CollectionFixture customization
Implement and use re-usable extension method to support seeded Guids
* [AC-1174] Introduce WithValueFromList AutoFixtureExtensions
Modify CollectionCustomization to use multiple organization Ids for auto generated test data
* [AC-1174] Simplify CollectionUserAuthorizationHandler.cs
Modify the authorization handler to only perform authorization logic. Validation logic will need to be handled by any calling commands/controllers instead.
* [AC-1174] Introduce shared CollectionAccessAuthorizationHandlerBase
A shared base authorization handler was created for both CollectionUser and CollectionGroup resources, as they share the same underlying management authorization logic.
* [AC-1174] Update CollectionUserAuthorizationHandler and CollectionGroupAuthorizationHandler to use the new CollectionAccessAuthorizationHandlerBase class
* [AC-1174] Formatting
* [AC-1174] Cleanup typo and redundant ToList() call
* [AC-1174] Add check for provider users
* [AC-1174] Reduce nested loops
* [AC-1174] Introduce ICollectionAccess.cs
* [AC-1174] Remove individual CollectionGroup and CollectionUser auth handlers and use base class instead
* [AC-1174] Tweak unit test to fail minimally
* [AC-1174] Reorganize authorization handlers in Core project
* [AC-1174] Introduce new AddCoreAuthorizationHandlers() extension method
* [AC-1174] Move CollectionAccessAuthorizationHandler into Api project
* [AC-1174] Move CollectionFixture to Vault folder
* [AC-1174] Rename operation to CreateUpdateDelete
* [AC-1174] Require single organization for collection access authorization handler
- Add requirement that all target collections must belong to the same organization
- Simplify logic related to multiple organizations
- Update tests and helpers
- Use ToHashSet to improve lookup time
* [AC-1174] Fix null reference exception
* [AC-1174] Throw bad request exception when collections belong to different organizations
* [AC-1174] Switch to CollectionAuthorizationHandler instead of CollectionAccessAuthorizationHandler to reduce complexity
* Fix improper merge conflict resolution
* fix: add permission check for collection management api, refs AC-1647 (#3252)
* [AC-1125] Enforce org setting for creating/deleting collections (#3241)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* feat: created collection auth handler/operations, added LimitCollectionCdOwnerAdmin to CurrentContentOrganization, refs AC-1125
* feat: create vault service collection extensions and register with base services, refs AC-1125
* feat: deprecated CurrentContext.CreateNewCollections, refs AC-1125
* feat: deprecate DeleteAnyCollection for single resource usages, refs AC-1125
* feat: move service registration to api, update references, refs AC-1125
* feat: add bulk delete authorization handler, refs AC-1125
* feat: always assign user and give manage access on create, refs AC-1125
* fix: updated CurrentContextOrganization type, refs AC-1125
* feat: combined existing collection authorization handlers/operations, refs AC-1125
* fix: OrganizationServiceTests -> CurrentContentOrganization typo, refs AC-1125
* fix: format, refs AC-1125
* fix: update collection controller tests, refs AC-1125
* fix: dotnet format, refs AC-1125
* feat: removed extra BulkAuthorizationHandler, refs AC-1125
* fix: dotnet format, refs AC-1125
* fix: change string to guid for org id, update bulk delete request model, refs AC-1125
* fix: remove delete many collection check, refs AC-1125
* fix: clean up collection auth handler, refs AC-1125
* fix: format fix for CollectionOperations, refs AC-1125
* fix: removed unnecessary owner check, add org null check to custom permission validation, refs AC-1125
* fix: remove unused methods in CurrentContext, refs AC-1125
* fix: removed obsolete test, fixed failling delete many test, refs AC-1125
* fix: CollectionAuthorizationHandlerTests fixes, refs AC-1125
* fix: OrganizationServiceTests fix broken test by mocking GetOrganization, refs AC-1125
* fix: CollectionAuthorizationHandler - remove unused repository, refs AC-1125
* feat: moved UserId null check to common method, refs AC-1125
* fix: updated auth handler tests to remove dependency on requirement for common code checks, refs AC-1125
* feat: updated conditionals/comments for create/delete methods within colleciton auth handler, refs AC-1125
* feat: added create/delete collection auth handler success methods, refs AC-1125
* fix: new up permissions to prevent excessive null checks, refs AC-1125
* fix: remove old reference to CreateNewCollections, refs AC-1125
* fix: typo within ViewAssignedCollections method, refs AC-1125
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
* refactor: remove organizationId from CollectionBulkDeleteRequestModel, refs AC-1649 (#3282)
* [AC-1174] Bulk Collection Management (#3229)
* [AC-1174] Update SelectionReadOnlyRequestModel to use Guid for Id property
* [AC-1174] Introduce initial bulk-access collection endpoint
* [AC-1174] Introduce BulkAddCollectionAccessCommand and validation logic/tests
* [AC-1174] Add CreateOrUpdateAccessMany method to CollectionRepository
* [AC-1174] Add event logs for bulk add collection access command
* [AC-1174] Add User_BumpAccountRevisionDateByCollectionIds and database migration script
* [AC-1174] Implement EF repository method
* [AC-1174] Improve null checks
* [AC-1174] Remove unnecessary BulkCollectionAccessRequestModel helpers
* [AC-1174] Add unit tests for new controller endpoint
* [AC-1174] Fix formatting
* [AC-1174] Remove comment
* [AC-1174] Remove redundant organizationId parameter
* [AC-1174] Ensure user and group Ids are distinct
* [AC-1174] Cleanup tests based on PR feedback
* [AC-1174] Formatting
* [AC-1174] Update CollectionGroup alias in the sproc
* [AC-1174] Add some additional comments to SQL sproc
* [AC-1174] Add comment explaining additional SaveChangesAsync call
---------
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
* [AC-1646] Rename LimitCollectionCdOwnerAdmin column (#3300)
* Rename LimitCollectionCdOwnerAdmin -> LimitCollectionCreationDeletion
* Rename and bump migration script
* [AC-1666] Removed EditAnyCollection from Create/Delete permission checks (#3301)
* fix: remove EditAnyCollection from Create/Delete permission check, refs AC-1666
* fix: updated comment, refs AC-1666
* [AC-1669] Bug - Remove obsolete assignUserId from CollectionService.SaveAsync(...) (#3312)
* fix: remove AssignUserId from CollectionService.SaveAsync, refs AC-1669
* fix: add manage access conditional before creating collection, refs AC-1669
* fix: move access logic for create/update, fix all tests, refs AC-1669
* fix: add CollectionAccessSelection fixture, update tests, update bad reqeuest message, refs AC-1669
* fix: format, refs AC-1669
* fix: update null params with specific arg.is null checks, refs Ac-1669
* fix: update attribute class name, refs AC-1669
* [AC-1713] [Flexible collections] Add feature flags to server (#3334)
* Add feature flags for FlexibleCollections and BulkCollectionAccess
* Flag new routes and behaviour
---------
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
* Add joint codeownership for auth handlers (#3346)
* [AC-1717] Update default values for LimitCollectionCreationDeletion (#3365)
* Change default value in organization create sproc to 1
* Drop old column name still present in some QA instances
* Set LimitCollectionCreationDeletion value in code based on feature flag
* Fix: add missing namespace after merging in master
* Fix: add missing namespace after merging in master
* [AC-1683] Fix DB migrations for new Manage permission (#3307)
* [AC-1683] Update migration script and introduce V2 procedures and types
* [AC-1683] Update repository calls to use new V2 procedures / types
* [AC-1684] Update bulk add collection migration script to use new V2 type
* [AC-1683] Undo Manage changes to more original procedures
* [AC-1683] Restore whitespace changes
* [AC-1683] Clarify comments regarding explicit column lists
* [AC-1683] Update migration script dates
* [AC-1683] Split the migration script for readability
* [AC-1683] Re-name SelectReadOnlyArray_V2 to CollectionAccessSelectionType
* [AC-1648] [Flexible Collections] Bump migration scripts before feature branch merge (#3371)
* Bump dates on sql migration scripts
* Bump date on ef migrations
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
Co-authored-by: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com>
Co-authored-by: Vincent Salucci <vincesalucci21@gmail.com>
Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
2023-11-01 19:30:52 +10:00
if ( permissions . EditAnyCollection & & ! await _currentContext . EditAnyCollection ( organizationId ) )
2023-05-17 14:17:37 +01:00
{
return false ;
}
[AC-1373] Flexible Collections (#3245)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* fix: merge conflict resolution
* [AC-1174] CollectionUser and CollectionGroup authorization handlers (#3194)
* [AC-1174] Introduce BulkAuthorizationHandler.cs
* [AC-1174] Introduce CollectionUserAuthorizationHandler
* [AC-1174] Add CreateForNewCollection CollectionUser requirement
* [AC-1174] Add some more details to CollectionCustomization
* [AC-1174] Formatting
* [AC-1174] Add CollectionGroupOperation.cs
* [AC-1174] Introduce CollectionGroupAuthorizationHandler.cs
* [AC-1174] Cleanup CollectionFixture customization
Implement and use re-usable extension method to support seeded Guids
* [AC-1174] Introduce WithValueFromList AutoFixtureExtensions
Modify CollectionCustomization to use multiple organization Ids for auto generated test data
* [AC-1174] Simplify CollectionUserAuthorizationHandler.cs
Modify the authorization handler to only perform authorization logic. Validation logic will need to be handled by any calling commands/controllers instead.
* [AC-1174] Introduce shared CollectionAccessAuthorizationHandlerBase
A shared base authorization handler was created for both CollectionUser and CollectionGroup resources, as they share the same underlying management authorization logic.
* [AC-1174] Update CollectionUserAuthorizationHandler and CollectionGroupAuthorizationHandler to use the new CollectionAccessAuthorizationHandlerBase class
* [AC-1174] Formatting
* [AC-1174] Cleanup typo and redundant ToList() call
* [AC-1174] Add check for provider users
* [AC-1174] Reduce nested loops
* [AC-1174] Introduce ICollectionAccess.cs
* [AC-1174] Remove individual CollectionGroup and CollectionUser auth handlers and use base class instead
* [AC-1174] Tweak unit test to fail minimally
* [AC-1174] Reorganize authorization handlers in Core project
* [AC-1174] Introduce new AddCoreAuthorizationHandlers() extension method
* [AC-1174] Move CollectionAccessAuthorizationHandler into Api project
* [AC-1174] Move CollectionFixture to Vault folder
* [AC-1174] Rename operation to CreateUpdateDelete
* [AC-1174] Require single organization for collection access authorization handler
- Add requirement that all target collections must belong to the same organization
- Simplify logic related to multiple organizations
- Update tests and helpers
- Use ToHashSet to improve lookup time
* [AC-1174] Fix null reference exception
* [AC-1174] Throw bad request exception when collections belong to different organizations
* [AC-1174] Switch to CollectionAuthorizationHandler instead of CollectionAccessAuthorizationHandler to reduce complexity
* Fix improper merge conflict resolution
* fix: add permission check for collection management api, refs AC-1647 (#3252)
* [AC-1125] Enforce org setting for creating/deleting collections (#3241)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* feat: created collection auth handler/operations, added LimitCollectionCdOwnerAdmin to CurrentContentOrganization, refs AC-1125
* feat: create vault service collection extensions and register with base services, refs AC-1125
* feat: deprecated CurrentContext.CreateNewCollections, refs AC-1125
* feat: deprecate DeleteAnyCollection for single resource usages, refs AC-1125
* feat: move service registration to api, update references, refs AC-1125
* feat: add bulk delete authorization handler, refs AC-1125
* feat: always assign user and give manage access on create, refs AC-1125
* fix: updated CurrentContextOrganization type, refs AC-1125
* feat: combined existing collection authorization handlers/operations, refs AC-1125
* fix: OrganizationServiceTests -> CurrentContentOrganization typo, refs AC-1125
* fix: format, refs AC-1125
* fix: update collection controller tests, refs AC-1125
* fix: dotnet format, refs AC-1125
* feat: removed extra BulkAuthorizationHandler, refs AC-1125
* fix: dotnet format, refs AC-1125
* fix: change string to guid for org id, update bulk delete request model, refs AC-1125
* fix: remove delete many collection check, refs AC-1125
* fix: clean up collection auth handler, refs AC-1125
* fix: format fix for CollectionOperations, refs AC-1125
* fix: removed unnecessary owner check, add org null check to custom permission validation, refs AC-1125
* fix: remove unused methods in CurrentContext, refs AC-1125
* fix: removed obsolete test, fixed failling delete many test, refs AC-1125
* fix: CollectionAuthorizationHandlerTests fixes, refs AC-1125
* fix: OrganizationServiceTests fix broken test by mocking GetOrganization, refs AC-1125
* fix: CollectionAuthorizationHandler - remove unused repository, refs AC-1125
* feat: moved UserId null check to common method, refs AC-1125
* fix: updated auth handler tests to remove dependency on requirement for common code checks, refs AC-1125
* feat: updated conditionals/comments for create/delete methods within colleciton auth handler, refs AC-1125
* feat: added create/delete collection auth handler success methods, refs AC-1125
* fix: new up permissions to prevent excessive null checks, refs AC-1125
* fix: remove old reference to CreateNewCollections, refs AC-1125
* fix: typo within ViewAssignedCollections method, refs AC-1125
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
* refactor: remove organizationId from CollectionBulkDeleteRequestModel, refs AC-1649 (#3282)
* [AC-1174] Bulk Collection Management (#3229)
* [AC-1174] Update SelectionReadOnlyRequestModel to use Guid for Id property
* [AC-1174] Introduce initial bulk-access collection endpoint
* [AC-1174] Introduce BulkAddCollectionAccessCommand and validation logic/tests
* [AC-1174] Add CreateOrUpdateAccessMany method to CollectionRepository
* [AC-1174] Add event logs for bulk add collection access command
* [AC-1174] Add User_BumpAccountRevisionDateByCollectionIds and database migration script
* [AC-1174] Implement EF repository method
* [AC-1174] Improve null checks
* [AC-1174] Remove unnecessary BulkCollectionAccessRequestModel helpers
* [AC-1174] Add unit tests for new controller endpoint
* [AC-1174] Fix formatting
* [AC-1174] Remove comment
* [AC-1174] Remove redundant organizationId parameter
* [AC-1174] Ensure user and group Ids are distinct
* [AC-1174] Cleanup tests based on PR feedback
* [AC-1174] Formatting
* [AC-1174] Update CollectionGroup alias in the sproc
* [AC-1174] Add some additional comments to SQL sproc
* [AC-1174] Add comment explaining additional SaveChangesAsync call
---------
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
* [AC-1646] Rename LimitCollectionCdOwnerAdmin column (#3300)
* Rename LimitCollectionCdOwnerAdmin -> LimitCollectionCreationDeletion
* Rename and bump migration script
* [AC-1666] Removed EditAnyCollection from Create/Delete permission checks (#3301)
* fix: remove EditAnyCollection from Create/Delete permission check, refs AC-1666
* fix: updated comment, refs AC-1666
* [AC-1669] Bug - Remove obsolete assignUserId from CollectionService.SaveAsync(...) (#3312)
* fix: remove AssignUserId from CollectionService.SaveAsync, refs AC-1669
* fix: add manage access conditional before creating collection, refs AC-1669
* fix: move access logic for create/update, fix all tests, refs AC-1669
* fix: add CollectionAccessSelection fixture, update tests, update bad reqeuest message, refs AC-1669
* fix: format, refs AC-1669
* fix: update null params with specific arg.is null checks, refs Ac-1669
* fix: update attribute class name, refs AC-1669
* [AC-1713] [Flexible collections] Add feature flags to server (#3334)
* Add feature flags for FlexibleCollections and BulkCollectionAccess
* Flag new routes and behaviour
---------
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
* Add joint codeownership for auth handlers (#3346)
* [AC-1717] Update default values for LimitCollectionCreationDeletion (#3365)
* Change default value in organization create sproc to 1
* Drop old column name still present in some QA instances
* Set LimitCollectionCreationDeletion value in code based on feature flag
* Fix: add missing namespace after merging in master
* Fix: add missing namespace after merging in master
* [AC-1683] Fix DB migrations for new Manage permission (#3307)
* [AC-1683] Update migration script and introduce V2 procedures and types
* [AC-1683] Update repository calls to use new V2 procedures / types
* [AC-1684] Update bulk add collection migration script to use new V2 type
* [AC-1683] Undo Manage changes to more original procedures
* [AC-1683] Restore whitespace changes
* [AC-1683] Clarify comments regarding explicit column lists
* [AC-1683] Update migration script dates
* [AC-1683] Split the migration script for readability
* [AC-1683] Re-name SelectReadOnlyArray_V2 to CollectionAccessSelectionType
* [AC-1648] [Flexible Collections] Bump migration scripts before feature branch merge (#3371)
* Bump dates on sql migration scripts
* Bump date on ef migrations
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
Co-authored-by: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com>
Co-authored-by: Vincent Salucci <vincesalucci21@gmail.com>
Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
2023-11-01 19:30:52 +10:00
if ( permissions . EditAssignedCollections & & ! await _currentContext . EditAssignedCollections ( organizationId ) )
2023-05-17 14:17:37 +01:00
{
return false ;
}
[AC-1373] Flexible Collections (#3245)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* fix: merge conflict resolution
* [AC-1174] CollectionUser and CollectionGroup authorization handlers (#3194)
* [AC-1174] Introduce BulkAuthorizationHandler.cs
* [AC-1174] Introduce CollectionUserAuthorizationHandler
* [AC-1174] Add CreateForNewCollection CollectionUser requirement
* [AC-1174] Add some more details to CollectionCustomization
* [AC-1174] Formatting
* [AC-1174] Add CollectionGroupOperation.cs
* [AC-1174] Introduce CollectionGroupAuthorizationHandler.cs
* [AC-1174] Cleanup CollectionFixture customization
Implement and use re-usable extension method to support seeded Guids
* [AC-1174] Introduce WithValueFromList AutoFixtureExtensions
Modify CollectionCustomization to use multiple organization Ids for auto generated test data
* [AC-1174] Simplify CollectionUserAuthorizationHandler.cs
Modify the authorization handler to only perform authorization logic. Validation logic will need to be handled by any calling commands/controllers instead.
* [AC-1174] Introduce shared CollectionAccessAuthorizationHandlerBase
A shared base authorization handler was created for both CollectionUser and CollectionGroup resources, as they share the same underlying management authorization logic.
* [AC-1174] Update CollectionUserAuthorizationHandler and CollectionGroupAuthorizationHandler to use the new CollectionAccessAuthorizationHandlerBase class
* [AC-1174] Formatting
* [AC-1174] Cleanup typo and redundant ToList() call
* [AC-1174] Add check for provider users
* [AC-1174] Reduce nested loops
* [AC-1174] Introduce ICollectionAccess.cs
* [AC-1174] Remove individual CollectionGroup and CollectionUser auth handlers and use base class instead
* [AC-1174] Tweak unit test to fail minimally
* [AC-1174] Reorganize authorization handlers in Core project
* [AC-1174] Introduce new AddCoreAuthorizationHandlers() extension method
* [AC-1174] Move CollectionAccessAuthorizationHandler into Api project
* [AC-1174] Move CollectionFixture to Vault folder
* [AC-1174] Rename operation to CreateUpdateDelete
* [AC-1174] Require single organization for collection access authorization handler
- Add requirement that all target collections must belong to the same organization
- Simplify logic related to multiple organizations
- Update tests and helpers
- Use ToHashSet to improve lookup time
* [AC-1174] Fix null reference exception
* [AC-1174] Throw bad request exception when collections belong to different organizations
* [AC-1174] Switch to CollectionAuthorizationHandler instead of CollectionAccessAuthorizationHandler to reduce complexity
* Fix improper merge conflict resolution
* fix: add permission check for collection management api, refs AC-1647 (#3252)
* [AC-1125] Enforce org setting for creating/deleting collections (#3241)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* feat: created collection auth handler/operations, added LimitCollectionCdOwnerAdmin to CurrentContentOrganization, refs AC-1125
* feat: create vault service collection extensions and register with base services, refs AC-1125
* feat: deprecated CurrentContext.CreateNewCollections, refs AC-1125
* feat: deprecate DeleteAnyCollection for single resource usages, refs AC-1125
* feat: move service registration to api, update references, refs AC-1125
* feat: add bulk delete authorization handler, refs AC-1125
* feat: always assign user and give manage access on create, refs AC-1125
* fix: updated CurrentContextOrganization type, refs AC-1125
* feat: combined existing collection authorization handlers/operations, refs AC-1125
* fix: OrganizationServiceTests -> CurrentContentOrganization typo, refs AC-1125
* fix: format, refs AC-1125
* fix: update collection controller tests, refs AC-1125
* fix: dotnet format, refs AC-1125
* feat: removed extra BulkAuthorizationHandler, refs AC-1125
* fix: dotnet format, refs AC-1125
* fix: change string to guid for org id, update bulk delete request model, refs AC-1125
* fix: remove delete many collection check, refs AC-1125
* fix: clean up collection auth handler, refs AC-1125
* fix: format fix for CollectionOperations, refs AC-1125
* fix: removed unnecessary owner check, add org null check to custom permission validation, refs AC-1125
* fix: remove unused methods in CurrentContext, refs AC-1125
* fix: removed obsolete test, fixed failling delete many test, refs AC-1125
* fix: CollectionAuthorizationHandlerTests fixes, refs AC-1125
* fix: OrganizationServiceTests fix broken test by mocking GetOrganization, refs AC-1125
* fix: CollectionAuthorizationHandler - remove unused repository, refs AC-1125
* feat: moved UserId null check to common method, refs AC-1125
* fix: updated auth handler tests to remove dependency on requirement for common code checks, refs AC-1125
* feat: updated conditionals/comments for create/delete methods within colleciton auth handler, refs AC-1125
* feat: added create/delete collection auth handler success methods, refs AC-1125
* fix: new up permissions to prevent excessive null checks, refs AC-1125
* fix: remove old reference to CreateNewCollections, refs AC-1125
* fix: typo within ViewAssignedCollections method, refs AC-1125
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
* refactor: remove organizationId from CollectionBulkDeleteRequestModel, refs AC-1649 (#3282)
* [AC-1174] Bulk Collection Management (#3229)
* [AC-1174] Update SelectionReadOnlyRequestModel to use Guid for Id property
* [AC-1174] Introduce initial bulk-access collection endpoint
* [AC-1174] Introduce BulkAddCollectionAccessCommand and validation logic/tests
* [AC-1174] Add CreateOrUpdateAccessMany method to CollectionRepository
* [AC-1174] Add event logs for bulk add collection access command
* [AC-1174] Add User_BumpAccountRevisionDateByCollectionIds and database migration script
* [AC-1174] Implement EF repository method
* [AC-1174] Improve null checks
* [AC-1174] Remove unnecessary BulkCollectionAccessRequestModel helpers
* [AC-1174] Add unit tests for new controller endpoint
* [AC-1174] Fix formatting
* [AC-1174] Remove comment
* [AC-1174] Remove redundant organizationId parameter
* [AC-1174] Ensure user and group Ids are distinct
* [AC-1174] Cleanup tests based on PR feedback
* [AC-1174] Formatting
* [AC-1174] Update CollectionGroup alias in the sproc
* [AC-1174] Add some additional comments to SQL sproc
* [AC-1174] Add comment explaining additional SaveChangesAsync call
---------
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
* [AC-1646] Rename LimitCollectionCdOwnerAdmin column (#3300)
* Rename LimitCollectionCdOwnerAdmin -> LimitCollectionCreationDeletion
* Rename and bump migration script
* [AC-1666] Removed EditAnyCollection from Create/Delete permission checks (#3301)
* fix: remove EditAnyCollection from Create/Delete permission check, refs AC-1666
* fix: updated comment, refs AC-1666
* [AC-1669] Bug - Remove obsolete assignUserId from CollectionService.SaveAsync(...) (#3312)
* fix: remove AssignUserId from CollectionService.SaveAsync, refs AC-1669
* fix: add manage access conditional before creating collection, refs AC-1669
* fix: move access logic for create/update, fix all tests, refs AC-1669
* fix: add CollectionAccessSelection fixture, update tests, update bad reqeuest message, refs AC-1669
* fix: format, refs AC-1669
* fix: update null params with specific arg.is null checks, refs Ac-1669
* fix: update attribute class name, refs AC-1669
* [AC-1713] [Flexible collections] Add feature flags to server (#3334)
* Add feature flags for FlexibleCollections and BulkCollectionAccess
* Flag new routes and behaviour
---------
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
* Add joint codeownership for auth handlers (#3346)
* [AC-1717] Update default values for LimitCollectionCreationDeletion (#3365)
* Change default value in organization create sproc to 1
* Drop old column name still present in some QA instances
* Set LimitCollectionCreationDeletion value in code based on feature flag
* Fix: add missing namespace after merging in master
* Fix: add missing namespace after merging in master
* [AC-1683] Fix DB migrations for new Manage permission (#3307)
* [AC-1683] Update migration script and introduce V2 procedures and types
* [AC-1683] Update repository calls to use new V2 procedures / types
* [AC-1684] Update bulk add collection migration script to use new V2 type
* [AC-1683] Undo Manage changes to more original procedures
* [AC-1683] Restore whitespace changes
* [AC-1683] Clarify comments regarding explicit column lists
* [AC-1683] Update migration script dates
* [AC-1683] Split the migration script for readability
* [AC-1683] Re-name SelectReadOnlyArray_V2 to CollectionAccessSelectionType
* [AC-1648] [Flexible Collections] Bump migration scripts before feature branch merge (#3371)
* Bump dates on sql migration scripts
* Bump date on ef migrations
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
Co-authored-by: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com>
Co-authored-by: Vincent Salucci <vincesalucci21@gmail.com>
Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
2023-11-01 19:30:52 +10:00
if ( permissions . ManageResetPassword & & ! await _currentContext . ManageResetPassword ( organizationId ) )
2023-05-17 14:17:37 +01:00
{
return false ;
}
[AC-1373] Flexible Collections (#3245)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* fix: merge conflict resolution
* [AC-1174] CollectionUser and CollectionGroup authorization handlers (#3194)
* [AC-1174] Introduce BulkAuthorizationHandler.cs
* [AC-1174] Introduce CollectionUserAuthorizationHandler
* [AC-1174] Add CreateForNewCollection CollectionUser requirement
* [AC-1174] Add some more details to CollectionCustomization
* [AC-1174] Formatting
* [AC-1174] Add CollectionGroupOperation.cs
* [AC-1174] Introduce CollectionGroupAuthorizationHandler.cs
* [AC-1174] Cleanup CollectionFixture customization
Implement and use re-usable extension method to support seeded Guids
* [AC-1174] Introduce WithValueFromList AutoFixtureExtensions
Modify CollectionCustomization to use multiple organization Ids for auto generated test data
* [AC-1174] Simplify CollectionUserAuthorizationHandler.cs
Modify the authorization handler to only perform authorization logic. Validation logic will need to be handled by any calling commands/controllers instead.
* [AC-1174] Introduce shared CollectionAccessAuthorizationHandlerBase
A shared base authorization handler was created for both CollectionUser and CollectionGroup resources, as they share the same underlying management authorization logic.
* [AC-1174] Update CollectionUserAuthorizationHandler and CollectionGroupAuthorizationHandler to use the new CollectionAccessAuthorizationHandlerBase class
* [AC-1174] Formatting
* [AC-1174] Cleanup typo and redundant ToList() call
* [AC-1174] Add check for provider users
* [AC-1174] Reduce nested loops
* [AC-1174] Introduce ICollectionAccess.cs
* [AC-1174] Remove individual CollectionGroup and CollectionUser auth handlers and use base class instead
* [AC-1174] Tweak unit test to fail minimally
* [AC-1174] Reorganize authorization handlers in Core project
* [AC-1174] Introduce new AddCoreAuthorizationHandlers() extension method
* [AC-1174] Move CollectionAccessAuthorizationHandler into Api project
* [AC-1174] Move CollectionFixture to Vault folder
* [AC-1174] Rename operation to CreateUpdateDelete
* [AC-1174] Require single organization for collection access authorization handler
- Add requirement that all target collections must belong to the same organization
- Simplify logic related to multiple organizations
- Update tests and helpers
- Use ToHashSet to improve lookup time
* [AC-1174] Fix null reference exception
* [AC-1174] Throw bad request exception when collections belong to different organizations
* [AC-1174] Switch to CollectionAuthorizationHandler instead of CollectionAccessAuthorizationHandler to reduce complexity
* Fix improper merge conflict resolution
* fix: add permission check for collection management api, refs AC-1647 (#3252)
* [AC-1125] Enforce org setting for creating/deleting collections (#3241)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* feat: created collection auth handler/operations, added LimitCollectionCdOwnerAdmin to CurrentContentOrganization, refs AC-1125
* feat: create vault service collection extensions and register with base services, refs AC-1125
* feat: deprecated CurrentContext.CreateNewCollections, refs AC-1125
* feat: deprecate DeleteAnyCollection for single resource usages, refs AC-1125
* feat: move service registration to api, update references, refs AC-1125
* feat: add bulk delete authorization handler, refs AC-1125
* feat: always assign user and give manage access on create, refs AC-1125
* fix: updated CurrentContextOrganization type, refs AC-1125
* feat: combined existing collection authorization handlers/operations, refs AC-1125
* fix: OrganizationServiceTests -> CurrentContentOrganization typo, refs AC-1125
* fix: format, refs AC-1125
* fix: update collection controller tests, refs AC-1125
* fix: dotnet format, refs AC-1125
* feat: removed extra BulkAuthorizationHandler, refs AC-1125
* fix: dotnet format, refs AC-1125
* fix: change string to guid for org id, update bulk delete request model, refs AC-1125
* fix: remove delete many collection check, refs AC-1125
* fix: clean up collection auth handler, refs AC-1125
* fix: format fix for CollectionOperations, refs AC-1125
* fix: removed unnecessary owner check, add org null check to custom permission validation, refs AC-1125
* fix: remove unused methods in CurrentContext, refs AC-1125
* fix: removed obsolete test, fixed failling delete many test, refs AC-1125
* fix: CollectionAuthorizationHandlerTests fixes, refs AC-1125
* fix: OrganizationServiceTests fix broken test by mocking GetOrganization, refs AC-1125
* fix: CollectionAuthorizationHandler - remove unused repository, refs AC-1125
* feat: moved UserId null check to common method, refs AC-1125
* fix: updated auth handler tests to remove dependency on requirement for common code checks, refs AC-1125
* feat: updated conditionals/comments for create/delete methods within colleciton auth handler, refs AC-1125
* feat: added create/delete collection auth handler success methods, refs AC-1125
* fix: new up permissions to prevent excessive null checks, refs AC-1125
* fix: remove old reference to CreateNewCollections, refs AC-1125
* fix: typo within ViewAssignedCollections method, refs AC-1125
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
* refactor: remove organizationId from CollectionBulkDeleteRequestModel, refs AC-1649 (#3282)
* [AC-1174] Bulk Collection Management (#3229)
* [AC-1174] Update SelectionReadOnlyRequestModel to use Guid for Id property
* [AC-1174] Introduce initial bulk-access collection endpoint
* [AC-1174] Introduce BulkAddCollectionAccessCommand and validation logic/tests
* [AC-1174] Add CreateOrUpdateAccessMany method to CollectionRepository
* [AC-1174] Add event logs for bulk add collection access command
* [AC-1174] Add User_BumpAccountRevisionDateByCollectionIds and database migration script
* [AC-1174] Implement EF repository method
* [AC-1174] Improve null checks
* [AC-1174] Remove unnecessary BulkCollectionAccessRequestModel helpers
* [AC-1174] Add unit tests for new controller endpoint
* [AC-1174] Fix formatting
* [AC-1174] Remove comment
* [AC-1174] Remove redundant organizationId parameter
* [AC-1174] Ensure user and group Ids are distinct
* [AC-1174] Cleanup tests based on PR feedback
* [AC-1174] Formatting
* [AC-1174] Update CollectionGroup alias in the sproc
* [AC-1174] Add some additional comments to SQL sproc
* [AC-1174] Add comment explaining additional SaveChangesAsync call
---------
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
* [AC-1646] Rename LimitCollectionCdOwnerAdmin column (#3300)
* Rename LimitCollectionCdOwnerAdmin -> LimitCollectionCreationDeletion
* Rename and bump migration script
* [AC-1666] Removed EditAnyCollection from Create/Delete permission checks (#3301)
* fix: remove EditAnyCollection from Create/Delete permission check, refs AC-1666
* fix: updated comment, refs AC-1666
* [AC-1669] Bug - Remove obsolete assignUserId from CollectionService.SaveAsync(...) (#3312)
* fix: remove AssignUserId from CollectionService.SaveAsync, refs AC-1669
* fix: add manage access conditional before creating collection, refs AC-1669
* fix: move access logic for create/update, fix all tests, refs AC-1669
* fix: add CollectionAccessSelection fixture, update tests, update bad reqeuest message, refs AC-1669
* fix: format, refs AC-1669
* fix: update null params with specific arg.is null checks, refs Ac-1669
* fix: update attribute class name, refs AC-1669
* [AC-1713] [Flexible collections] Add feature flags to server (#3334)
* Add feature flags for FlexibleCollections and BulkCollectionAccess
* Flag new routes and behaviour
---------
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
* Add joint codeownership for auth handlers (#3346)
* [AC-1717] Update default values for LimitCollectionCreationDeletion (#3365)
* Change default value in organization create sproc to 1
* Drop old column name still present in some QA instances
* Set LimitCollectionCreationDeletion value in code based on feature flag
* Fix: add missing namespace after merging in master
* Fix: add missing namespace after merging in master
* [AC-1683] Fix DB migrations for new Manage permission (#3307)
* [AC-1683] Update migration script and introduce V2 procedures and types
* [AC-1683] Update repository calls to use new V2 procedures / types
* [AC-1684] Update bulk add collection migration script to use new V2 type
* [AC-1683] Undo Manage changes to more original procedures
* [AC-1683] Restore whitespace changes
* [AC-1683] Clarify comments regarding explicit column lists
* [AC-1683] Update migration script dates
* [AC-1683] Split the migration script for readability
* [AC-1683] Re-name SelectReadOnlyArray_V2 to CollectionAccessSelectionType
* [AC-1648] [Flexible Collections] Bump migration scripts before feature branch merge (#3371)
* Bump dates on sql migration scripts
* Bump date on ef migrations
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
Co-authored-by: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com>
Co-authored-by: Vincent Salucci <vincesalucci21@gmail.com>
Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
2023-11-01 19:30:52 +10:00
var org = _currentContext . GetOrganization ( organizationId ) ;
if ( org = = null )
2023-05-17 14:17:37 +01:00
{
return false ;
}
[AC-1373] Flexible Collections (#3245)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* fix: merge conflict resolution
* [AC-1174] CollectionUser and CollectionGroup authorization handlers (#3194)
* [AC-1174] Introduce BulkAuthorizationHandler.cs
* [AC-1174] Introduce CollectionUserAuthorizationHandler
* [AC-1174] Add CreateForNewCollection CollectionUser requirement
* [AC-1174] Add some more details to CollectionCustomization
* [AC-1174] Formatting
* [AC-1174] Add CollectionGroupOperation.cs
* [AC-1174] Introduce CollectionGroupAuthorizationHandler.cs
* [AC-1174] Cleanup CollectionFixture customization
Implement and use re-usable extension method to support seeded Guids
* [AC-1174] Introduce WithValueFromList AutoFixtureExtensions
Modify CollectionCustomization to use multiple organization Ids for auto generated test data
* [AC-1174] Simplify CollectionUserAuthorizationHandler.cs
Modify the authorization handler to only perform authorization logic. Validation logic will need to be handled by any calling commands/controllers instead.
* [AC-1174] Introduce shared CollectionAccessAuthorizationHandlerBase
A shared base authorization handler was created for both CollectionUser and CollectionGroup resources, as they share the same underlying management authorization logic.
* [AC-1174] Update CollectionUserAuthorizationHandler and CollectionGroupAuthorizationHandler to use the new CollectionAccessAuthorizationHandlerBase class
* [AC-1174] Formatting
* [AC-1174] Cleanup typo and redundant ToList() call
* [AC-1174] Add check for provider users
* [AC-1174] Reduce nested loops
* [AC-1174] Introduce ICollectionAccess.cs
* [AC-1174] Remove individual CollectionGroup and CollectionUser auth handlers and use base class instead
* [AC-1174] Tweak unit test to fail minimally
* [AC-1174] Reorganize authorization handlers in Core project
* [AC-1174] Introduce new AddCoreAuthorizationHandlers() extension method
* [AC-1174] Move CollectionAccessAuthorizationHandler into Api project
* [AC-1174] Move CollectionFixture to Vault folder
* [AC-1174] Rename operation to CreateUpdateDelete
* [AC-1174] Require single organization for collection access authorization handler
- Add requirement that all target collections must belong to the same organization
- Simplify logic related to multiple organizations
- Update tests and helpers
- Use ToHashSet to improve lookup time
* [AC-1174] Fix null reference exception
* [AC-1174] Throw bad request exception when collections belong to different organizations
* [AC-1174] Switch to CollectionAuthorizationHandler instead of CollectionAccessAuthorizationHandler to reduce complexity
* Fix improper merge conflict resolution
* fix: add permission check for collection management api, refs AC-1647 (#3252)
* [AC-1125] Enforce org setting for creating/deleting collections (#3241)
* [AC-1117] Add manage permission (#3126)
* Update sql files to add Manage permission
* Add migration script
* Rename collection manage migration file to remove duplicate migration date
* Migrations
* Add manage to models
* Add manage to repository
* Add constraint to Manage columns
* Migration lint fixes
* Add manage to OrganizationUserUserDetails_ReadWithCollectionsById
* Add missing manage fields
* Add 'Manage' to UserCollectionDetails
* Use CREATE OR ALTER where possible
* [AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
* feat: update org table with new column, write migration, refs AC-1374
* feat: update views with new column, refs AC-1374
* feat: Alter sprocs (org create/update) to include new column, refs AC-1374
* feat: update entity/data/request/response models to handle new column, refs AC-1374
* feat: update necessary Provider related views during migration, refs AC-1374
* fix: update org create to default new column to false, refs AC-1374
* feat: added new API/request model for collection management and removed property from update request model, refs AC-1374
* fix: renamed migration script to be after secrets manage beta column changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: add ef migrations to reflect mssql changes, refs AC-1374
* fix: dotnet format, refs AC-1374
* feat: update API signature to accept Guid and explain Cd verbiage, refs AC-1374
* feat: created collection auth handler/operations, added LimitCollectionCdOwnerAdmin to CurrentContentOrganization, refs AC-1125
* feat: create vault service collection extensions and register with base services, refs AC-1125
* feat: deprecated CurrentContext.CreateNewCollections, refs AC-1125
* feat: deprecate DeleteAnyCollection for single resource usages, refs AC-1125
* feat: move service registration to api, update references, refs AC-1125
* feat: add bulk delete authorization handler, refs AC-1125
* feat: always assign user and give manage access on create, refs AC-1125
* fix: updated CurrentContextOrganization type, refs AC-1125
* feat: combined existing collection authorization handlers/operations, refs AC-1125
* fix: OrganizationServiceTests -> CurrentContentOrganization typo, refs AC-1125
* fix: format, refs AC-1125
* fix: update collection controller tests, refs AC-1125
* fix: dotnet format, refs AC-1125
* feat: removed extra BulkAuthorizationHandler, refs AC-1125
* fix: dotnet format, refs AC-1125
* fix: change string to guid for org id, update bulk delete request model, refs AC-1125
* fix: remove delete many collection check, refs AC-1125
* fix: clean up collection auth handler, refs AC-1125
* fix: format fix for CollectionOperations, refs AC-1125
* fix: removed unnecessary owner check, add org null check to custom permission validation, refs AC-1125
* fix: remove unused methods in CurrentContext, refs AC-1125
* fix: removed obsolete test, fixed failling delete many test, refs AC-1125
* fix: CollectionAuthorizationHandlerTests fixes, refs AC-1125
* fix: OrganizationServiceTests fix broken test by mocking GetOrganization, refs AC-1125
* fix: CollectionAuthorizationHandler - remove unused repository, refs AC-1125
* feat: moved UserId null check to common method, refs AC-1125
* fix: updated auth handler tests to remove dependency on requirement for common code checks, refs AC-1125
* feat: updated conditionals/comments for create/delete methods within colleciton auth handler, refs AC-1125
* feat: added create/delete collection auth handler success methods, refs AC-1125
* fix: new up permissions to prevent excessive null checks, refs AC-1125
* fix: remove old reference to CreateNewCollections, refs AC-1125
* fix: typo within ViewAssignedCollections method, refs AC-1125
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
* refactor: remove organizationId from CollectionBulkDeleteRequestModel, refs AC-1649 (#3282)
* [AC-1174] Bulk Collection Management (#3229)
* [AC-1174] Update SelectionReadOnlyRequestModel to use Guid for Id property
* [AC-1174] Introduce initial bulk-access collection endpoint
* [AC-1174] Introduce BulkAddCollectionAccessCommand and validation logic/tests
* [AC-1174] Add CreateOrUpdateAccessMany method to CollectionRepository
* [AC-1174] Add event logs for bulk add collection access command
* [AC-1174] Add User_BumpAccountRevisionDateByCollectionIds and database migration script
* [AC-1174] Implement EF repository method
* [AC-1174] Improve null checks
* [AC-1174] Remove unnecessary BulkCollectionAccessRequestModel helpers
* [AC-1174] Add unit tests for new controller endpoint
* [AC-1174] Fix formatting
* [AC-1174] Remove comment
* [AC-1174] Remove redundant organizationId parameter
* [AC-1174] Ensure user and group Ids are distinct
* [AC-1174] Cleanup tests based on PR feedback
* [AC-1174] Formatting
* [AC-1174] Update CollectionGroup alias in the sproc
* [AC-1174] Add some additional comments to SQL sproc
* [AC-1174] Add comment explaining additional SaveChangesAsync call
---------
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
* [AC-1646] Rename LimitCollectionCdOwnerAdmin column (#3300)
* Rename LimitCollectionCdOwnerAdmin -> LimitCollectionCreationDeletion
* Rename and bump migration script
* [AC-1666] Removed EditAnyCollection from Create/Delete permission checks (#3301)
* fix: remove EditAnyCollection from Create/Delete permission check, refs AC-1666
* fix: updated comment, refs AC-1666
* [AC-1669] Bug - Remove obsolete assignUserId from CollectionService.SaveAsync(...) (#3312)
* fix: remove AssignUserId from CollectionService.SaveAsync, refs AC-1669
* fix: add manage access conditional before creating collection, refs AC-1669
* fix: move access logic for create/update, fix all tests, refs AC-1669
* fix: add CollectionAccessSelection fixture, update tests, update bad reqeuest message, refs AC-1669
* fix: format, refs AC-1669
* fix: update null params with specific arg.is null checks, refs Ac-1669
* fix: update attribute class name, refs AC-1669
* [AC-1713] [Flexible collections] Add feature flags to server (#3334)
* Add feature flags for FlexibleCollections and BulkCollectionAccess
* Flag new routes and behaviour
---------
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
* Add joint codeownership for auth handlers (#3346)
* [AC-1717] Update default values for LimitCollectionCreationDeletion (#3365)
* Change default value in organization create sproc to 1
* Drop old column name still present in some QA instances
* Set LimitCollectionCreationDeletion value in code based on feature flag
* Fix: add missing namespace after merging in master
* Fix: add missing namespace after merging in master
* [AC-1683] Fix DB migrations for new Manage permission (#3307)
* [AC-1683] Update migration script and introduce V2 procedures and types
* [AC-1683] Update repository calls to use new V2 procedures / types
* [AC-1684] Update bulk add collection migration script to use new V2 type
* [AC-1683] Undo Manage changes to more original procedures
* [AC-1683] Restore whitespace changes
* [AC-1683] Clarify comments regarding explicit column lists
* [AC-1683] Update migration script dates
* [AC-1683] Split the migration script for readability
* [AC-1683] Re-name SelectReadOnlyArray_V2 to CollectionAccessSelectionType
* [AC-1648] [Flexible Collections] Bump migration scripts before feature branch merge (#3371)
* Bump dates on sql migration scripts
* Bump date on ef migrations
---------
Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com>
Co-authored-by: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com>
Co-authored-by: Vincent Salucci <vincesalucci21@gmail.com>
Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
2023-11-01 19:30:52 +10:00
if ( permissions . CreateNewCollections & & ! org . Permissions . CreateNewCollections )
{
return false ;
}
if ( permissions . DeleteAnyCollection & & ! org . Permissions . DeleteAnyCollection )
2023-05-17 14:17:37 +01:00
{
return false ;
}
return true ;
}
2022-06-16 15:59:57 -04:00
private async Task ValidateDeleteOrganizationAsync ( Organization organization )
2022-08-29 16:06:55 -04:00
{
2022-06-16 15:59:57 -04:00
var ssoConfig = await _ssoConfigRepository . GetByOrganizationIdAsync ( organization . Id ) ;
2023-05-10 12:52:08 -07:00
if ( ssoConfig ? . GetData ( ) ? . MemberDecryptionType = = MemberDecryptionType . KeyConnector )
2022-08-29 15:53:48 -04:00
{
2022-06-16 15:59:57 -04:00
throw new BadRequestException ( "You cannot delete an Organization that is using Key Connector." ) ;
2022-08-29 15:53:48 -04:00
}
2022-08-29 16:06:55 -04:00
}
2022-06-16 15:59:57 -04:00
2022-07-25 10:47:44 +10:00
public async Task RevokeUserAsync ( OrganizationUser organizationUser , Guid ? revokingUserId )
2022-08-29 16:06:55 -04:00
{
2022-07-25 10:47:44 +10:00
if ( revokingUserId . HasValue & & organizationUser . UserId = = revokingUserId . Value )
2022-06-16 15:59:57 -04:00
{
throw new BadRequestException ( "You cannot revoke yourself." ) ;
2022-08-29 14:53:16 -04:00
}
2022-06-16 15:59:57 -04:00
if ( organizationUser . Type = = OrganizationUserType . Owner & & revokingUserId . HasValue & &
! await _currentContext . OrganizationOwner ( organizationUser . OrganizationId ) )
{
throw new BadRequestException ( "Only owners can revoke other owners." ) ;
}
2022-11-09 12:13:29 +00:00
await RepositoryRevokeUserAsync ( organizationUser ) ;
await _eventService . LogOrganizationUserEventAsync ( organizationUser , EventType . OrganizationUser_Revoked ) ;
}
public async Task RevokeUserAsync ( OrganizationUser organizationUser ,
EventSystemUser systemUser )
{
await RepositoryRevokeUserAsync ( organizationUser ) ;
await _eventService . LogOrganizationUserEventAsync ( organizationUser , EventType . OrganizationUser_Revoked , systemUser ) ;
}
private async Task RepositoryRevokeUserAsync ( OrganizationUser organizationUser )
{
if ( organizationUser . Status = = OrganizationUserStatusType . Revoked )
{
throw new BadRequestException ( "Already revoked." ) ;
}
2023-05-17 16:39:08 +01:00
if ( ! await HasConfirmedOwnersExceptAsync ( organizationUser . OrganizationId , new [ ] { organizationUser . Id } , includeProvider : true ) )
2022-08-29 15:53:48 -04:00
{
2022-06-16 15:59:57 -04:00
throw new BadRequestException ( "Organization must have at least one confirmed owner." ) ;
2022-08-29 15:53:48 -04:00
}
2022-06-16 15:59:57 -04:00
await _organizationUserRepository . RevokeAsync ( organizationUser . Id ) ;
organizationUser . Status = OrganizationUserStatusType . Revoked ;
}
public async Task < List < Tuple < OrganizationUser , string > > > RevokeUsersAsync ( Guid organizationId ,
IEnumerable < Guid > organizationUserIds , Guid ? revokingUserId )
{
var orgUsers = await _organizationUserRepository . GetManyAsync ( organizationUserIds ) ;
var filteredUsers = orgUsers . Where ( u = > u . OrganizationId = = organizationId )
. ToList ( ) ;
if ( ! filteredUsers . Any ( ) )
2022-08-29 16:06:55 -04:00
{
2022-06-16 15:59:57 -04:00
throw new BadRequestException ( "Users invalid." ) ;
2022-06-17 11:04:25 -04:00
}
2022-07-25 10:47:44 +10:00
if ( ! await HasConfirmedOwnersExceptAsync ( organizationId , organizationUserIds ) )
2022-08-29 15:53:48 -04:00
{
2022-07-25 10:47:44 +10:00
throw new BadRequestException ( "Organization must have at least one confirmed owner." ) ;
2022-08-29 16:06:55 -04:00
}
2022-06-16 15:59:57 -04:00
2022-07-25 10:47:44 +10:00
var deletingUserIsOwner = false ;
if ( revokingUserId . HasValue )
2022-08-29 15:53:48 -04:00
{
2022-07-25 10:47:44 +10:00
deletingUserIsOwner = await _currentContext . OrganizationOwner ( organizationId ) ;
2022-08-29 14:53:16 -04:00
}
2022-08-29 15:53:48 -04:00
2022-07-20 11:42:06 +10:00
var result = new List < Tuple < OrganizationUser , string > > ( ) ;
2022-06-16 15:59:57 -04:00
foreach ( var organizationUser in filteredUsers )
2022-08-29 16:06:55 -04:00
{
try
2022-08-29 15:53:48 -04:00
{
2022-07-25 10:47:44 +10:00
if ( organizationUser . Status = = OrganizationUserStatusType . Revoked )
2022-08-29 16:06:55 -04:00
{
2022-07-25 10:47:44 +10:00
throw new BadRequestException ( "Already revoked." ) ;
2022-08-29 14:53:16 -04:00
}
2022-06-16 15:59:57 -04:00
if ( revokingUserId . HasValue & & organizationUser . UserId = = revokingUserId )
2022-08-29 16:06:55 -04:00
{
2022-06-16 15:59:57 -04:00
throw new BadRequestException ( "You cannot revoke yourself." ) ;
2022-08-29 16:06:55 -04:00
}
2022-06-16 15:59:57 -04:00
if ( organizationUser . Type = = OrganizationUserType . Owner & & revokingUserId . HasValue & & ! deletingUserIsOwner )
2022-08-29 15:53:48 -04:00
{
2022-06-16 15:59:57 -04:00
throw new BadRequestException ( "Only owners can revoke other owners." ) ;
2022-08-29 15:53:48 -04:00
}
2022-06-16 15:59:57 -04:00
await _organizationUserRepository . RevokeAsync ( organizationUser . Id ) ;
organizationUser . Status = OrganizationUserStatusType . Revoked ;
await _eventService . LogOrganizationUserEventAsync ( organizationUser , EventType . OrganizationUser_Revoked ) ;
2022-08-29 15:53:48 -04:00
2022-07-25 10:47:44 +10:00
result . Add ( Tuple . Create ( organizationUser , "" ) ) ;
2022-08-29 16:06:55 -04:00
}
2022-06-16 15:59:57 -04:00
catch ( BadRequestException e )
2022-08-29 16:06:55 -04:00
{
2022-06-16 15:59:57 -04:00
result . Add ( Tuple . Create ( organizationUser , e . Message ) ) ;
2022-08-29 15:53:48 -04:00
}
2022-08-29 16:06:55 -04:00
}
2022-08-29 15:53:48 -04:00
2022-06-16 15:59:57 -04:00
return result ;
2022-08-29 16:06:55 -04:00
}
2022-08-29 15:53:48 -04:00
2022-11-09 12:13:29 +00:00
public async Task RestoreUserAsync ( OrganizationUser organizationUser , Guid ? restoringUserId ,
IUserService userService )
2022-08-29 16:06:55 -04:00
{
2022-06-16 15:59:57 -04:00
if ( restoringUserId . HasValue & & organizationUser . UserId = = restoringUserId . Value )
2022-08-29 16:06:55 -04:00
{
2022-06-16 15:59:57 -04:00
throw new BadRequestException ( "You cannot restore yourself." ) ;
}
2022-08-03 07:09:22 +10:00
if ( organizationUser . Type = = OrganizationUserType . Owner & & restoringUserId . HasValue & &
! await _currentContext . OrganizationOwner ( organizationUser . OrganizationId ) )
2022-06-16 15:59:57 -04:00
{
throw new BadRequestException ( "Only owners can restore other owners." ) ;
}
2022-11-09 12:13:29 +00:00
await RepositoryRestoreUserAsync ( organizationUser , userService ) ;
await _eventService . LogOrganizationUserEventAsync ( organizationUser , EventType . OrganizationUser_Restored ) ;
}
public async Task RestoreUserAsync ( OrganizationUser organizationUser , EventSystemUser systemUser ,
IUserService userService )
{
await RepositoryRestoreUserAsync ( organizationUser , userService ) ;
await _eventService . LogOrganizationUserEventAsync ( organizationUser , EventType . OrganizationUser_Restored , systemUser ) ;
}
private async Task RepositoryRestoreUserAsync ( OrganizationUser organizationUser , IUserService userService )
{
if ( organizationUser . Status ! = OrganizationUserStatusType . Revoked )
{
throw new BadRequestException ( "Already active." ) ;
}
2022-09-23 14:30:39 +10:00
var organization = await _organizationRepository . GetByIdAsync ( organizationUser . OrganizationId ) ;
2023-02-24 07:54:19 +10:00
var occupiedSeats = await _organizationUserRepository . GetOccupiedSeatCountByOrganizationIdAsync ( organization . Id ) ;
2022-09-23 14:30:39 +10:00
var availableSeats = organization . Seats . GetValueOrDefault ( 0 ) - occupiedSeats ;
if ( availableSeats < 1 )
{
await AutoAddSeatsAsync ( organization , 1 , DateTime . UtcNow ) ;
}
2022-07-25 10:47:44 +10:00
await CheckPoliciesBeforeRestoreAsync ( organizationUser , userService ) ;
2022-06-16 15:59:57 -04:00
2022-07-25 10:47:44 +10:00
var status = GetPriorActiveOrganizationUserStatusType ( organizationUser ) ;
2022-06-16 15:59:57 -04:00
2022-08-03 07:09:22 +10:00
await _organizationUserRepository . RestoreAsync ( organizationUser . Id , status ) ;
2022-07-25 10:47:44 +10:00
organizationUser . Status = status ;
2022-08-29 16:06:55 -04:00
}
2022-08-03 07:09:22 +10:00
2022-06-16 15:59:57 -04:00
public async Task < List < Tuple < OrganizationUser , string > > > RestoreUsersAsync ( Guid organizationId ,
IEnumerable < Guid > organizationUserIds , Guid ? restoringUserId , IUserService userService )
2022-08-29 16:06:55 -04:00
{
2022-06-16 15:59:57 -04:00
var orgUsers = await _organizationUserRepository . GetManyAsync ( organizationUserIds ) ;
var filteredUsers = orgUsers . Where ( u = > u . OrganizationId = = organizationId )
. ToList ( ) ;
2022-07-25 10:47:44 +10:00
if ( ! filteredUsers . Any ( ) )
2022-08-29 16:06:55 -04:00
{
2022-07-25 10:47:44 +10:00
throw new BadRequestException ( "Users invalid." ) ;
2022-06-16 15:59:57 -04:00
}
2022-09-23 14:30:39 +10:00
var organization = await _organizationRepository . GetByIdAsync ( organizationId ) ;
2023-02-24 07:54:19 +10:00
var occupiedSeats = await _organizationUserRepository . GetOccupiedSeatCountByOrganizationIdAsync ( organization . Id ) ;
2022-09-23 14:30:39 +10:00
var availableSeats = organization . Seats . GetValueOrDefault ( 0 ) - occupiedSeats ;
var newSeatsRequired = organizationUserIds . Count ( ) - availableSeats ;
await AutoAddSeatsAsync ( organization , newSeatsRequired , DateTime . UtcNow ) ;
2022-07-25 10:47:44 +10:00
var deletingUserIsOwner = false ;
2022-08-03 07:09:22 +10:00
if ( restoringUserId . HasValue )
2022-06-16 15:59:57 -04:00
{
2022-07-25 10:47:44 +10:00
deletingUserIsOwner = await _currentContext . OrganizationOwner ( organizationId ) ;
2022-06-16 15:59:57 -04:00
}
2022-07-25 10:47:44 +10:00
var result = new List < Tuple < OrganizationUser , string > > ( ) ;
2022-06-16 15:59:57 -04:00
2022-07-25 10:47:44 +10:00
foreach ( var organizationUser in filteredUsers )
2022-08-29 16:06:55 -04:00
{
try
2022-08-29 15:53:48 -04:00
{
2022-07-20 11:42:06 +10:00
if ( organizationUser . Status ! = OrganizationUserStatusType . Revoked )
2022-06-16 15:59:57 -04:00
{
2022-07-20 11:42:06 +10:00
throw new BadRequestException ( "Already active." ) ;
2022-08-29 15:53:48 -04:00
}
2022-07-20 11:42:06 +10:00
if ( restoringUserId . HasValue & & organizationUser . UserId = = restoringUserId )
2022-08-29 15:53:48 -04:00
{
2022-07-20 11:42:06 +10:00
throw new BadRequestException ( "You cannot restore yourself." ) ;
2022-06-16 15:59:57 -04:00
}
2022-08-03 07:09:22 +10:00
if ( organizationUser . Type = = OrganizationUserType . Owner & & restoringUserId . HasValue & & ! deletingUserIsOwner )
2022-08-29 15:53:48 -04:00
{
2022-08-03 07:09:22 +10:00
throw new BadRequestException ( "Only owners can restore other owners." ) ;
2022-08-29 15:53:48 -04:00
}
2022-08-03 07:09:22 +10:00
2022-06-16 15:59:57 -04:00
await CheckPoliciesBeforeRestoreAsync ( organizationUser , userService ) ;
2022-07-25 10:47:44 +10:00
var status = GetPriorActiveOrganizationUserStatusType ( organizationUser ) ;
2022-06-16 15:59:57 -04:00
2022-07-25 10:47:44 +10:00
await _organizationUserRepository . RestoreAsync ( organizationUser . Id , status ) ;
2022-06-16 15:59:57 -04:00
organizationUser . Status = status ;
await _eventService . LogOrganizationUserEventAsync ( organizationUser , EventType . OrganizationUser_Restored ) ;
2022-08-29 15:53:48 -04:00
2022-06-16 15:59:57 -04:00
result . Add ( Tuple . Create ( organizationUser , "" ) ) ;
}
catch ( BadRequestException e )
{
result . Add ( Tuple . Create ( organizationUser , e . Message ) ) ;
}
2022-08-29 14:53:16 -04:00
}
2022-06-16 15:59:57 -04:00
return result ;
2022-08-29 16:06:55 -04:00
}
2022-08-03 07:09:22 +10:00
private async Task CheckPoliciesBeforeRestoreAsync ( OrganizationUser orgUser , IUserService userService )
2022-08-29 16:06:55 -04:00
{
2022-08-03 07:09:22 +10:00
// An invited OrganizationUser isn't linked with a user account yet, so these checks are irrelevant
// The user will be subject to the same checks when they try to accept the invite
if ( GetPriorActiveOrganizationUserStatusType ( orgUser ) = = OrganizationUserStatusType . Invited )
{
return ;
}
var userId = orgUser . UserId . Value ;
// Enforce Single Organization Policy of organization user is being restored to
var allOrgUsers = await _organizationUserRepository . GetManyByUserAsync ( userId ) ;
var hasOtherOrgs = allOrgUsers . Any ( ou = > ou . OrganizationId ! = orgUser . OrganizationId ) ;
2023-05-12 08:22:19 +01:00
var singleOrgPoliciesApplyingToRevokedUsers = await _policyService . GetPoliciesApplicableToUserAsync ( userId ,
2022-08-03 07:09:22 +10:00
PolicyType . SingleOrg , OrganizationUserStatusType . Revoked ) ;
var singleOrgPolicyApplies = singleOrgPoliciesApplyingToRevokedUsers . Any ( p = > p . OrganizationId = = orgUser . OrganizationId ) ;
if ( hasOtherOrgs & & singleOrgPolicyApplies )
{
throw new BadRequestException ( "You cannot restore this user until " +
"they leave or remove all other organizations." ) ;
}
// Enforce Single Organization Policy of other organizations user is a member of
2023-05-12 08:22:19 +01:00
var anySingleOrgPolicies = await _policyService . AnyPoliciesApplicableToUserAsync ( userId ,
2022-08-03 07:09:22 +10:00
PolicyType . SingleOrg ) ;
2023-05-12 08:22:19 +01:00
if ( anySingleOrgPolicies )
2022-08-03 07:09:22 +10:00
{
throw new BadRequestException ( "You cannot restore this user because they are a member of " +
"another organization which forbids it" ) ;
}
// Enforce Two Factor Authentication Policy of organization user is trying to join
var user = await _userRepository . GetByIdAsync ( userId ) ;
if ( ! await userService . TwoFactorIsEnabledAsync ( user ) )
2022-08-29 16:06:55 -04:00
{
2023-05-12 08:22:19 +01:00
var invitedTwoFactorPolicies = await _policyService . GetPoliciesApplicableToUserAsync ( userId ,
2022-08-03 07:09:22 +10:00
PolicyType . TwoFactorAuthentication , OrganizationUserStatusType . Invited ) ;
if ( invitedTwoFactorPolicies . Any ( p = > p . OrganizationId = = orgUser . OrganizationId ) )
{
throw new BadRequestException ( "You cannot restore this user until they enable " +
"two-step login on their user account." ) ;
}
}
2022-08-29 16:06:55 -04:00
}
2022-08-03 07:09:22 +10:00
2022-06-16 15:59:57 -04:00
static OrganizationUserStatusType GetPriorActiveOrganizationUserStatusType ( OrganizationUser organizationUser )
2022-08-29 16:06:55 -04:00
{
2022-06-16 15:59:57 -04:00
// Determine status to revert back to
var status = OrganizationUserStatusType . Invited ;
if ( organizationUser . UserId . HasValue & & string . IsNullOrWhiteSpace ( organizationUser . Email ) )
{
// Has UserId & Email is null, then Accepted
status = OrganizationUserStatusType . Accepted ;
if ( ! string . IsNullOrWhiteSpace ( organizationUser . Key ) )
{
// We have an org key for this user, user was confirmed
status = OrganizationUserStatusType . Confirmed ;
}
2022-08-29 15:53:48 -04:00
}
2022-08-29 16:06:55 -04:00
2022-06-16 15:59:57 -04:00
return status ;
2017-03-03 00:07:11 -05:00
}
2023-04-14 11:13:16 +01:00
public async Task CreatePendingOrganization ( Organization organization , string ownerEmail , ClaimsPrincipal user , IUserService userService , bool salesAssistedTrialStarted )
{
2023-10-17 15:56:35 +01:00
var plan = StaticStore . Plans . FirstOrDefault ( p = > p . Type = = organization . PlanType ) ;
2023-04-14 11:13:16 +01:00
2023-12-20 22:54:45 +01:00
if ( plan ! . Disabled )
2023-04-14 11:13:16 +01:00
{
throw new BadRequestException ( "Plan not found." ) ;
}
organization . Id = CoreHelpers . GenerateComb ( ) ;
organization . Enabled = false ;
organization . Status = OrganizationStatusType . Pending ;
await SignUpAsync ( organization , default , null , null , true ) ;
var ownerOrganizationUser = new OrganizationUser
{
OrganizationId = organization . Id ,
UserId = null ,
Email = ownerEmail ,
Key = null ,
Type = OrganizationUserType . Owner ,
Status = OrganizationUserStatusType . Invited ,
2024-01-22 08:56:20 +10:00
// If using Flexible Collections, AccessAll is deprecated and set to false.
// If not using Flexible Collections, set AccessAll to true (previous behavior)
AccessAll = ! organization . FlexibleCollections ,
2023-04-14 11:13:16 +01:00
} ;
await _organizationUserRepository . CreateAsync ( ownerOrganizationUser ) ;
await SendInviteAsync ( ownerOrganizationUser , organization , true ) ;
await _eventService . LogOrganizationUserEventAsync ( ownerOrganizationUser , EventType . OrganizationUser_Invited ) ;
2023-05-16 16:21:57 +02:00
await _referenceEventService . RaiseEventAsync ( new ReferenceEvent ( ReferenceEventType . OrganizationCreatedByAdmin , organization , _currentContext )
2023-04-14 11:13:16 +01:00
{
EventRaisedByUser = userService . GetUserName ( user ) ,
SalesAssistedTrialStarted = salesAssistedTrialStarted ,
} ) ;
}
2024-02-25 17:00:34 -06:00
public async Task InitPendingOrganization ( Guid userId , Guid organizationId , Guid organizationUserId , string publicKey , string privateKey , string collectionName )
2023-04-14 11:13:16 +01:00
{
await ValidateSignUpPoliciesAsync ( userId ) ;
var org = await GetOrgById ( organizationId ) ;
if ( org . Enabled )
{
throw new BadRequestException ( "Organization is already enabled." ) ;
}
if ( org . Status ! = OrganizationStatusType . Pending )
{
throw new BadRequestException ( "Organization is not on a Pending status." ) ;
}
if ( ! string . IsNullOrEmpty ( org . PublicKey ) )
{
throw new BadRequestException ( "Organization already has a Public Key." ) ;
}
if ( ! string . IsNullOrEmpty ( org . PrivateKey ) )
{
throw new BadRequestException ( "Organization already has a Private Key." ) ;
}
org . Enabled = true ;
org . Status = OrganizationStatusType . Created ;
org . PublicKey = publicKey ;
org . PrivateKey = privateKey ;
await UpdateAsync ( org ) ;
if ( ! string . IsNullOrWhiteSpace ( collectionName ) )
{
2024-02-12 08:50:41 +10:00
// If using Flexible Collections, give the owner Can Manage access over the default collection
List < CollectionAccessSelection > defaultOwnerAccess = null ;
if ( org . FlexibleCollections )
{
defaultOwnerAccess =
2024-02-25 17:00:34 -06:00
[new CollectionAccessSelection { Id = organizationUserId, HidePasswords = false, ReadOnly = false, Manage = true }] ;
2024-02-12 08:50:41 +10:00
}
2023-04-14 11:13:16 +01:00
var defaultCollection = new Collection
{
Name = collectionName ,
OrganizationId = org . Id
} ;
2024-02-12 08:50:41 +10:00
await _collectionRepository . CreateAsync ( defaultCollection , null , defaultOwnerAccess ) ;
2023-04-14 11:13:16 +01:00
}
}
2017-03-03 00:07:11 -05:00
}