Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Core/AdminConsole/Enums/PolicyType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public enum PolicyType : byte
SingleOrg = 3,
RequireSso = 4,
OrganizationDataOwnership = 5,
[Obsolete("Consolidated into SendOptions (type 7). Use SendOptions policy with SendPolicyData.DisableSend.")]
DisableSend = 6,
SendOptions = 7,
ResetPassword = 8,
Expand Down Expand Up @@ -41,7 +42,7 @@ public static string GetName(this PolicyType type)
PolicyType.RequireSso => "Require single sign-on authentication",
PolicyType.OrganizationDataOwnership => "Enforce organization data ownership",
PolicyType.DisableSend => "Remove Send",
PolicyType.SendOptions => "Send options",
PolicyType.SendOptions => "Send",
PolicyType.ResetPassword => "Account recovery administration",
PolicyType.MaximumVaultTimeout => "Vault timeout",
PolicyType.DisablePersonalVaultExport => "Remove individual vault export",
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.ComponentModel.DataAnnotations;

namespace Bit.Core.AdminConsole.Models.Data.Organizations.Policies;

public class SendPolicyData : IPolicyDataModel
{
[Display(Name = "DisableSend")]
public bool DisableSend { get; set; }

[Display(Name = "DisableHideEmail")]
public bool DisableHideEmail { get; set; }

[Display(Name = "DisableNoAuthSends")]
public bool DisableNoAuthSends { get; set; }

[Display(Name = "DisablePasswordSends")]
public bool DisablePasswordSends { get; set; }

[Display(Name = "DisableEmailVerifiedSends")]
public bool DisableEmailVerifiedSends { get; set; }
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using Bit.Core.AdminConsole.Enums;
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;

namespace Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;

/// <summary>
/// Policy requirements for the Send policy.
/// </summary>
public class SendPolicyRequirement : IPolicyRequirement
{
/// <summary>
/// Indicates whether Send is disabled for the org. If true, the org users should not be able to create or edit Sends.
/// They may still delete existing Sends.
/// </summary>
public bool DisableSend { get; init; }

/// <summary>
/// Indicates whether the org users are prohibited from hiding their email from the recipient of a Send.
/// </summary>
public bool DisableHideEmail { get; init; }

/// <summary>
/// Indicates whether the org users are prohibited from creating or editing Sends that use no authorization.
/// </summary>
public bool DisableNoAuthSends { get; init; }

/// <summary>
/// Indicates whether the org users are prohibited from creating or editing Sends that use password authorization.
/// </summary>
public bool DisablePasswordSends { get; init; }

/// <summary>
/// Indicates whether the org users are prohibited from creating or editing Sends that use email verification.
/// </summary>
public bool DisableEmailVerifiedSends { get; init; }
}

public class SendPolicyRequirementFactory : BasePolicyRequirementFactory<SendPolicyRequirement>
{
public override PolicyType PolicyType => PolicyType.SendOptions;

public override SendPolicyRequirement Create(IEnumerable<PolicyDetails> policyDetails)
{
return policyDetails
.Select(p => p.GetDataModel<SendPolicyData>())
.Aggregate(
new SendPolicyRequirement(),
(result, data) =>
{
var disableNoAuthSends = result.DisableNoAuthSends || data.DisableNoAuthSends;
var disablePasswordSends = result.DisablePasswordSends || data.DisablePasswordSends;
var disableEmailVerifiedSends = result.DisableEmailVerifiedSends || data.DisableEmailVerifiedSends;
return new SendPolicyRequirement
{
DisableSend = result.DisableSend || data.DisableSend
|| (disableNoAuthSends && disablePasswordSends && disableEmailVerifiedSends),
DisableHideEmail = result.DisableHideEmail || data.DisableHideEmail,
DisableNoAuthSends = disableNoAuthSends,
DisablePasswordSends = disablePasswordSends,
DisableEmailVerifiedSends = disableEmailVerifiedSends,
};
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ private static void AddPolicyUpdateEvents(this IServiceCollection services)

private static void AddPolicyRequirements(this IServiceCollection services)
{
services.AddScoped<IPolicyRequirementFactory<IPolicyRequirement>, DisableSendPolicyRequirementFactory>();
services.AddScoped<IPolicyRequirementFactory<IPolicyRequirement>, SendOptionsPolicyRequirementFactory>();
services.AddScoped<IPolicyRequirementFactory<IPolicyRequirement>, SendPolicyRequirementFactory>();
services.AddScoped<IPolicyRequirementFactory<IPolicyRequirement>, ResetPasswordPolicyRequirementFactory>();
services.AddScoped<IPolicyRequirementFactory<IPolicyRequirement>, OrganizationDataOwnershipPolicyRequirementFactory>();
services.AddScoped<IPolicyRequirementFactory<IPolicyRequirement>, RequireSsoPolicyRequirementFactory>();
Expand Down
2 changes: 1 addition & 1 deletion src/Core/AdminConsole/Utilities/PolicyDataValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public static class PolicyDataValidator
ValidateModel(masterPasswordData, policyType);
break;
case PolicyType.SendOptions:
CoreHelpers.LoadClassFromJsonData<SendOptionsPolicyData>(json);
CoreHelpers.LoadClassFromJsonData<SendPolicyData>(json);
break;
case PolicyType.ResetPassword:
CoreHelpers.LoadClassFromJsonData<ResetPasswordDataModel>(json);
Expand Down
62 changes: 52 additions & 10 deletions src/Core/Tools/SendFeatures/Services/SendValidationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Bit.Core.Services;
using Bit.Core.Settings;
using Bit.Core.Tools.Entities;
using Bit.Core.Tools.Enums;
using Bit.Core.Utilities;

namespace Bit.Core.Tools.Services;
Expand Down Expand Up @@ -74,13 +75,37 @@ public async Task ValidateUserCanSaveAsync(Guid? userId, Send send)
throw new BadRequestException("Due to an Enterprise Policy, you are only able to delete an existing Send.");
}

if (send.HideEmail.GetValueOrDefault())
var sendOptionsPolicies = await _policyService.GetPoliciesApplicableToUserAsync(userId.Value, PolicyType.SendOptions);
var sendOptionsPolicyData = sendOptionsPolicies
.Select(p => CoreHelpers.LoadClassFromJsonData<SendPolicyData>(p.PolicyData))
.Where(d => d != null)
.ToList();

if (sendOptionsPolicyData.Any(d => d.DisableSend))
{
var sendOptionsPolicies = await _policyService.GetPoliciesApplicableToUserAsync(userId.Value, PolicyType.SendOptions);
if (sendOptionsPolicies.Any(p => CoreHelpers.LoadClassFromJsonData<SendOptionsPolicyData>(p.PolicyData)?.DisableHideEmail ?? false))
{
throw new BadRequestException("Due to an Enterprise Policy, you are not allowed to hide your email address from recipients when creating or editing a Send.");
}
throw new BadRequestException("Due to an Enterprise Policy, you are only able to delete an existing Send.");
}

if (send.HideEmail.GetValueOrDefault() && sendOptionsPolicyData.Any(d => d.DisableHideEmail))
{
throw new BadRequestException("Due to an Enterprise Policy, you are not allowed to hide your email address from recipients when creating or editing a Send.");
}

var authType = send.AuthType ?? AuthType.None;

if (authType == AuthType.None && sendOptionsPolicyData.Any(d => d.DisableNoAuthSends))
{
throw new BadRequestException("Due to an Enterprise Policy, you are not allowed to create or edit Sends without authentication.");
}

if (authType == AuthType.Password && sendOptionsPolicyData.Any(d => d.DisablePasswordSends))
{
throw new BadRequestException("Due to an Enterprise Policy, you are not allowed to create or edit Sends that use password authentication.");
}

if (authType == AuthType.Email && sendOptionsPolicyData.Any(d => d.DisableEmailVerifiedSends))
{
throw new BadRequestException("Due to an Enterprise Policy, you are not allowed to create or edit Sends that use email verification.");
}
}

Expand All @@ -91,17 +116,34 @@ public async Task ValidateUserCanSaveAsync_vNext(Guid? userId, Send send)
return;
}

var disableSendRequirement = await _policyRequirementQuery.GetAsync<DisableSendPolicyRequirement>(userId.Value);
if (disableSendRequirement.DisableSend)
var sendRequirement = await _policyRequirementQuery.GetAsync<SendPolicyRequirement>(userId.Value);

if (sendRequirement.DisableSend)
{
throw new BadRequestException("Due to an Enterprise Policy, you are only able to delete an existing Send.");
}

var sendOptionsRequirement = await _policyRequirementQuery.GetAsync<SendOptionsPolicyRequirement>(userId.Value);
if (sendOptionsRequirement.DisableHideEmail && send.HideEmail.GetValueOrDefault())
if (sendRequirement.DisableHideEmail && send.HideEmail.GetValueOrDefault())
{
throw new BadRequestException("Due to an Enterprise Policy, you are not allowed to hide your email address from recipients when creating or editing a Send.");
}

var authType = send.AuthType ?? AuthType.None;

if (sendRequirement.DisableNoAuthSends && authType == AuthType.None)
{
throw new BadRequestException("Due to an Enterprise Policy, you are not allowed to create or edit Sends without authentication.");
}

if (sendRequirement.DisablePasswordSends && authType == AuthType.Password)
{
throw new BadRequestException("Due to an Enterprise Policy, you are not allowed to create or edit Sends that use password authentication.");
}

if (sendRequirement.DisableEmailVerifiedSends && authType == AuthType.Email)
{
throw new BadRequestException("Due to an Enterprise Policy, you are not allowed to create or edit Sends that use email verification.");
}
}

public async Task<long> StorageRemainingForSendAsync(Send send)
Expand Down

This file was deleted.

This file was deleted.

Loading
Loading