mirror of
https://github.com/bitwarden/android.git
synced 2025-01-12 11:17:30 +03:00
[Policy] Personal Ownership (#1166)
* Initial commit of personal ownership policy * Updated logic for returning from allowing cipher creation from notification * fixed small edge case when user in one org // adjusted error message to match all platforms * Removed test code
This commit is contained in:
parent
0dd87bbf78
commit
6e40b7f25b
8 changed files with 74 additions and 1 deletions
|
@ -23,6 +23,8 @@ namespace Bit.Droid.Autofill
|
||||||
private ICipherService _cipherService;
|
private ICipherService _cipherService;
|
||||||
private IVaultTimeoutService _vaultTimeoutService;
|
private IVaultTimeoutService _vaultTimeoutService;
|
||||||
private IStorageService _storageService;
|
private IStorageService _storageService;
|
||||||
|
private IPolicyService _policyService;
|
||||||
|
private IUserService _userService;
|
||||||
|
|
||||||
public async override void OnFillRequest(FillRequest request, CancellationSignal cancellationSignal,
|
public async override void OnFillRequest(FillRequest request, CancellationSignal cancellationSignal,
|
||||||
FillCallback callback)
|
FillCallback callback)
|
||||||
|
@ -89,6 +91,26 @@ namespace Bit.Droid.Autofill
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_policyService ??= ServiceContainer.Resolve<IPolicyService>("policyService");
|
||||||
|
|
||||||
|
var personalOwnershipPolicies = await _policyService.GetAll(PolicyType.PersonalOwnership);
|
||||||
|
if (personalOwnershipPolicies != null)
|
||||||
|
{
|
||||||
|
_userService ??= ServiceContainer.Resolve<IUserService>("userService");
|
||||||
|
foreach (var policy in personalOwnershipPolicies)
|
||||||
|
{
|
||||||
|
if (policy.Enabled)
|
||||||
|
{
|
||||||
|
var org = await _userService.GetOrganizationAsync(policy.OrganizationId);
|
||||||
|
if (org != null && org.Enabled && org.UsePolicies && !org.IsAdmin
|
||||||
|
&& org.Status == OrganizationUserStatusType.Confirmed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var parser = new Parser(structure, ApplicationContext);
|
var parser = new Parser(structure, ApplicationContext);
|
||||||
parser.Parse();
|
parser.Parse();
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace Bit.App.Pages
|
||||||
private readonly IAuditService _auditService;
|
private readonly IAuditService _auditService;
|
||||||
private readonly IMessagingService _messagingService;
|
private readonly IMessagingService _messagingService;
|
||||||
private readonly IEventService _eventService;
|
private readonly IEventService _eventService;
|
||||||
|
private readonly IPolicyService _policyService;
|
||||||
private CipherView _cipher;
|
private CipherView _cipher;
|
||||||
private bool _showNotesSeparator;
|
private bool _showNotesSeparator;
|
||||||
private bool _showPassword;
|
private bool _showPassword;
|
||||||
|
@ -78,6 +79,7 @@ namespace Bit.App.Pages
|
||||||
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
|
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
|
||||||
_collectionService = ServiceContainer.Resolve<ICollectionService>("collectionService");
|
_collectionService = ServiceContainer.Resolve<ICollectionService>("collectionService");
|
||||||
_eventService = ServiceContainer.Resolve<IEventService>("eventService");
|
_eventService = ServiceContainer.Resolve<IEventService>("eventService");
|
||||||
|
_policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
|
||||||
GeneratePasswordCommand = new Command(GeneratePassword);
|
GeneratePasswordCommand = new Command(GeneratePassword);
|
||||||
TogglePasswordCommand = new Command(TogglePassword);
|
TogglePasswordCommand = new Command(TogglePassword);
|
||||||
ToggleCardCodeCommand = new Command(ToggleCardCode);
|
ToggleCardCodeCommand = new Command(ToggleCardCode);
|
||||||
|
@ -87,6 +89,7 @@ namespace Bit.App.Pages
|
||||||
Uris = new ExtendedObservableCollection<LoginUriView>();
|
Uris = new ExtendedObservableCollection<LoginUriView>();
|
||||||
Fields = new ExtendedObservableCollection<AddEditPageFieldViewModel>();
|
Fields = new ExtendedObservableCollection<AddEditPageFieldViewModel>();
|
||||||
Collections = new ExtendedObservableCollection<CollectionViewModel>();
|
Collections = new ExtendedObservableCollection<CollectionViewModel>();
|
||||||
|
AllowPersonal = true;
|
||||||
|
|
||||||
TypeOptions = new List<KeyValuePair<string, CipherType>>
|
TypeOptions = new List<KeyValuePair<string, CipherType>>
|
||||||
{
|
{
|
||||||
|
@ -276,6 +279,7 @@ namespace Bit.App.Pages
|
||||||
public string ShowCardCodeIcon => ShowCardCode ? "" : "";
|
public string ShowCardCodeIcon => ShowCardCode ? "" : "";
|
||||||
public int PasswordFieldColSpan => Cipher.ViewPassword ? 1 : 4;
|
public int PasswordFieldColSpan => Cipher.ViewPassword ? 1 : 4;
|
||||||
public int TotpColumnSpan => Cipher.ViewPassword ? 1 : 2;
|
public int TotpColumnSpan => Cipher.ViewPassword ? 1 : 2;
|
||||||
|
public bool AllowPersonal { get; set; }
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
|
@ -284,6 +288,7 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
public async Task<bool> LoadAsync(AppOptions appOptions = null)
|
public async Task<bool> LoadAsync(AppOptions appOptions = null)
|
||||||
{
|
{
|
||||||
|
var policies = (await _policyService.GetAll(PolicyType.PersonalOwnership))?.ToList();
|
||||||
var myEmail = await _userService.GetEmailAsync();
|
var myEmail = await _userService.GetEmailAsync();
|
||||||
OwnershipOptions.Add(new KeyValuePair<string, string>(myEmail, null));
|
OwnershipOptions.Add(new KeyValuePair<string, string>(myEmail, null));
|
||||||
var orgs = await _userService.GetAllOrganizationAsync();
|
var orgs = await _userService.GetAllOrganizationAsync();
|
||||||
|
@ -292,6 +297,24 @@ namespace Bit.App.Pages
|
||||||
if (org.Enabled && org.Status == OrganizationUserStatusType.Confirmed)
|
if (org.Enabled && org.Status == OrganizationUserStatusType.Confirmed)
|
||||||
{
|
{
|
||||||
OwnershipOptions.Add(new KeyValuePair<string, string>(org.Name, org.Id));
|
OwnershipOptions.Add(new KeyValuePair<string, string>(org.Name, org.Id));
|
||||||
|
if (policies != null && org.UsePolicies && !org.IsAdmin && AllowPersonal)
|
||||||
|
{
|
||||||
|
foreach (var policy in policies)
|
||||||
|
{
|
||||||
|
if (policy.OrganizationId == org.Id && policy.Enabled)
|
||||||
|
{
|
||||||
|
AllowPersonal = false;
|
||||||
|
// Remove personal ownership
|
||||||
|
OwnershipOptions.RemoveAt(0);
|
||||||
|
// Default to the organization who owns this policy for now (if necessary)
|
||||||
|
if (string.IsNullOrWhiteSpace(OrganizationId))
|
||||||
|
{
|
||||||
|
OrganizationId = org.Id;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,6 +387,12 @@ namespace Bit.App.Pages
|
||||||
IdentityTitleOptions.FindIndex(k => k.Value == Cipher.Identity.Title);
|
IdentityTitleOptions.FindIndex(k => k.Value == Cipher.Identity.Title);
|
||||||
OwnershipSelectedIndex = string.IsNullOrWhiteSpace(Cipher.OrganizationId) ? 0 :
|
OwnershipSelectedIndex = string.IsNullOrWhiteSpace(Cipher.OrganizationId) ? 0 :
|
||||||
OwnershipOptions.FindIndex(k => k.Value == Cipher.OrganizationId);
|
OwnershipOptions.FindIndex(k => k.Value == Cipher.OrganizationId);
|
||||||
|
|
||||||
|
// If the selected organization is on Index 0 and we've removed the personal option, force refresh
|
||||||
|
if (!AllowPersonal && OwnershipSelectedIndex == 0)
|
||||||
|
{
|
||||||
|
OrganizationChanged();
|
||||||
|
}
|
||||||
|
|
||||||
if ((!EditMode || CloneMode) && (CollectionIds?.Any() ?? false))
|
if ((!EditMode || CloneMode) && (CollectionIds?.Any() ?? false))
|
||||||
{
|
{
|
||||||
|
@ -410,6 +439,13 @@ namespace Bit.App.Pages
|
||||||
AppResources.Ok);
|
AppResources.Ok);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((!EditMode || CloneMode) && !AllowPersonal && string.IsNullOrWhiteSpace(Cipher.OrganizationId))
|
||||||
|
{
|
||||||
|
await Page.DisplayAlert(AppResources.AnErrorHasOccurred,
|
||||||
|
AppResources.PersonalOwnershipSubmitError,AppResources.Ok);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Cipher.Fields = Fields != null && Fields.Any() ?
|
Cipher.Fields = Fields != null && Fields.Any() ?
|
||||||
Fields.Where(f => f != null).Select(f => f.Field).ToList() : null;
|
Fields.Where(f => f != null).Select(f => f.Field).ToList() : null;
|
||||||
|
|
6
src/App/Resources/AppResources.Designer.cs
generated
6
src/App/Resources/AppResources.Designer.cs
generated
|
@ -3158,5 +3158,11 @@ namespace Bit.App.Resources {
|
||||||
return ResourceManager.GetString("DrawOverDescription3", resourceCulture);
|
return ResourceManager.GetString("DrawOverDescription3", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string PersonalOwnershipSubmitError {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("PersonalOwnershipSubmitError", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1786,4 +1786,7 @@
|
||||||
<data name="DrawOverDescription3" xml:space="preserve">
|
<data name="DrawOverDescription3" xml:space="preserve">
|
||||||
<value>If enabled, accessibility will show a popup to augment the Autofill Service for older apps that don't support the Android Autofill Framework.</value>
|
<value>If enabled, accessibility will show a popup to augment the Autofill Service for older apps that don't support the Android Autofill Framework.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PersonalOwnershipSubmitError" xml:space="preserve">
|
||||||
|
<value>Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -6,6 +6,7 @@
|
||||||
MasterPassword = 1,
|
MasterPassword = 1,
|
||||||
PasswordGenerator = 2,
|
PasswordGenerator = 2,
|
||||||
OnlyOrg = 3,
|
OnlyOrg = 3,
|
||||||
RequireSso = 4
|
RequireSso = 4,
|
||||||
|
PersonalOwnership = 5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace Bit.Core.Models.Data
|
||||||
UseTotp = response.UseTotp;
|
UseTotp = response.UseTotp;
|
||||||
Use2fa = response.Use2fa;
|
Use2fa = response.Use2fa;
|
||||||
UseApi = response.UseApi;
|
UseApi = response.UseApi;
|
||||||
|
UsePolicies = response.UsePolicies;
|
||||||
SelfHost = response.SelfHost;
|
SelfHost = response.SelfHost;
|
||||||
UsersGetPremium = response.UsersGetPremium;
|
UsersGetPremium = response.UsersGetPremium;
|
||||||
Seats = response.Seats;
|
Seats = response.Seats;
|
||||||
|
@ -38,6 +39,7 @@ namespace Bit.Core.Models.Data
|
||||||
public bool UseTotp { get; set; }
|
public bool UseTotp { get; set; }
|
||||||
public bool Use2fa { get; set; }
|
public bool Use2fa { get; set; }
|
||||||
public bool UseApi { get; set; }
|
public bool UseApi { get; set; }
|
||||||
|
public bool UsePolicies { get; set; }
|
||||||
public bool SelfHost { get; set; }
|
public bool SelfHost { get; set; }
|
||||||
public bool UsersGetPremium { get; set; }
|
public bool UsersGetPremium { get; set; }
|
||||||
public int Seats { get; set; }
|
public int Seats { get; set; }
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace Bit.Core.Models.Domain
|
||||||
UseTotp = obj.UseTotp;
|
UseTotp = obj.UseTotp;
|
||||||
Use2fa = obj.Use2fa;
|
Use2fa = obj.Use2fa;
|
||||||
UseApi = obj.UseApi;
|
UseApi = obj.UseApi;
|
||||||
|
UsePolicies = obj.UsePolicies;
|
||||||
SelfHost = obj.SelfHost;
|
SelfHost = obj.SelfHost;
|
||||||
UsersGetPremium = obj.UsersGetPremium;
|
UsersGetPremium = obj.UsersGetPremium;
|
||||||
Seats = obj.Seats;
|
Seats = obj.Seats;
|
||||||
|
@ -38,6 +39,7 @@ namespace Bit.Core.Models.Domain
|
||||||
public bool UseTotp { get; set; }
|
public bool UseTotp { get; set; }
|
||||||
public bool Use2fa { get; set; }
|
public bool Use2fa { get; set; }
|
||||||
public bool UseApi { get; set; }
|
public bool UseApi { get; set; }
|
||||||
|
public bool UsePolicies { get; set; }
|
||||||
public bool SelfHost { get; set; }
|
public bool SelfHost { get; set; }
|
||||||
public bool UsersGetPremium { get; set; }
|
public bool UsersGetPremium { get; set; }
|
||||||
public int Seats { get; set; }
|
public int Seats { get; set; }
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace Bit.Core.Models.Response
|
||||||
public bool UseTotp { get; set; }
|
public bool UseTotp { get; set; }
|
||||||
public bool Use2fa { get; set; }
|
public bool Use2fa { get; set; }
|
||||||
public bool UseApi { get; set; }
|
public bool UseApi { get; set; }
|
||||||
|
public bool UsePolicies { get; set; }
|
||||||
public bool UsersGetPremium { get; set; }
|
public bool UsersGetPremium { get; set; }
|
||||||
public bool SelfHost { get; set; }
|
public bool SelfHost { get; set; }
|
||||||
public int Seats { get; set; }
|
public int Seats { get; set; }
|
||||||
|
|
Loading…
Reference in a new issue