mirror of
https://github.com/bitwarden/server.git
synced 2024-11-28 13:15:12 +01:00
Hide email address in Sends (#1234)
* Add send HideEmail to tables and models * Respect HideEmail setting for Sends * Recreate SendView to include new HideEmail column * Enforce new Send policy * Insert default value for new HideEmail column * Delete c95d7598-71cc-4eab-8b08-aced0045198b.json * Remove unrelated files * Revert disableSendPolicy, add sendOptionsPolicy * Minor style fixes * Update SQL project with Send.HideEmail column * unit test SendOptionsPolicy.DisableHideEmail * Add SendOptionsPolicy to Portal * Make HideEmail nullable, fix migrator script * Remove NOT NULL constraint from HideEmail * Fix style * Make HideEmail nullable * minor fixes to model and error message * Move SendOptionsExemption banner Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
This commit is contained in:
parent
94249747b4
commit
688cc00d48
@ -137,6 +137,7 @@ namespace Bit.Portal.Controllers
|
|||||||
case PolicyType.TwoFactorAuthentication:
|
case PolicyType.TwoFactorAuthentication:
|
||||||
case PolicyType.PersonalOwnership:
|
case PolicyType.PersonalOwnership:
|
||||||
case PolicyType.DisableSend:
|
case PolicyType.DisableSend:
|
||||||
|
case PolicyType.SendOptions:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PolicyType.SingleOrg:
|
case PolicyType.SingleOrg:
|
||||||
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Models.Table;
|
using Bit.Core.Models.Table;
|
||||||
|
using Bit.Core.Models.Data;
|
||||||
using Bit.Core.Services;
|
using Bit.Core.Services;
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
|
|
||||||
@ -45,6 +46,9 @@ namespace Bit.Portal.Models
|
|||||||
case PolicyType.PasswordGenerator:
|
case PolicyType.PasswordGenerator:
|
||||||
PasswordGeneratorDataModel = JsonSerializer.Deserialize<PasswordGeneratorDataModel>(model.Data, options);
|
PasswordGeneratorDataModel = JsonSerializer.Deserialize<PasswordGeneratorDataModel>(model.Data, options);
|
||||||
break;
|
break;
|
||||||
|
case PolicyType.SendOptions:
|
||||||
|
SendOptionsDataModel = JsonSerializer.Deserialize<SendOptionsPolicyData>(model.Data, options);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
@ -53,6 +57,7 @@ namespace Bit.Portal.Models
|
|||||||
|
|
||||||
public MasterPasswordDataModel MasterPasswordDataModel { get; set; }
|
public MasterPasswordDataModel MasterPasswordDataModel { get; set; }
|
||||||
public PasswordGeneratorDataModel PasswordGeneratorDataModel { get; set; }
|
public PasswordGeneratorDataModel PasswordGeneratorDataModel { get; set; }
|
||||||
|
public SendOptionsPolicyData SendOptionsDataModel { get; set; }
|
||||||
public List<SelectListItem> Complexities { get; set; }
|
public List<SelectListItem> Complexities { get; set; }
|
||||||
public List<SelectListItem> DefaultTypes { get; set; }
|
public List<SelectListItem> DefaultTypes { get; set; }
|
||||||
public string EnableCheckboxText { get; set; }
|
public string EnableCheckboxText { get; set; }
|
||||||
@ -88,6 +93,9 @@ namespace Bit.Portal.Models
|
|||||||
case PolicyType.PersonalOwnership:
|
case PolicyType.PersonalOwnership:
|
||||||
case PolicyType.DisableSend:
|
case PolicyType.DisableSend:
|
||||||
break;
|
break;
|
||||||
|
case PolicyType.SendOptions:
|
||||||
|
existingPolicy.Data = JsonSerializer.Serialize(SendOptionsDataModel, options);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,11 @@ namespace Bit.Portal.Models
|
|||||||
DescriptionKey = "DisableSendDescription";
|
DescriptionKey = "DisableSendDescription";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PolicyType.SendOptions:
|
||||||
|
NameKey = "SendOptions";
|
||||||
|
DescriptionKey = "SendOptionsDescription";
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,17 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@if (Model.PolicyType == PolicyType.SendOptions)
|
||||||
|
{
|
||||||
|
<div class="callout callout-warning" role="alert">
|
||||||
|
<h3 class="callout-heading">
|
||||||
|
<i class="fa fa-warning" *ngIf="icon" aria-hidden="true"></i>
|
||||||
|
@i18nService.T("Warning")
|
||||||
|
</h3>
|
||||||
|
@i18nService.T("SendOptionsExemption")
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<div asp-validation-summary="ModelOnly" class="alert alert-danger"></div>
|
<div asp-validation-summary="ModelOnly" class="alert alert-danger"></div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -187,6 +198,19 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@if (Model.PolicyType == PolicyType.SendOptions)
|
||||||
|
{
|
||||||
|
<div class="config-section">
|
||||||
|
<h2>@i18nService.T("Options")</h2>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" asp-for="SendOptionsDataModel.DisableHideEmail">
|
||||||
|
<label class="form-check-label" asp-for="SendOptionsDataModel.DisableHideEmail"></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<button type="submit" class="btn btn-primary">@i18nService.T("Save")</button>
|
<button type="submit" class="btn btn-primary">@i18nService.T("Save")</button>
|
||||||
<a class="btn btn-outline-secondary ml-1" asp-controller="Policies" asp-action="Index">@i18nService.T("Cancel")</a>
|
<a class="btn btn-outline-secondary ml-1" asp-controller="Policies" asp-action="Index">@i18nService.T("Cancel")</a>
|
||||||
|
@ -70,7 +70,7 @@ namespace Bit.Api.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
var sendResponse = new SendAccessResponseModel(send, _globalSettings);
|
var sendResponse = new SendAccessResponseModel(send, _globalSettings);
|
||||||
if (send.UserId.HasValue)
|
if (send.UserId.HasValue && !send.HideEmail.GetValueOrDefault())
|
||||||
{
|
{
|
||||||
var creator = await _userService.GetUserByIdAsync(send.UserId.Value);
|
var creator = await _userService.GetUserByIdAsync(send.UserId.Value);
|
||||||
sendResponse.CreatorIdentifier = creator.Email;
|
sendResponse.CreatorIdentifier = creator.Email;
|
||||||
|
@ -9,5 +9,6 @@
|
|||||||
RequireSso = 4,
|
RequireSso = 4,
|
||||||
PersonalOwnership = 5,
|
PersonalOwnership = 5,
|
||||||
DisableSend = 6,
|
DisableSend = 6,
|
||||||
|
SendOptions = 7,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ namespace Bit.Core.Models.Api
|
|||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
[Required]
|
[Required]
|
||||||
public bool? Disabled { get; set; }
|
public bool? Disabled { get; set; }
|
||||||
|
public bool? HideEmail { get; set; }
|
||||||
|
|
||||||
public Send ToSend(Guid userId, ISendService sendService)
|
public Send ToSend(Guid userId, ISendService sendService)
|
||||||
{
|
{
|
||||||
@ -125,6 +126,7 @@ namespace Bit.Core.Models.Api
|
|||||||
existingSend.Password = sendService.HashPassword(Password);
|
existingSend.Password = sendService.HashPassword(Password);
|
||||||
}
|
}
|
||||||
existingSend.Disabled = Disabled.GetValueOrDefault();
|
existingSend.Disabled = Disabled.GetValueOrDefault();
|
||||||
|
existingSend.HideEmail = HideEmail.GetValueOrDefault();
|
||||||
return existingSend;
|
return existingSend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ namespace Bit.Core.Models.Api
|
|||||||
DeletionDate = send.DeletionDate;
|
DeletionDate = send.DeletionDate;
|
||||||
Password = send.Password;
|
Password = send.Password;
|
||||||
Disabled = send.Disabled;
|
Disabled = send.Disabled;
|
||||||
|
HideEmail = send.HideEmail.GetValueOrDefault();
|
||||||
|
|
||||||
SendData sendData;
|
SendData sendData;
|
||||||
switch (send.Type)
|
switch (send.Type)
|
||||||
@ -66,5 +67,6 @@ namespace Bit.Core.Models.Api
|
|||||||
public DateTime RevisionDate { get; set; }
|
public DateTime RevisionDate { get; set; }
|
||||||
public DateTime? ExpirationDate { get; set; }
|
public DateTime? ExpirationDate { get; set; }
|
||||||
public DateTime DeletionDate { get; set; }
|
public DateTime DeletionDate { get; set; }
|
||||||
|
public bool HideEmail { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
src/Core/Models/Data/SendOptionsPolicyData.cs
Normal file
10
src/Core/Models/Data/SendOptionsPolicyData.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Bit.Core.Models.Data
|
||||||
|
{
|
||||||
|
public class SendOptionsPolicyData
|
||||||
|
{
|
||||||
|
[Display(Name = "DisableHideEmail")]
|
||||||
|
public bool DisableHideEmail { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,7 @@ namespace Bit.Core.Models.Table
|
|||||||
public DateTime? ExpirationDate { get; set; }
|
public DateTime? ExpirationDate { get; set; }
|
||||||
public DateTime DeletionDate { get; set; }
|
public DateTime DeletionDate { get; set; }
|
||||||
public bool Disabled { get; set; }
|
public bool Disabled { get; set; }
|
||||||
|
public bool? HideEmail { get; set; }
|
||||||
|
|
||||||
public void SetNewId()
|
public void SetNewId()
|
||||||
{
|
{
|
||||||
|
@ -598,6 +598,24 @@
|
|||||||
<data name="DisableSendExemption" xml:space="preserve">
|
<data name="DisableSendExemption" xml:space="preserve">
|
||||||
<value>Organization Owners and Administrators are exempt from this policy's enforcement.</value>
|
<value>Organization Owners and Administrators are exempt from this policy's enforcement.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SendOptions" xml:space="preserve">
|
||||||
|
<value>Send Options</value>
|
||||||
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Options" xml:space="preserve">
|
||||||
|
<value>Options</value>
|
||||||
|
</data>
|
||||||
|
<data name="DisableHideEmail" xml:space="preserve">
|
||||||
|
<value>Do not allow users to hide their email address when creating or editing a Send.</value>
|
||||||
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="SendOptionsDescription" xml:space="preserve">
|
||||||
|
<value>Set options for creating and editing Sends.</value>
|
||||||
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="SendOptionsExemption" xml:space="preserve">
|
||||||
|
<value>Organization Owners and Administrators are exempt from this policy's enforcement.</value>
|
||||||
|
</data>
|
||||||
<data name="DisableRequireSsoError" xml:space="preserve">
|
<data name="DisableRequireSsoError" xml:space="preserve">
|
||||||
<value>You must manually disable the Single Sign-On Authentication policy before this policy can be disabled.</value>
|
<value>You must manually disable the Single Sign-On Authentication policy before this policy can be disabled.</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -59,7 +59,7 @@ namespace Bit.Core.Services
|
|||||||
public async Task SaveSendAsync(Send send)
|
public async Task SaveSendAsync(Send send)
|
||||||
{
|
{
|
||||||
// Make sure user can save Sends
|
// Make sure user can save Sends
|
||||||
await ValidateUserCanSaveAsync(send.UserId);
|
await ValidateUserCanSaveAsync(send.UserId, send);
|
||||||
|
|
||||||
if (send.Id == default(Guid))
|
if (send.Id == default(Guid))
|
||||||
{
|
{
|
||||||
@ -265,7 +265,7 @@ namespace Bit.Core.Services
|
|||||||
return _passwordHasher.HashPassword(new User(), password);
|
return _passwordHasher.HashPassword(new User(), password);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ValidateUserCanSaveAsync(Guid? userId)
|
private async Task ValidateUserCanSaveAsync(Guid? userId, Send send)
|
||||||
{
|
{
|
||||||
if (!userId.HasValue || (!_currentContext.Organizations?.Any() ?? true))
|
if (!userId.HasValue || (!_currentContext.Organizations?.Any() ?? true))
|
||||||
{
|
{
|
||||||
@ -286,6 +286,23 @@ namespace Bit.Core.Services
|
|||||||
throw new BadRequestException("Due to an Enterprise Policy, you are only able to delete an existing Send.");
|
throw new BadRequestException("Due to an Enterprise Policy, you are only able to delete an existing Send.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (send.HideEmail.GetValueOrDefault())
|
||||||
|
{
|
||||||
|
foreach (var policy in policies.Where(p => p.Enabled && p.Type == PolicyType.SendOptions && !_currentContext.ManagePolicies(p.OrganizationId)))
|
||||||
|
{
|
||||||
|
SendOptionsPolicyData data = null;
|
||||||
|
if (policy.Data != null)
|
||||||
|
{
|
||||||
|
data = JsonConvert.DeserializeObject<SendOptionsPolicyData>(policy.Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data?.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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<long> StorageRemainingForSendAsync(Send send)
|
private async Task<long> StorageRemainingForSendAsync(Send send)
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
@RevisionDate DATETIME2(7),
|
@RevisionDate DATETIME2(7),
|
||||||
@ExpirationDate DATETIME2(7),
|
@ExpirationDate DATETIME2(7),
|
||||||
@DeletionDate DATETIME2(7),
|
@DeletionDate DATETIME2(7),
|
||||||
@Disabled BIT
|
@Disabled BIT,
|
||||||
|
@HideEmail BIT
|
||||||
AS
|
AS
|
||||||
BEGIN
|
BEGIN
|
||||||
SET NOCOUNT ON
|
SET NOCOUNT ON
|
||||||
@ -32,7 +33,8 @@ BEGIN
|
|||||||
[RevisionDate],
|
[RevisionDate],
|
||||||
[ExpirationDate],
|
[ExpirationDate],
|
||||||
[DeletionDate],
|
[DeletionDate],
|
||||||
[Disabled]
|
[Disabled],
|
||||||
|
[HideEmail]
|
||||||
)
|
)
|
||||||
VALUES
|
VALUES
|
||||||
(
|
(
|
||||||
@ -49,7 +51,8 @@ BEGIN
|
|||||||
@RevisionDate,
|
@RevisionDate,
|
||||||
@ExpirationDate,
|
@ExpirationDate,
|
||||||
@DeletionDate,
|
@DeletionDate,
|
||||||
@Disabled
|
@Disabled,
|
||||||
|
@HideEmail
|
||||||
)
|
)
|
||||||
|
|
||||||
IF @UserId IS NOT NULL
|
IF @UserId IS NOT NULL
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
@RevisionDate DATETIME2(7),
|
@RevisionDate DATETIME2(7),
|
||||||
@ExpirationDate DATETIME2(7),
|
@ExpirationDate DATETIME2(7),
|
||||||
@DeletionDate DATETIME2(7),
|
@DeletionDate DATETIME2(7),
|
||||||
@Disabled BIT
|
@Disabled BIT,
|
||||||
|
@HideEmail BIT
|
||||||
AS
|
AS
|
||||||
BEGIN
|
BEGIN
|
||||||
SET NOCOUNT ON
|
SET NOCOUNT ON
|
||||||
@ -32,7 +33,8 @@ BEGIN
|
|||||||
[RevisionDate] = @RevisionDate,
|
[RevisionDate] = @RevisionDate,
|
||||||
[ExpirationDate] = @ExpirationDate,
|
[ExpirationDate] = @ExpirationDate,
|
||||||
[DeletionDate] = @DeletionDate,
|
[DeletionDate] = @DeletionDate,
|
||||||
[Disabled] = @Disabled
|
[Disabled] = @Disabled,
|
||||||
|
[HideEmail] = @HideEmail
|
||||||
WHERE
|
WHERE
|
||||||
[Id] = @Id
|
[Id] = @Id
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
[ExpirationDate] DATETIME2 (7) NULL,
|
[ExpirationDate] DATETIME2 (7) NULL,
|
||||||
[DeletionDate] DATETIME2 (7) NOT NULL,
|
[DeletionDate] DATETIME2 (7) NOT NULL,
|
||||||
[Disabled] BIT NOT NULL,
|
[Disabled] BIT NOT NULL,
|
||||||
|
[HideEmail] BIT NULL,
|
||||||
CONSTRAINT [PK_Send] PRIMARY KEY CLUSTERED ([Id] ASC),
|
CONSTRAINT [PK_Send] PRIMARY KEY CLUSTERED ([Id] ASC),
|
||||||
CONSTRAINT [FK_Send_Organization] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id]),
|
CONSTRAINT [FK_Send_Organization] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id]),
|
||||||
CONSTRAINT [FK_Send_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id])
|
CONSTRAINT [FK_Send_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id])
|
||||||
|
@ -12,12 +12,15 @@ using Bit.Core.Test.AutoFixture;
|
|||||||
using Bit.Core.Test.AutoFixture.SendFixtures;
|
using Bit.Core.Test.AutoFixture.SendFixtures;
|
||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Bit.Core.Test.Services
|
namespace Bit.Core.Test.Services
|
||||||
{
|
{
|
||||||
public class SendServiceTests
|
public class SendServiceTests
|
||||||
{
|
{
|
||||||
private void SaveSendAsync_Setup(SendType sendType, bool canManagePolicies,
|
// Disable Send policy check
|
||||||
|
|
||||||
|
private void SaveSendAsync_DisableSend_Setup(SendType sendType, bool canManagePolicies,
|
||||||
SutProvider<SendService> sutProvider, Send send, List<Policy> policies)
|
SutProvider<SendService> sutProvider, Send send, List<Policy> policies)
|
||||||
{
|
{
|
||||||
send.Id = default;
|
send.Id = default;
|
||||||
@ -36,7 +39,7 @@ namespace Bit.Core.Test.Services
|
|||||||
public async void SaveSendAsync_DisableSend_CantManagePolicies_throws(SendType sendType,
|
public async void SaveSendAsync_DisableSend_CantManagePolicies_throws(SendType sendType,
|
||||||
SutProvider<SendService> sutProvider, Send send, List<Policy> policies)
|
SutProvider<SendService> sutProvider, Send send, List<Policy> policies)
|
||||||
{
|
{
|
||||||
SaveSendAsync_Setup(sendType, canManagePolicies: false, sutProvider, send, policies);
|
SaveSendAsync_DisableSend_Setup(sendType, canManagePolicies: false, sutProvider, send, policies);
|
||||||
|
|
||||||
await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.SaveSendAsync(send));
|
await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.SaveSendAsync(send));
|
||||||
}
|
}
|
||||||
@ -47,7 +50,7 @@ namespace Bit.Core.Test.Services
|
|||||||
public async void SaveSendAsync_DisableSend_DisabledPolicy_CantManagePolicies_success(SendType sendType,
|
public async void SaveSendAsync_DisableSend_DisabledPolicy_CantManagePolicies_success(SendType sendType,
|
||||||
SutProvider<SendService> sutProvider, Send send, List<Policy> policies)
|
SutProvider<SendService> sutProvider, Send send, List<Policy> policies)
|
||||||
{
|
{
|
||||||
SaveSendAsync_Setup(sendType, canManagePolicies: false, sutProvider, send, policies);
|
SaveSendAsync_DisableSend_Setup(sendType, canManagePolicies: false, sutProvider, send, policies);
|
||||||
foreach (var policy in policies.Where(p => p.Type == PolicyType.DisableSend))
|
foreach (var policy in policies.Where(p => p.Type == PolicyType.DisableSend))
|
||||||
{
|
{
|
||||||
policy.Enabled = false;
|
policy.Enabled = false;
|
||||||
@ -64,7 +67,75 @@ namespace Bit.Core.Test.Services
|
|||||||
public async void SaveSendAsync_DisableSend_CanManagePolicies_success(SendType sendType,
|
public async void SaveSendAsync_DisableSend_CanManagePolicies_success(SendType sendType,
|
||||||
SutProvider<SendService> sutProvider, Send send, List<Policy> policies)
|
SutProvider<SendService> sutProvider, Send send, List<Policy> policies)
|
||||||
{
|
{
|
||||||
SaveSendAsync_Setup(sendType, canManagePolicies: true, sutProvider, send, policies);
|
SaveSendAsync_DisableSend_Setup(sendType, canManagePolicies: true, sutProvider, send, policies);
|
||||||
|
|
||||||
|
await sutProvider.Sut.SaveSendAsync(send);
|
||||||
|
|
||||||
|
await sutProvider.GetDependency<ISendRepository>().Received(1).CreateAsync(send);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendOptionsPolicy.DisableHideEmail check
|
||||||
|
|
||||||
|
private void SaveSendAsync_DisableHideEmail_Setup(SendType sendType, bool canManagePolicies,
|
||||||
|
SutProvider<SendService> sutProvider, Send send, List<Policy> policies)
|
||||||
|
{
|
||||||
|
send.Id = default;
|
||||||
|
send.Type = sendType;
|
||||||
|
send.HideEmail = true;
|
||||||
|
|
||||||
|
var dataObj = new SendOptionsPolicyData();
|
||||||
|
dataObj.DisableHideEmail = true;
|
||||||
|
|
||||||
|
policies.First().Type = PolicyType.SendOptions;
|
||||||
|
policies.First().Enabled = true;
|
||||||
|
policies.First().Data = JsonConvert.SerializeObject(dataObj);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IPolicyRepository>().GetManyByUserIdAsync(send.UserId.Value).Returns(policies);
|
||||||
|
sutProvider.GetDependency<ICurrentContext>().ManagePolicies(Arg.Any<Guid>()).Returns(canManagePolicies);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineUserSendAutoData(SendType.File)]
|
||||||
|
[InlineUserSendAutoData(SendType.Text)]
|
||||||
|
public async void SaveSendAsync_DisableHideEmail_CantManagePolicies_throws(SendType sendType,
|
||||||
|
SutProvider<SendService> sutProvider, Send send, List<Policy> policies)
|
||||||
|
{
|
||||||
|
SaveSendAsync_DisableHideEmail_Setup(sendType, canManagePolicies: false, sutProvider, send, policies);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.SaveSendAsync(send));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineUserSendAutoData(SendType.File)]
|
||||||
|
[InlineUserSendAutoData(SendType.Text)]
|
||||||
|
public async void SaveSendAsync_DisableHideEmail_CantManagePolicies_success(SendType sendType,
|
||||||
|
SutProvider<SendService> sutProvider, Send send, List<Policy> policies)
|
||||||
|
{
|
||||||
|
SaveSendAsync_DisableHideEmail_Setup(sendType, canManagePolicies: false, sutProvider, send, policies);
|
||||||
|
|
||||||
|
var policyData = new SendOptionsPolicyData();
|
||||||
|
policyData.DisableHideEmail = false;
|
||||||
|
var policyDataSerialized = JsonConvert.SerializeObject(policyData);
|
||||||
|
|
||||||
|
foreach (var policy in policies.Where(p => p.Type == PolicyType.SendOptions))
|
||||||
|
{
|
||||||
|
policies.First().Enabled = true;
|
||||||
|
policies.First().Data = policyDataSerialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
await sutProvider.Sut.SaveSendAsync(send);
|
||||||
|
|
||||||
|
await sutProvider.GetDependency<ISendRepository>().Received(1).CreateAsync(send);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineUserSendAutoData(SendType.File)]
|
||||||
|
[InlineUserSendAutoData(SendType.Text)]
|
||||||
|
public async void SaveSendAsync_DisableHideEmail_CanManagePolicies_success(SendType sendType,
|
||||||
|
SutProvider<SendService> sutProvider, Send send, List<Policy> policies)
|
||||||
|
{
|
||||||
|
SaveSendAsync_DisableHideEmail_Setup(sendType, canManagePolicies: true, sutProvider, send, policies);
|
||||||
|
|
||||||
await sutProvider.Sut.SaveSendAsync(send);
|
await sutProvider.Sut.SaveSendAsync(send);
|
||||||
|
|
||||||
|
@ -0,0 +1,151 @@
|
|||||||
|
-- Add HideEmail column
|
||||||
|
IF COL_LENGTH('[dbo].[Send]', 'HideEmail') IS NULL
|
||||||
|
BEGIN
|
||||||
|
ALTER TABLE [dbo].[Send] ADD [HideEmail] BIT NULL;
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- Recreate View
|
||||||
|
IF OBJECT_ID('[dbo].[SendView]') IS NOT NULL
|
||||||
|
BEGIN
|
||||||
|
DROP VIEW [dbo].[SendView]
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE VIEW [dbo].[SendView]
|
||||||
|
AS
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
[dbo].[Send]
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- Recreate procedures
|
||||||
|
IF OBJECT_ID('[dbo].[Send_Create]') IS NOT NULL
|
||||||
|
BEGIN
|
||||||
|
DROP PROCEDURE [dbo].[Send_Create]
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE PROCEDURE [dbo].[Send_Create]
|
||||||
|
@Id UNIQUEIDENTIFIER,
|
||||||
|
@UserId UNIQUEIDENTIFIER,
|
||||||
|
@OrganizationId UNIQUEIDENTIFIER,
|
||||||
|
@Type TINYINT,
|
||||||
|
@Data VARCHAR(MAX),
|
||||||
|
@Key VARCHAR(MAX),
|
||||||
|
@Password NVARCHAR(300),
|
||||||
|
@MaxAccessCount INT,
|
||||||
|
@AccessCount INT,
|
||||||
|
@CreationDate DATETIME2(7),
|
||||||
|
@RevisionDate DATETIME2(7),
|
||||||
|
@ExpirationDate DATETIME2(7),
|
||||||
|
@DeletionDate DATETIME2(7),
|
||||||
|
@Disabled BIT,
|
||||||
|
@HideEmail BIT
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
INSERT INTO [dbo].[Send]
|
||||||
|
(
|
||||||
|
[Id],
|
||||||
|
[UserId],
|
||||||
|
[OrganizationId],
|
||||||
|
[Type],
|
||||||
|
[Data],
|
||||||
|
[Key],
|
||||||
|
[Password],
|
||||||
|
[MaxAccessCount],
|
||||||
|
[AccessCount],
|
||||||
|
[CreationDate],
|
||||||
|
[RevisionDate],
|
||||||
|
[ExpirationDate],
|
||||||
|
[DeletionDate],
|
||||||
|
[Disabled],
|
||||||
|
[HideEmail]
|
||||||
|
)
|
||||||
|
VALUES
|
||||||
|
(
|
||||||
|
@Id,
|
||||||
|
@UserId,
|
||||||
|
@OrganizationId,
|
||||||
|
@Type,
|
||||||
|
@Data,
|
||||||
|
@Key,
|
||||||
|
@Password,
|
||||||
|
@MaxAccessCount,
|
||||||
|
@AccessCount,
|
||||||
|
@CreationDate,
|
||||||
|
@RevisionDate,
|
||||||
|
@ExpirationDate,
|
||||||
|
@DeletionDate,
|
||||||
|
@Disabled,
|
||||||
|
@HideEmail
|
||||||
|
)
|
||||||
|
|
||||||
|
IF @UserId IS NOT NULL
|
||||||
|
BEGIN
|
||||||
|
IF @Type = 1 --File
|
||||||
|
BEGIN
|
||||||
|
EXEC [dbo].[User_UpdateStorage] @UserId
|
||||||
|
END
|
||||||
|
EXEC [dbo].[User_BumpAccountRevisionDate] @UserId
|
||||||
|
END
|
||||||
|
-- TODO: OrganizationId bump?
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
IF OBJECT_ID('[dbo].[Send_Update]') IS NOT NULL
|
||||||
|
BEGIN
|
||||||
|
DROP PROCEDURE [dbo].[Send_Update]
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE PROCEDURE [dbo].[Send_Update]
|
||||||
|
@Id UNIQUEIDENTIFIER,
|
||||||
|
@UserId UNIQUEIDENTIFIER,
|
||||||
|
@OrganizationId UNIQUEIDENTIFIER,
|
||||||
|
@Type TINYINT,
|
||||||
|
@Data VARCHAR(MAX),
|
||||||
|
@Key VARCHAR(MAX),
|
||||||
|
@Password NVARCHAR(300),
|
||||||
|
@MaxAccessCount INT,
|
||||||
|
@AccessCount INT,
|
||||||
|
@CreationDate DATETIME2(7),
|
||||||
|
@RevisionDate DATETIME2(7),
|
||||||
|
@ExpirationDate DATETIME2(7),
|
||||||
|
@DeletionDate DATETIME2(7),
|
||||||
|
@Disabled BIT,
|
||||||
|
@HideEmail BIT
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
UPDATE
|
||||||
|
[dbo].[Send]
|
||||||
|
SET
|
||||||
|
[UserId] = @UserId,
|
||||||
|
[OrganizationId] = @OrganizationId,
|
||||||
|
[Type] = @Type,
|
||||||
|
[Data] = @Data,
|
||||||
|
[Key] = @Key,
|
||||||
|
[Password] = @Password,
|
||||||
|
[MaxAccessCount] = @MaxAccessCount,
|
||||||
|
[AccessCount] = @AccessCount,
|
||||||
|
[CreationDate] = @CreationDate,
|
||||||
|
[RevisionDate] = @RevisionDate,
|
||||||
|
[ExpirationDate] = @ExpirationDate,
|
||||||
|
[DeletionDate] = @DeletionDate,
|
||||||
|
[Disabled] = @Disabled,
|
||||||
|
[HideEmail] = @HideEmail
|
||||||
|
WHERE
|
||||||
|
[Id] = @Id
|
||||||
|
|
||||||
|
IF @UserId IS NOT NULL
|
||||||
|
BEGIN
|
||||||
|
EXEC [dbo].[User_BumpAccountRevisionDate] @UserId
|
||||||
|
END
|
||||||
|
-- TODO: OrganizationId bump?
|
||||||
|
END
|
||||||
|
GO
|
Loading…
Reference in New Issue
Block a user