Hide email address in Sends (#1340)

* Add HideEmail model properties and locale strings

* Fix UI strings

* Add HideEmail to SendService

* Add HideEmail option to UI

* Tidy up declarations

* Add Bitwarden Send translation warning
This commit is contained in:
Thomas Rittson 2021-03-30 02:01:42 +10:00 committed by GitHub
parent 13ffbe911a
commit 04aeddc5de
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 96 additions and 0 deletions

View file

@ -89,6 +89,18 @@
StyleClass="text-muted, text-sm, text-bold"
HorizontalTextAlignment="Center" />
</Frame>
<Frame
IsVisible="{Binding SendOptionsPolicyInEffect}"
Padding="10"
Margin="0, 12, 0, 0"
HasShadow="False"
BackgroundColor="Transparent"
BorderColor="Accent">
<Label
Text="{u:I18n SendOptionsPolicyInEffect}"
StyleClass="text-muted, text-sm, text-bold"
HorizontalTextAlignment="Center" />
</Frame>
<StackLayout StyleClass="box-row">
<Label
Text="{u:I18n Name}"
@ -490,6 +502,20 @@
StyleClass="box-footer-label"
Margin="0,5,0,0" />
</StackLayout>
<StackLayout
StyleClass="box-row, box-row-switch"
Margin="0,5,0,0">
<Label
Text="{u:I18n HideEmail}"
StyleClass="box-label-regular"
VerticalOptions="Center"
HorizontalOptions="StartAndExpand" />
<Switch
IsToggled="{Binding Send.HideEmail}"
IsEnabled="{Binding DisableHideEmailControl, Converter={StaticResource inverseBool}}"
HorizontalOptions="End"
Margin="10,0,0,0" />
</StackLayout>
<StackLayout
StyleClass="box-row, box-row-switch"
Margin="0,5,0,0">

View file

@ -42,6 +42,9 @@ namespace Bit.App.Pages
nameof(IsText),
nameof(IsFile),
};
private bool _disableHideEmail;
private bool _sendOptionsPolicyInEffect;
private bool _disableHideEmailControl;
public SendAddEditPageViewModel()
{
@ -91,6 +94,7 @@ namespace Bit.App.Pages
public byte[] FileData { get; set; }
public string NewPassword { get; set; }
public bool ShareOnSave { get; set; }
public bool DisableHideEmailControl { get; set; }
public List<KeyValuePair<string, SendType>> TypeOptions { get; }
public List<KeyValuePair<string, string>> DeletionTypeOptions { get; }
public List<KeyValuePair<string, string>> ExpirationTypeOptions { get; }
@ -194,6 +198,16 @@ namespace Bit.App.Pages
nameof(ShowPasswordIcon)
});
}
public bool DisableHideEmail
{
get => _disableHideEmail;
set => SetProperty(ref _disableHideEmail, value);
}
public bool SendOptionsPolicyInEffect
{
get => _sendOptionsPolicyInEffect;
set => SetProperty(ref _sendOptionsPolicyInEffect, value);
}
public bool EditMode => !string.IsNullOrWhiteSpace(SendId);
public bool IsText => Send?.Type == SendType.Text;
public bool IsFile => Send?.Type == SendType.File;
@ -206,6 +220,8 @@ namespace Bit.App.Pages
PageTitle = EditMode ? AppResources.EditSend : AppResources.AddSend;
_canAccessPremium = await _userService.CanAccessPremiumAsync();
SendEnabled = ! await AppHelpers.IsSendDisabledByPolicyAsync();
DisableHideEmail = await AppHelpers.IsHideEmailDisabledByPolicyAsync();
SendOptionsPolicyInEffect = SendEnabled && DisableHideEmail;
}
public async Task<bool> LoadAsync()
@ -243,6 +259,10 @@ namespace Bit.App.Pages
_isOverridingPickers = false;
}
DisableHideEmailControl = !SendEnabled ||
(!EditMode && DisableHideEmail) ||
(EditMode && DisableHideEmail && !Send.HideEmail);
return true;
}

View file

@ -3484,5 +3484,17 @@ namespace Bit.App.Resources {
return ResourceManager.GetString("AboutSend", resourceCulture);
}
}
public static string HideEmail {
get {
return ResourceManager.GetString("HideEmail", resourceCulture);
}
}
public static string SendOptionsPolicyInEffect {
get {
return ResourceManager.GetString("SendOptionsPolicyInEffect", resourceCulture);
}
}
}
}

View file

@ -1975,4 +1975,11 @@
<value>About 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="HideEmail" xml:space="preserve">
<value>Hide my email address from recipients.</value>
</data>
<data name="SendOptionsPolicyInEffect" xml:space="preserve">
<value>One or more organization policies are affecting your Send options.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
</root>

View file

@ -311,6 +311,26 @@ namespace Bit.App.Utilities
});
}
public static async Task<bool> IsHideEmailDisabledByPolicyAsync()
{
var policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
var userService = ServiceContainer.Resolve<IUserService>("userService");
var policies = await policyService.GetAll(PolicyType.SendOptions);
var organizations = await userService.GetAllOrganizationAsync();
return organizations.Any(o =>
{
return o.Enabled &&
o.Status == OrganizationUserStatusType.Confirmed &&
o.UsePolicies &&
!o.canManagePolicies &&
policies.Any(p => p.OrganizationId == o.Id &&
p.Enabled &&
p.Data.ContainsKey("disableHideEmail") &&
(bool)p.Data["disableHideEmail"]);
});
}
public static async Task<bool> PerformUpdateTasksAsync(ISyncService syncService,
IDeviceActionService deviceActionService, IStorageService storageService)
{

View file

@ -9,5 +9,6 @@
RequireSso = 4, // Requires users to authenticate with SSO
PersonalOwnership = 5, // Disables personal vault ownership for adding/cloning items
DisableSend = 6, // Disables the ability to create and edit Sends
SendOptions = 7, // Sets restrictions or defaults for Bitwarden Sends
}
}

View file

@ -24,6 +24,7 @@ namespace Bit.Core.Models.Data
DeletionDate = response.DeletionDate;
Password = response.Password;
Disabled = response.Disabled;
HideEmail = response.HideEmail.GetValueOrDefault();
switch (Type)
{
@ -54,5 +55,6 @@ namespace Bit.Core.Models.Data
public DateTime DeletionDate { get; set; }
public string Password { get; set; }
public bool Disabled { get; set; }
public bool HideEmail { get; set; }
}
}

View file

@ -27,6 +27,7 @@ namespace Bit.Core.Models.Domain
public DateTime DeletionDate { get; set; }
public string Password { get; set; }
public bool Disabled { get; set; }
public bool HideEmail { get; set; }
public Send() : base() { }
@ -49,6 +50,7 @@ namespace Bit.Core.Models.Domain
RevisionDate = data.RevisionDate;
DeletionDate = data.DeletionDate;
ExpirationDate = data.ExpirationDate;
HideEmail = data.HideEmail;
switch (Type)
{

View file

@ -19,6 +19,7 @@ namespace Bit.Core.Models.Request
public SendFileApi File { get; set; }
public string Password { get; set; }
public bool Disabled { get; set; }
public bool HideEmail { get; set; }
public SendRequest(Send send, long? fileLength)
{
@ -32,6 +33,7 @@ namespace Bit.Core.Models.Request
Key = send.Key?.EncryptedString;
Password = send.Password;
Disabled = send.Disabled;
HideEmail = send.HideEmail;
switch (Type)
{

View file

@ -21,5 +21,6 @@ namespace Bit.Core.Models.Response
public DateTime DeletionDate { get; set; }
public string Password { get; set; }
public bool Disabled { get; set; }
public bool? HideEmail { get; set; }
}
}

View file

@ -21,6 +21,7 @@ namespace Bit.Core.Models.View
ExpirationDate = send.ExpirationDate;
Disabled = send.Disabled;
Password = send.Password;
HideEmail = send.HideEmail;
}
public string Id { get; set; }
@ -45,5 +46,6 @@ namespace Bit.Core.Models.View
public bool Expired => ExpirationDate.HasValue && ExpirationDate.Value <= DateTime.UtcNow;
public bool PendingDelete => DeletionDate <= DateTime.UtcNow;
public string DisplayDate => DeletionDate.ToLocalTime().ToString("MMM d, yyyy, h:mm tt");
public bool HideEmail { get; set; }
}
}

View file

@ -101,6 +101,7 @@ namespace Bit.Core.Services
Key = await _cryptoService.EncryptAsync(model.Key, key),
Name = await _cryptoService.EncryptAsync(model.Name, model.CryptoKey),
Notes = await _cryptoService.EncryptAsync(model.Notes, model.CryptoKey),
HideEmail = model.HideEmail
};
byte[] encryptedFileData = null;