mirror of
https://github.com/bitwarden/server.git
synced 2025-02-12 01:11:22 +01:00
Merge branch 'main' into km/userkey-rotation-v2
This commit is contained in:
commit
8f9252decb
@ -309,7 +309,7 @@ public class OrganizationsController : Controller
|
|||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
[RequirePermission(Permission.Org_Delete)]
|
[RequirePermission(Permission.Org_RequestDelete)]
|
||||||
public async Task<IActionResult> DeleteInitiation(Guid id, OrganizationInitiateDeleteModel model)
|
public async Task<IActionResult> DeleteInitiation(Guid id, OrganizationInitiateDeleteModel model)
|
||||||
{
|
{
|
||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
|
@ -311,10 +311,8 @@ public class OrganizationUsersController : Controller
|
|||||||
throw new UnauthorizedAccessException();
|
throw new UnauthorizedAccessException();
|
||||||
}
|
}
|
||||||
|
|
||||||
var masterPasswordPolicy = await _policyRepository.GetByOrganizationIdTypeAsync(orgId, PolicyType.ResetPassword);
|
var useMasterPasswordPolicy = await ShouldHandleResetPasswordAsync(orgId);
|
||||||
var useMasterPasswordPolicy = masterPasswordPolicy != null &&
|
|
||||||
masterPasswordPolicy.Enabled &&
|
|
||||||
masterPasswordPolicy.GetDataModel<ResetPasswordDataModel>().AutoEnrollEnabled;
|
|
||||||
if (useMasterPasswordPolicy && string.IsNullOrWhiteSpace(model.ResetPasswordKey))
|
if (useMasterPasswordPolicy && string.IsNullOrWhiteSpace(model.ResetPasswordKey))
|
||||||
{
|
{
|
||||||
throw new BadRequestException(string.Empty, "Master Password reset is required, but not provided.");
|
throw new BadRequestException(string.Empty, "Master Password reset is required, but not provided.");
|
||||||
@ -328,6 +326,23 @@ public class OrganizationUsersController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<bool> ShouldHandleResetPasswordAsync(Guid orgId)
|
||||||
|
{
|
||||||
|
var organizationAbility = await _applicationCacheService.GetOrganizationAbilityAsync(orgId);
|
||||||
|
|
||||||
|
if (organizationAbility is not { UsePolicies: true })
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var masterPasswordPolicy = await _policyRepository.GetByOrganizationIdTypeAsync(orgId, PolicyType.ResetPassword);
|
||||||
|
var useMasterPasswordPolicy = masterPasswordPolicy != null &&
|
||||||
|
masterPasswordPolicy.Enabled &&
|
||||||
|
masterPasswordPolicy.GetDataModel<ResetPasswordDataModel>().AutoEnrollEnabled;
|
||||||
|
|
||||||
|
return useMasterPasswordPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPost("{id}/confirm")]
|
[HttpPost("{id}/confirm")]
|
||||||
public async Task Confirm(string orgId, string id, [FromBody] OrganizationUserConfirmRequestModel model)
|
public async Task Confirm(string orgId, string id, [FromBody] OrganizationUserConfirmRequestModel model)
|
||||||
{
|
{
|
||||||
|
@ -57,6 +57,7 @@ public class OrganizationResponseModel : ResponseModel
|
|||||||
MaxAutoscaleSmServiceAccounts = organization.MaxAutoscaleSmServiceAccounts;
|
MaxAutoscaleSmServiceAccounts = organization.MaxAutoscaleSmServiceAccounts;
|
||||||
LimitCollectionCreation = organization.LimitCollectionCreation;
|
LimitCollectionCreation = organization.LimitCollectionCreation;
|
||||||
LimitCollectionDeletion = organization.LimitCollectionDeletion;
|
LimitCollectionDeletion = organization.LimitCollectionDeletion;
|
||||||
|
LimitItemDeletion = organization.LimitItemDeletion;
|
||||||
AllowAdminAccessToAllCollectionItems = organization.AllowAdminAccessToAllCollectionItems;
|
AllowAdminAccessToAllCollectionItems = organization.AllowAdminAccessToAllCollectionItems;
|
||||||
UseRiskInsights = organization.UseRiskInsights;
|
UseRiskInsights = organization.UseRiskInsights;
|
||||||
}
|
}
|
||||||
@ -102,6 +103,7 @@ public class OrganizationResponseModel : ResponseModel
|
|||||||
public int? MaxAutoscaleSmServiceAccounts { get; set; }
|
public int? MaxAutoscaleSmServiceAccounts { get; set; }
|
||||||
public bool LimitCollectionCreation { get; set; }
|
public bool LimitCollectionCreation { get; set; }
|
||||||
public bool LimitCollectionDeletion { get; set; }
|
public bool LimitCollectionDeletion { get; set; }
|
||||||
|
public bool LimitItemDeletion { get; set; }
|
||||||
public bool AllowAdminAccessToAllCollectionItems { get; set; }
|
public bool AllowAdminAccessToAllCollectionItems { get; set; }
|
||||||
public bool UseRiskInsights { get; set; }
|
public bool UseRiskInsights { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,7 @@ public class ProfileOrganizationResponseModel : ResponseModel
|
|||||||
AccessSecretsManager = organization.AccessSecretsManager;
|
AccessSecretsManager = organization.AccessSecretsManager;
|
||||||
LimitCollectionCreation = organization.LimitCollectionCreation;
|
LimitCollectionCreation = organization.LimitCollectionCreation;
|
||||||
LimitCollectionDeletion = organization.LimitCollectionDeletion;
|
LimitCollectionDeletion = organization.LimitCollectionDeletion;
|
||||||
|
LimitItemDeletion = organization.LimitItemDeletion;
|
||||||
AllowAdminAccessToAllCollectionItems = organization.AllowAdminAccessToAllCollectionItems;
|
AllowAdminAccessToAllCollectionItems = organization.AllowAdminAccessToAllCollectionItems;
|
||||||
UserIsManagedByOrganization = organizationIdsManagingUser.Contains(organization.OrganizationId);
|
UserIsManagedByOrganization = organizationIdsManagingUser.Contains(organization.OrganizationId);
|
||||||
UseRiskInsights = organization.UseRiskInsights;
|
UseRiskInsights = organization.UseRiskInsights;
|
||||||
@ -128,6 +129,7 @@ public class ProfileOrganizationResponseModel : ResponseModel
|
|||||||
public bool AccessSecretsManager { get; set; }
|
public bool AccessSecretsManager { get; set; }
|
||||||
public bool LimitCollectionCreation { get; set; }
|
public bool LimitCollectionCreation { get; set; }
|
||||||
public bool LimitCollectionDeletion { get; set; }
|
public bool LimitCollectionDeletion { get; set; }
|
||||||
|
public bool LimitItemDeletion { get; set; }
|
||||||
public bool AllowAdminAccessToAllCollectionItems { get; set; }
|
public bool AllowAdminAccessToAllCollectionItems { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates if the organization manages the user.
|
/// Indicates if the organization manages the user.
|
||||||
|
@ -47,6 +47,7 @@ public class ProfileProviderOrganizationResponseModel : ProfileOrganizationRespo
|
|||||||
ProductTierType = StaticStore.GetPlan(organization.PlanType).ProductTier;
|
ProductTierType = StaticStore.GetPlan(organization.PlanType).ProductTier;
|
||||||
LimitCollectionCreation = organization.LimitCollectionCreation;
|
LimitCollectionCreation = organization.LimitCollectionCreation;
|
||||||
LimitCollectionDeletion = organization.LimitCollectionDeletion;
|
LimitCollectionDeletion = organization.LimitCollectionDeletion;
|
||||||
|
LimitItemDeletion = organization.LimitItemDeletion;
|
||||||
AllowAdminAccessToAllCollectionItems = organization.AllowAdminAccessToAllCollectionItems;
|
AllowAdminAccessToAllCollectionItems = organization.AllowAdminAccessToAllCollectionItems;
|
||||||
UseRiskInsights = organization.UseRiskInsights;
|
UseRiskInsights = organization.UseRiskInsights;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Bit.Core.Auth.Entities;
|
using Bit.Core.Auth.Entities;
|
||||||
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Models.Api;
|
using Bit.Core.Models.Api;
|
||||||
|
|
||||||
namespace Bit.Api.Auth.Models.Response;
|
namespace Bit.Api.Auth.Models.Response;
|
||||||
@ -17,6 +18,7 @@ public class AuthRequestResponseModel : ResponseModel
|
|||||||
|
|
||||||
Id = authRequest.Id;
|
Id = authRequest.Id;
|
||||||
PublicKey = authRequest.PublicKey;
|
PublicKey = authRequest.PublicKey;
|
||||||
|
RequestDeviceTypeValue = authRequest.RequestDeviceType;
|
||||||
RequestDeviceType = authRequest.RequestDeviceType.GetType().GetMember(authRequest.RequestDeviceType.ToString())
|
RequestDeviceType = authRequest.RequestDeviceType.GetType().GetMember(authRequest.RequestDeviceType.ToString())
|
||||||
.FirstOrDefault()?.GetCustomAttribute<DisplayAttribute>()?.GetName();
|
.FirstOrDefault()?.GetCustomAttribute<DisplayAttribute>()?.GetName();
|
||||||
RequestIpAddress = authRequest.RequestIpAddress;
|
RequestIpAddress = authRequest.RequestIpAddress;
|
||||||
@ -30,6 +32,7 @@ public class AuthRequestResponseModel : ResponseModel
|
|||||||
|
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
public string PublicKey { get; set; }
|
public string PublicKey { get; set; }
|
||||||
|
public DeviceType RequestDeviceTypeValue { get; set; }
|
||||||
public string RequestDeviceType { get; set; }
|
public string RequestDeviceType { get; set; }
|
||||||
public string RequestIpAddress { get; set; }
|
public string RequestIpAddress { get; set; }
|
||||||
public string Key { get; set; }
|
public string Key { get; set; }
|
||||||
|
@ -7,12 +7,14 @@ public class OrganizationCollectionManagementUpdateRequestModel
|
|||||||
{
|
{
|
||||||
public bool LimitCollectionCreation { get; set; }
|
public bool LimitCollectionCreation { get; set; }
|
||||||
public bool LimitCollectionDeletion { get; set; }
|
public bool LimitCollectionDeletion { get; set; }
|
||||||
|
public bool LimitItemDeletion { get; set; }
|
||||||
public bool AllowAdminAccessToAllCollectionItems { get; set; }
|
public bool AllowAdminAccessToAllCollectionItems { get; set; }
|
||||||
|
|
||||||
public virtual Organization ToOrganization(Organization existingOrganization, IFeatureService featureService)
|
public virtual Organization ToOrganization(Organization existingOrganization, IFeatureService featureService)
|
||||||
{
|
{
|
||||||
existingOrganization.LimitCollectionCreation = LimitCollectionCreation;
|
existingOrganization.LimitCollectionCreation = LimitCollectionCreation;
|
||||||
existingOrganization.LimitCollectionDeletion = LimitCollectionDeletion;
|
existingOrganization.LimitCollectionDeletion = LimitCollectionDeletion;
|
||||||
|
existingOrganization.LimitItemDeletion = LimitItemDeletion;
|
||||||
existingOrganization.AllowAdminAccessToAllCollectionItems = AllowAdminAccessToAllCollectionItems;
|
existingOrganization.AllowAdminAccessToAllCollectionItems = AllowAdminAccessToAllCollectionItems;
|
||||||
return existingOrganization;
|
return existingOrganization;
|
||||||
}
|
}
|
||||||
|
@ -1097,7 +1097,7 @@ public class CiphersController : Controller
|
|||||||
|
|
||||||
[HttpDelete("{id}/attachment/{attachmentId}")]
|
[HttpDelete("{id}/attachment/{attachmentId}")]
|
||||||
[HttpPost("{id}/attachment/{attachmentId}/delete")]
|
[HttpPost("{id}/attachment/{attachmentId}/delete")]
|
||||||
public async Task DeleteAttachment(Guid id, string attachmentId)
|
public async Task<DeleteAttachmentResponseData> DeleteAttachment(Guid id, string attachmentId)
|
||||||
{
|
{
|
||||||
var userId = _userService.GetProperUserId(User).Value;
|
var userId = _userService.GetProperUserId(User).Value;
|
||||||
var cipher = await GetByIdAsync(id, userId);
|
var cipher = await GetByIdAsync(id, userId);
|
||||||
@ -1106,7 +1106,7 @@ public class CiphersController : Controller
|
|||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
await _cipherService.DeleteAttachmentAsync(cipher, attachmentId, userId, false);
|
return await _cipherService.DeleteAttachmentAsync(cipher, attachmentId, userId, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpDelete("{id}/attachment/{attachmentId}/admin")]
|
[HttpDelete("{id}/attachment/{attachmentId}/admin")]
|
||||||
|
@ -23,6 +23,7 @@ public class OrganizationAbility
|
|||||||
UsePolicies = organization.UsePolicies;
|
UsePolicies = organization.UsePolicies;
|
||||||
LimitCollectionCreation = organization.LimitCollectionCreation;
|
LimitCollectionCreation = organization.LimitCollectionCreation;
|
||||||
LimitCollectionDeletion = organization.LimitCollectionDeletion;
|
LimitCollectionDeletion = organization.LimitCollectionDeletion;
|
||||||
|
LimitItemDeletion = organization.LimitItemDeletion;
|
||||||
AllowAdminAccessToAllCollectionItems = organization.AllowAdminAccessToAllCollectionItems;
|
AllowAdminAccessToAllCollectionItems = organization.AllowAdminAccessToAllCollectionItems;
|
||||||
UseRiskInsights = organization.UseRiskInsights;
|
UseRiskInsights = organization.UseRiskInsights;
|
||||||
}
|
}
|
||||||
@ -41,6 +42,7 @@ public class OrganizationAbility
|
|||||||
public bool UsePolicies { get; set; }
|
public bool UsePolicies { get; set; }
|
||||||
public bool LimitCollectionCreation { get; set; }
|
public bool LimitCollectionCreation { get; set; }
|
||||||
public bool LimitCollectionDeletion { get; set; }
|
public bool LimitCollectionDeletion { get; set; }
|
||||||
|
public bool LimitItemDeletion { get; set; }
|
||||||
public bool AllowAdminAccessToAllCollectionItems { get; set; }
|
public bool AllowAdminAccessToAllCollectionItems { get; set; }
|
||||||
public bool UseRiskInsights { get; set; }
|
public bool UseRiskInsights { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@ public class OrganizationUserOrganizationDetails
|
|||||||
public int? SmServiceAccounts { get; set; }
|
public int? SmServiceAccounts { get; set; }
|
||||||
public bool LimitCollectionCreation { get; set; }
|
public bool LimitCollectionCreation { get; set; }
|
||||||
public bool LimitCollectionDeletion { get; set; }
|
public bool LimitCollectionDeletion { get; set; }
|
||||||
|
public bool LimitItemDeletion { get; set; }
|
||||||
public bool AllowAdminAccessToAllCollectionItems { get; set; }
|
public bool AllowAdminAccessToAllCollectionItems { get; set; }
|
||||||
public bool UseRiskInsights { get; set; }
|
public bool UseRiskInsights { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -146,6 +146,7 @@ public class SelfHostedOrganizationDetails : Organization
|
|||||||
OwnersNotifiedOfAutoscaling = OwnersNotifiedOfAutoscaling,
|
OwnersNotifiedOfAutoscaling = OwnersNotifiedOfAutoscaling,
|
||||||
LimitCollectionCreation = LimitCollectionCreation,
|
LimitCollectionCreation = LimitCollectionCreation,
|
||||||
LimitCollectionDeletion = LimitCollectionDeletion,
|
LimitCollectionDeletion = LimitCollectionDeletion,
|
||||||
|
LimitItemDeletion = LimitItemDeletion,
|
||||||
AllowAdminAccessToAllCollectionItems = AllowAdminAccessToAllCollectionItems,
|
AllowAdminAccessToAllCollectionItems = AllowAdminAccessToAllCollectionItems,
|
||||||
Status = Status
|
Status = Status
|
||||||
};
|
};
|
||||||
|
@ -42,6 +42,7 @@ public class ProviderUserOrganizationDetails
|
|||||||
public PlanType PlanType { get; set; }
|
public PlanType PlanType { get; set; }
|
||||||
public bool LimitCollectionCreation { get; set; }
|
public bool LimitCollectionCreation { get; set; }
|
||||||
public bool LimitCollectionDeletion { get; set; }
|
public bool LimitCollectionDeletion { get; set; }
|
||||||
|
public bool LimitItemDeletion { get; set; }
|
||||||
public bool AllowAdminAccessToAllCollectionItems { get; set; }
|
public bool AllowAdminAccessToAllCollectionItems { get; set; }
|
||||||
public bool UseRiskInsights { get; set; }
|
public bool UseRiskInsights { get; set; }
|
||||||
public ProviderType ProviderType { get; set; }
|
public ProviderType ProviderType { get; set; }
|
||||||
|
@ -168,6 +168,9 @@ public static class FeatureFlagKeys
|
|||||||
public const string EnablePasswordManagerSyncAndroid = "enable-password-manager-sync-android";
|
public const string EnablePasswordManagerSyncAndroid = "enable-password-manager-sync-android";
|
||||||
public const string EnablePasswordManagerSynciOS = "enable-password-manager-sync-ios";
|
public const string EnablePasswordManagerSynciOS = "enable-password-manager-sync-ios";
|
||||||
public const string AccountDeprovisioningBanner = "pm-17120-account-deprovisioning-admin-console-banner";
|
public const string AccountDeprovisioningBanner = "pm-17120-account-deprovisioning-admin-console-banner";
|
||||||
|
public const string SingleTapPasskeyCreation = "single-tap-passkey-creation";
|
||||||
|
public const string SingleTapPasskeyAuthentication = "single-tap-passkey-authentication";
|
||||||
|
public const string EnableRiskInsightsNotifications = "enable-risk-insights-notifications";
|
||||||
|
|
||||||
public static List<string> GetAllKeys()
|
public static List<string> GetAllKeys()
|
||||||
{
|
{
|
||||||
|
@ -62,4 +62,5 @@ public class OrganizationCollectionManagementPushNotification
|
|||||||
public Guid OrganizationId { get; init; }
|
public Guid OrganizationId { get; init; }
|
||||||
public bool LimitCollectionCreation { get; init; }
|
public bool LimitCollectionCreation { get; init; }
|
||||||
public bool LimitCollectionDeletion { get; init; }
|
public bool LimitCollectionDeletion { get; init; }
|
||||||
|
public bool LimitItemDeletion { get; init; }
|
||||||
}
|
}
|
||||||
|
@ -246,7 +246,8 @@ public class NotificationHubPushNotificationService : IPushNotificationService
|
|||||||
{
|
{
|
||||||
OrganizationId = organization.Id,
|
OrganizationId = organization.Id,
|
||||||
LimitCollectionCreation = organization.LimitCollectionCreation,
|
LimitCollectionCreation = organization.LimitCollectionCreation,
|
||||||
LimitCollectionDeletion = organization.LimitCollectionDeletion
|
LimitCollectionDeletion = organization.LimitCollectionDeletion,
|
||||||
|
LimitItemDeletion = organization.LimitItemDeletion
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
@ -239,6 +239,7 @@ public class AzureQueuePushNotificationService : IPushNotificationService
|
|||||||
{
|
{
|
||||||
OrganizationId = organization.Id,
|
OrganizationId = organization.Id,
|
||||||
LimitCollectionCreation = organization.LimitCollectionCreation,
|
LimitCollectionCreation = organization.LimitCollectionCreation,
|
||||||
LimitCollectionDeletion = organization.LimitCollectionDeletion
|
LimitCollectionDeletion = organization.LimitCollectionDeletion,
|
||||||
|
LimitItemDeletion = organization.LimitItemDeletion
|
||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
|
@ -248,6 +248,7 @@ public class NotificationsApiPushNotificationService : BaseIdentityClientService
|
|||||||
{
|
{
|
||||||
OrganizationId = organization.Id,
|
OrganizationId = organization.Id,
|
||||||
LimitCollectionCreation = organization.LimitCollectionCreation,
|
LimitCollectionCreation = organization.LimitCollectionCreation,
|
||||||
LimitCollectionDeletion = organization.LimitCollectionDeletion
|
LimitCollectionDeletion = organization.LimitCollectionDeletion,
|
||||||
|
LimitItemDeletion = organization.LimitItemDeletion
|
||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
|
@ -273,7 +273,8 @@ public class RelayPushNotificationService : BaseIdentityClientService, IPushNoti
|
|||||||
{
|
{
|
||||||
OrganizationId = organization.Id,
|
OrganizationId = organization.Id,
|
||||||
LimitCollectionCreation = organization.LimitCollectionCreation,
|
LimitCollectionCreation = organization.LimitCollectionCreation,
|
||||||
LimitCollectionDeletion = organization.LimitCollectionDeletion
|
LimitCollectionDeletion = organization.LimitCollectionDeletion,
|
||||||
|
LimitItemDeletion = organization.LimitItemDeletion
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
13
src/Core/Vault/Models/Data/DeleteAttachmentReponseData.cs
Normal file
13
src/Core/Vault/Models/Data/DeleteAttachmentReponseData.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using Bit.Core.Vault.Entities;
|
||||||
|
|
||||||
|
namespace Bit.Core.Vault.Models.Data;
|
||||||
|
|
||||||
|
public class DeleteAttachmentResponseData
|
||||||
|
{
|
||||||
|
public Cipher Cipher { get; set; }
|
||||||
|
|
||||||
|
public DeleteAttachmentResponseData(Cipher cipher)
|
||||||
|
{
|
||||||
|
Cipher = cipher;
|
||||||
|
}
|
||||||
|
}
|
@ -17,7 +17,7 @@ public interface ICipherService
|
|||||||
string attachmentId, Guid organizationShareId);
|
string attachmentId, Guid organizationShareId);
|
||||||
Task DeleteAsync(Cipher cipher, Guid deletingUserId, bool orgAdmin = false);
|
Task DeleteAsync(Cipher cipher, Guid deletingUserId, bool orgAdmin = false);
|
||||||
Task DeleteManyAsync(IEnumerable<Guid> cipherIds, Guid deletingUserId, Guid? organizationId = null, bool orgAdmin = false);
|
Task DeleteManyAsync(IEnumerable<Guid> cipherIds, Guid deletingUserId, Guid? organizationId = null, bool orgAdmin = false);
|
||||||
Task DeleteAttachmentAsync(Cipher cipher, string attachmentId, Guid deletingUserId, bool orgAdmin = false);
|
Task<DeleteAttachmentResponseData> DeleteAttachmentAsync(Cipher cipher, string attachmentId, Guid deletingUserId, bool orgAdmin = false);
|
||||||
Task PurgeAsync(Guid organizationId);
|
Task PurgeAsync(Guid organizationId);
|
||||||
Task MoveManyAsync(IEnumerable<Guid> cipherIds, Guid? destinationFolderId, Guid movingUserId);
|
Task MoveManyAsync(IEnumerable<Guid> cipherIds, Guid? destinationFolderId, Guid movingUserId);
|
||||||
Task SaveFolderAsync(Folder folder);
|
Task SaveFolderAsync(Folder folder);
|
||||||
|
@ -210,6 +210,11 @@ public class CipherService : ICipherService
|
|||||||
AttachmentData = JsonSerializer.Serialize(data)
|
AttachmentData = JsonSerializer.Serialize(data)
|
||||||
});
|
});
|
||||||
cipher.AddAttachment(attachmentId, data);
|
cipher.AddAttachment(attachmentId, data);
|
||||||
|
|
||||||
|
// Update the revision date when an attachment is added
|
||||||
|
cipher.RevisionDate = DateTime.UtcNow;
|
||||||
|
await _cipherRepository.ReplaceAsync((CipherDetails)cipher);
|
||||||
|
|
||||||
await _pushService.PushSyncCipherUpdateAsync(cipher, null);
|
await _pushService.PushSyncCipherUpdateAsync(cipher, null);
|
||||||
|
|
||||||
return (attachmentId, uploadUrl);
|
return (attachmentId, uploadUrl);
|
||||||
@ -259,6 +264,10 @@ public class CipherService : ICipherService
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the revision date when an attachment is added
|
||||||
|
cipher.RevisionDate = DateTime.UtcNow;
|
||||||
|
await _cipherRepository.ReplaceAsync((CipherDetails)cipher);
|
||||||
|
|
||||||
// push
|
// push
|
||||||
await _pushService.PushSyncCipherUpdateAsync(cipher, null);
|
await _pushService.PushSyncCipherUpdateAsync(cipher, null);
|
||||||
}
|
}
|
||||||
@ -441,7 +450,7 @@ public class CipherService : ICipherService
|
|||||||
await _pushService.PushSyncCiphersAsync(deletingUserId);
|
await _pushService.PushSyncCiphersAsync(deletingUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteAttachmentAsync(Cipher cipher, string attachmentId, Guid deletingUserId,
|
public async Task<DeleteAttachmentResponseData> DeleteAttachmentAsync(Cipher cipher, string attachmentId, Guid deletingUserId,
|
||||||
bool orgAdmin = false)
|
bool orgAdmin = false)
|
||||||
{
|
{
|
||||||
if (!orgAdmin && !(await UserCanEditAsync(cipher, deletingUserId)))
|
if (!orgAdmin && !(await UserCanEditAsync(cipher, deletingUserId)))
|
||||||
@ -454,7 +463,7 @@ public class CipherService : ICipherService
|
|||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
await DeleteAttachmentAsync(cipher, cipher.GetAttachments()[attachmentId]);
|
return await DeleteAttachmentAsync(cipher, cipher.GetAttachments()[attachmentId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task PurgeAsync(Guid organizationId)
|
public async Task PurgeAsync(Guid organizationId)
|
||||||
@ -834,11 +843,11 @@ public class CipherService : ICipherService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DeleteAttachmentAsync(Cipher cipher, CipherAttachment.MetaData attachmentData)
|
private async Task<DeleteAttachmentResponseData> DeleteAttachmentAsync(Cipher cipher, CipherAttachment.MetaData attachmentData)
|
||||||
{
|
{
|
||||||
if (attachmentData == null || string.IsNullOrWhiteSpace(attachmentData.AttachmentId))
|
if (attachmentData == null || string.IsNullOrWhiteSpace(attachmentData.AttachmentId))
|
||||||
{
|
{
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _cipherRepository.DeleteAttachmentAsync(cipher.Id, attachmentData.AttachmentId);
|
await _cipherRepository.DeleteAttachmentAsync(cipher.Id, attachmentData.AttachmentId);
|
||||||
@ -846,8 +855,14 @@ public class CipherService : ICipherService
|
|||||||
await _attachmentStorageService.DeleteAttachmentAsync(cipher.Id, attachmentData);
|
await _attachmentStorageService.DeleteAttachmentAsync(cipher.Id, attachmentData);
|
||||||
await _eventService.LogCipherEventAsync(cipher, Bit.Core.Enums.EventType.Cipher_AttachmentDeleted);
|
await _eventService.LogCipherEventAsync(cipher, Bit.Core.Enums.EventType.Cipher_AttachmentDeleted);
|
||||||
|
|
||||||
|
// Update the revision date when an attachment is deleted
|
||||||
|
cipher.RevisionDate = DateTime.UtcNow;
|
||||||
|
await _cipherRepository.ReplaceAsync((CipherDetails)cipher);
|
||||||
|
|
||||||
// push
|
// push
|
||||||
await _pushService.PushSyncCipherUpdateAsync(cipher, null);
|
await _pushService.PushSyncCipherUpdateAsync(cipher, null);
|
||||||
|
|
||||||
|
return new DeleteAttachmentResponseData(cipher);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ValidateCipherEditForAttachmentAsync(Cipher cipher, Guid savingUserId, bool orgAdmin,
|
private async Task ValidateCipherEditForAttachmentAsync(Cipher cipher, Guid savingUserId, bool orgAdmin,
|
||||||
|
@ -20,5 +20,6 @@ public static class VaultServiceCollectionExtensions
|
|||||||
services.AddScoped<IGetTaskDetailsForUserQuery, GetTaskDetailsForUserQuery>();
|
services.AddScoped<IGetTaskDetailsForUserQuery, GetTaskDetailsForUserQuery>();
|
||||||
services.AddScoped<IMarkTaskAsCompleteCommand, MarkTaskAsCompletedCommand>();
|
services.AddScoped<IMarkTaskAsCompleteCommand, MarkTaskAsCompletedCommand>();
|
||||||
services.AddScoped<IGetCipherPermissionsForUserQuery, GetCipherPermissionsForUserQuery>();
|
services.AddScoped<IGetCipherPermissionsForUserQuery, GetCipherPermissionsForUserQuery>();
|
||||||
|
services.AddScoped<IGetTasksForOrganizationQuery, GetTasksForOrganizationQuery>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,7 @@ public class OrganizationRepository : Repository<Core.AdminConsole.Entities.Orga
|
|||||||
UsePolicies = e.UsePolicies,
|
UsePolicies = e.UsePolicies,
|
||||||
LimitCollectionCreation = e.LimitCollectionCreation,
|
LimitCollectionCreation = e.LimitCollectionCreation,
|
||||||
LimitCollectionDeletion = e.LimitCollectionDeletion,
|
LimitCollectionDeletion = e.LimitCollectionDeletion,
|
||||||
|
LimitItemDeletion = e.LimitItemDeletion,
|
||||||
AllowAdminAccessToAllCollectionItems = e.AllowAdminAccessToAllCollectionItems,
|
AllowAdminAccessToAllCollectionItems = e.AllowAdminAccessToAllCollectionItems,
|
||||||
UseRiskInsights = e.UseRiskInsights
|
UseRiskInsights = e.UseRiskInsights
|
||||||
}).ToListAsync();
|
}).ToListAsync();
|
||||||
|
@ -68,6 +68,7 @@ public class OrganizationUserOrganizationDetailsViewQuery : IQuery<OrganizationU
|
|||||||
SmServiceAccounts = o.SmServiceAccounts,
|
SmServiceAccounts = o.SmServiceAccounts,
|
||||||
LimitCollectionCreation = o.LimitCollectionCreation,
|
LimitCollectionCreation = o.LimitCollectionCreation,
|
||||||
LimitCollectionDeletion = o.LimitCollectionDeletion,
|
LimitCollectionDeletion = o.LimitCollectionDeletion,
|
||||||
|
LimitItemDeletion = o.LimitItemDeletion,
|
||||||
AllowAdminAccessToAllCollectionItems = o.AllowAdminAccessToAllCollectionItems,
|
AllowAdminAccessToAllCollectionItems = o.AllowAdminAccessToAllCollectionItems,
|
||||||
UseRiskInsights = o.UseRiskInsights,
|
UseRiskInsights = o.UseRiskInsights,
|
||||||
};
|
};
|
||||||
|
@ -46,6 +46,7 @@ public class ProviderUserOrganizationDetailsViewQuery : IQuery<ProviderUserOrgan
|
|||||||
PlanType = x.o.PlanType,
|
PlanType = x.o.PlanType,
|
||||||
LimitCollectionCreation = x.o.LimitCollectionCreation,
|
LimitCollectionCreation = x.o.LimitCollectionCreation,
|
||||||
LimitCollectionDeletion = x.o.LimitCollectionDeletion,
|
LimitCollectionDeletion = x.o.LimitCollectionDeletion,
|
||||||
|
LimitItemDeletion = x.o.LimitItemDeletion,
|
||||||
AllowAdminAccessToAllCollectionItems = x.o.AllowAdminAccessToAllCollectionItems,
|
AllowAdminAccessToAllCollectionItems = x.o.AllowAdminAccessToAllCollectionItems,
|
||||||
UseRiskInsights = x.o.UseRiskInsights,
|
UseRiskInsights = x.o.UseRiskInsights,
|
||||||
ProviderType = x.p.Type
|
ProviderType = x.p.Type
|
||||||
|
@ -123,24 +123,74 @@ public class OrganizationUsersControllerTests
|
|||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[BitAutoData]
|
[BitAutoData]
|
||||||
public async Task Accept_RequireMasterPasswordReset(Guid orgId, Guid orgUserId,
|
public async Task Accept_WhenOrganizationUsePoliciesIsEnabledAndResetPolicyIsEnabled_ShouldHandleResetPassword(Guid orgId, Guid orgUserId,
|
||||||
OrganizationUserAcceptRequestModel model, User user, SutProvider<OrganizationUsersController> sutProvider)
|
OrganizationUserAcceptRequestModel model, User user, SutProvider<OrganizationUsersController> sutProvider)
|
||||||
{
|
{
|
||||||
|
// Arrange
|
||||||
|
var applicationCacheService = sutProvider.GetDependency<IApplicationCacheService>();
|
||||||
|
applicationCacheService.GetOrganizationAbilityAsync(orgId).Returns(new OrganizationAbility { UsePolicies = true });
|
||||||
|
|
||||||
var policy = new Policy
|
var policy = new Policy
|
||||||
{
|
{
|
||||||
Enabled = true,
|
Enabled = true,
|
||||||
Data = CoreHelpers.ClassToJsonData(new ResetPasswordDataModel { AutoEnrollEnabled = true, }),
|
Data = CoreHelpers.ClassToJsonData(new ResetPasswordDataModel { AutoEnrollEnabled = true, }),
|
||||||
};
|
};
|
||||||
sutProvider.GetDependency<IUserService>().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user);
|
var userService = sutProvider.GetDependency<IUserService>();
|
||||||
sutProvider.GetDependency<IPolicyRepository>().GetByOrganizationIdTypeAsync(orgId,
|
userService.GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user);
|
||||||
|
|
||||||
|
|
||||||
|
var policyRepository = sutProvider.GetDependency<IPolicyRepository>();
|
||||||
|
policyRepository.GetByOrganizationIdTypeAsync(orgId,
|
||||||
PolicyType.ResetPassword).Returns(policy);
|
PolicyType.ResetPassword).Returns(policy);
|
||||||
|
|
||||||
|
// Act
|
||||||
await sutProvider.Sut.Accept(orgId, orgUserId, model);
|
await sutProvider.Sut.Accept(orgId, orgUserId, model);
|
||||||
|
|
||||||
|
// Assert
|
||||||
await sutProvider.GetDependency<IAcceptOrgUserCommand>().Received(1)
|
await sutProvider.GetDependency<IAcceptOrgUserCommand>().Received(1)
|
||||||
.AcceptOrgUserByEmailTokenAsync(orgUserId, user, model.Token, sutProvider.GetDependency<IUserService>());
|
.AcceptOrgUserByEmailTokenAsync(orgUserId, user, model.Token, userService);
|
||||||
await sutProvider.GetDependency<IOrganizationService>().Received(1)
|
await sutProvider.GetDependency<IOrganizationService>().Received(1)
|
||||||
.UpdateUserResetPasswordEnrollmentAsync(orgId, user.Id, model.ResetPasswordKey, user.Id);
|
.UpdateUserResetPasswordEnrollmentAsync(orgId, user.Id, model.ResetPasswordKey, user.Id);
|
||||||
|
|
||||||
|
await userService.Received(1).GetUserByPrincipalAsync(default);
|
||||||
|
await applicationCacheService.Received(1).GetOrganizationAbilityAsync(orgId);
|
||||||
|
await policyRepository.Received(1).GetByOrganizationIdTypeAsync(orgId, PolicyType.ResetPassword);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[BitAutoData]
|
||||||
|
public async Task Accept_WhenOrganizationUsePoliciesIsDisabled_ShouldNotHandleResetPassword(Guid orgId, Guid orgUserId,
|
||||||
|
OrganizationUserAcceptRequestModel model, User user, SutProvider<OrganizationUsersController> sutProvider)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var applicationCacheService = sutProvider.GetDependency<IApplicationCacheService>();
|
||||||
|
applicationCacheService.GetOrganizationAbilityAsync(orgId).Returns(new OrganizationAbility { UsePolicies = false });
|
||||||
|
|
||||||
|
var policy = new Policy
|
||||||
|
{
|
||||||
|
Enabled = true,
|
||||||
|
Data = CoreHelpers.ClassToJsonData(new ResetPasswordDataModel { AutoEnrollEnabled = true, }),
|
||||||
|
};
|
||||||
|
var userService = sutProvider.GetDependency<IUserService>();
|
||||||
|
userService.GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user);
|
||||||
|
|
||||||
|
var policyRepository = sutProvider.GetDependency<IPolicyRepository>();
|
||||||
|
policyRepository.GetByOrganizationIdTypeAsync(orgId,
|
||||||
|
PolicyType.ResetPassword).Returns(policy);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await sutProvider.Sut.Accept(orgId, orgUserId, model);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
await userService.Received(1).GetUserByPrincipalAsync(default);
|
||||||
|
await sutProvider.GetDependency<IAcceptOrgUserCommand>().Received(1)
|
||||||
|
.AcceptOrgUserByEmailTokenAsync(orgUserId, user, model.Token, userService);
|
||||||
|
await sutProvider.GetDependency<IOrganizationService>().Received(0)
|
||||||
|
.UpdateUserResetPasswordEnrollmentAsync(orgId, user.Id, model.ResetPasswordKey, user.Id);
|
||||||
|
|
||||||
|
await policyRepository.Received(0).GetByOrganizationIdTypeAsync(orgId, PolicyType.ResetPassword);
|
||||||
|
await applicationCacheService.Received(1).GetOrganizationAbilityAsync(orgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
|
Loading…
Reference in New Issue
Block a user