mirror of
https://github.com/bitwarden/mobile
synced 2025-12-12 06:13:21 +00:00
SG-210 Account Switching in Autofill (iOS) (#1909)
* SG-210 Set up account switching on Autofill iOS * SG-210 Fix refresh after sync on autofill ciphers, also added account switching on lock view on autofill. Also fix possible crash when scrolling when no items were displayed and also fixed navigation when login in on an automatically logged out account. * SG-210 Added reference on iOS.Core project * Fix formatting on AccountManager * SG-210 Fix background color for dark theme
This commit is contained in:
committed by
GitHub
parent
88b406544b
commit
fba407f3b6
@@ -1,27 +1,32 @@
|
||||
using AuthenticationServices;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using AuthenticationServices;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Models;
|
||||
using Bit.App.Pages;
|
||||
using Bit.App.Utilities;
|
||||
using Bit.App.Utilities.AccountManagement;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.iOS.Autofill.Models;
|
||||
using Bit.iOS.Core.Utilities;
|
||||
using Foundation;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Pages;
|
||||
using UIKit;
|
||||
using Xamarin.Forms;
|
||||
using Bit.App.Utilities;
|
||||
using Bit.App.Models;
|
||||
using Bit.iOS.Core.Views;
|
||||
using CoreNFC;
|
||||
using Foundation;
|
||||
using UIKit;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.iOS.Autofill
|
||||
{
|
||||
public partial class CredentialProviderViewController : ASCredentialProviderViewController
|
||||
public partial class CredentialProviderViewController : ASCredentialProviderViewController, IAccountsManagerHost
|
||||
{
|
||||
private Context _context;
|
||||
private NFCNdefReaderSession _nfcSession = null;
|
||||
private Core.NFCReaderDelegate _nfcDelegate = null;
|
||||
private IAccountsManager _accountsManager;
|
||||
|
||||
private readonly LazyResolve<IStateService> _stateService = new LazyResolve<IStateService>("stateService");
|
||||
|
||||
public CredentialProviderViewController(IntPtr handle)
|
||||
: base(handle)
|
||||
@@ -56,7 +61,7 @@ namespace Bit.iOS.Autofill
|
||||
}
|
||||
if (!await IsAuthed())
|
||||
{
|
||||
LaunchHomePage();
|
||||
await _accountsManager.NavigateOnAccountChangeAsync(false);
|
||||
}
|
||||
else if (await IsLocked())
|
||||
{
|
||||
@@ -78,9 +83,8 @@ namespace Bit.iOS.Autofill
|
||||
public override async void ProvideCredentialWithoutUserInteraction(ASPasswordCredentialIdentity credentialIdentity)
|
||||
{
|
||||
InitAppIfNeeded();
|
||||
var stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
||||
await stateService.SetPasswordRepromptAutofillAsync(false);
|
||||
await stateService.SetPasswordVerifiedAutofillAsync(false);
|
||||
await _stateService.Value.SetPasswordRepromptAutofillAsync(false);
|
||||
await _stateService.Value.SetPasswordVerifiedAutofillAsync(false);
|
||||
if (!await IsAuthed() || await IsLocked())
|
||||
{
|
||||
var err = new NSError(new NSString("ASExtensionErrorDomain"),
|
||||
@@ -97,7 +101,7 @@ namespace Bit.iOS.Autofill
|
||||
InitAppIfNeeded();
|
||||
if (!await IsAuthed())
|
||||
{
|
||||
LaunchHomePage();
|
||||
await _accountsManager.NavigateOnAccountChangeAsync(false);
|
||||
return;
|
||||
}
|
||||
_context.CredentialIdentity = credentialIdentity;
|
||||
@@ -110,7 +114,7 @@ namespace Bit.iOS.Autofill
|
||||
_context.Configuring = true;
|
||||
if (!await IsAuthed())
|
||||
{
|
||||
LaunchHomePage();
|
||||
await _accountsManager.NavigateOnAccountChangeAsync(false);
|
||||
return;
|
||||
}
|
||||
CheckLock(() => PerformSegue("setupSegue", this));
|
||||
@@ -229,7 +233,6 @@ namespace Bit.iOS.Autofill
|
||||
return;
|
||||
}
|
||||
|
||||
var stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
||||
var decCipher = await cipher.DecryptAsync();
|
||||
if (decCipher.Reprompt != Bit.Core.Enums.CipherRepromptType.None)
|
||||
{
|
||||
@@ -237,13 +240,13 @@ namespace Bit.iOS.Autofill
|
||||
// already verified the password.
|
||||
if (!userInteraction)
|
||||
{
|
||||
await stateService.SetPasswordRepromptAutofillAsync(true);
|
||||
await _stateService.Value.SetPasswordRepromptAutofillAsync(true);
|
||||
var err = new NSError(new NSString("ASExtensionErrorDomain"),
|
||||
Convert.ToInt32(ASExtensionErrorCode.UserInteractionRequired), null);
|
||||
ExtensionContext?.CancelRequest(err);
|
||||
return;
|
||||
}
|
||||
else if (!await stateService.GetPasswordVerifiedAutofillAsync())
|
||||
else if (!await _stateService.Value.GetPasswordVerifiedAutofillAsync())
|
||||
{
|
||||
// Add a timeout to resolve keyboard not always showing up.
|
||||
await Task.Delay(250);
|
||||
@@ -258,10 +261,10 @@ namespace Bit.iOS.Autofill
|
||||
}
|
||||
}
|
||||
string totpCode = null;
|
||||
var disableTotpCopy = await stateService.GetDisableAutoTotpCopyAsync();
|
||||
var disableTotpCopy = await _stateService.Value.GetDisableAutoTotpCopyAsync();
|
||||
if (!disableTotpCopy.GetValueOrDefault(false))
|
||||
{
|
||||
var canAccessPremiumAsync = await stateService.CanAccessPremiumAsync();
|
||||
var canAccessPremiumAsync = await _stateService.Value.CanAccessPremiumAsync();
|
||||
if (!string.IsNullOrWhiteSpace(decCipher.Login.Totp) &&
|
||||
(canAccessPremiumAsync || cipher.OrganizationUseTotp))
|
||||
{
|
||||
@@ -275,8 +278,7 @@ namespace Bit.iOS.Autofill
|
||||
|
||||
private async void CheckLock(Action notLockedAction)
|
||||
{
|
||||
var stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
||||
if (await IsLocked() || await stateService.GetPasswordRepromptAutofillAsync())
|
||||
if (await IsLocked() || await _stateService.Value.GetPasswordRepromptAutofillAsync())
|
||||
{
|
||||
PerformSegue("lockPasswordSegue", this);
|
||||
}
|
||||
@@ -294,8 +296,7 @@ namespace Bit.iOS.Autofill
|
||||
|
||||
private Task<bool> IsAuthed()
|
||||
{
|
||||
var stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
||||
return stateService.IsAuthenticatedAsync();
|
||||
return _stateService.Value.IsAuthenticatedAsync();
|
||||
}
|
||||
|
||||
private void LogoutIfAuthed()
|
||||
@@ -304,8 +305,7 @@ namespace Bit.iOS.Autofill
|
||||
{
|
||||
if (await IsAuthed())
|
||||
{
|
||||
var stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
||||
await AppHelpers.LogOutAsync(await stateService.GetActiveUserIdAsync());
|
||||
await AppHelpers.LogOutAsync(await _stateService.Value.GetActiveUserIdAsync());
|
||||
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||
if (deviceActionService.SystemMajorVersion() >= 12)
|
||||
{
|
||||
@@ -331,12 +331,16 @@ namespace Bit.iOS.Autofill
|
||||
Bit.Core.Constants.iOSAutoFillClearCiphersCacheKey, Bit.Core.Constants.iOSAllClearCipherCacheKeys);
|
||||
iOSCoreHelpers.InitLogger();
|
||||
iOSCoreHelpers.Bootstrap();
|
||||
var app = new App.App(new AppOptions { IosExtension = true });
|
||||
var appOptions = new AppOptions { IosExtension = true };
|
||||
var app = new App.App(appOptions);
|
||||
ThemeManager.SetTheme(app.Resources);
|
||||
iOSCoreHelpers.AppearanceAdjustments();
|
||||
_nfcDelegate = new Core.NFCReaderDelegate((success, message) =>
|
||||
messagingService.Send("gotYubiKeyOTP", message));
|
||||
iOSCoreHelpers.SubscribeBroadcastReceiver(this, _nfcSession, _nfcDelegate);
|
||||
|
||||
_accountsManager = ServiceContainer.Resolve<IAccountsManager>("accountsManager");
|
||||
_accountsManager.Init(() => appOptions, this);
|
||||
}
|
||||
|
||||
private void InitAppIfNeeded()
|
||||
@@ -514,5 +518,35 @@ namespace Bit.iOS.Autofill
|
||||
updateTempPasswordController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
|
||||
PresentViewController(updateTempPasswordController, true, null);
|
||||
}
|
||||
|
||||
public Task SetPreviousPageInfoAsync() => Task.CompletedTask;
|
||||
public Task UpdateThemeAsync() => Task.CompletedTask;
|
||||
|
||||
public void Navigate(NavigationTarget navTarget, INavigationParams navParams = null)
|
||||
{
|
||||
switch (navTarget)
|
||||
{
|
||||
case NavigationTarget.HomeLogin:
|
||||
DismissViewController(false, () => LaunchHomePage());
|
||||
break;
|
||||
case NavigationTarget.Login:
|
||||
if (navParams is LoginNavigationParams loginParams)
|
||||
{
|
||||
DismissViewController(false, () => LaunchLoginFlow(loginParams.Email));
|
||||
}
|
||||
else
|
||||
{
|
||||
DismissViewController(false, () => LaunchLoginFlow());
|
||||
}
|
||||
break;
|
||||
case NavigationTarget.Lock:
|
||||
DismissViewController(false, () => PerformSegue("lockPasswordSegue", this));
|
||||
break;
|
||||
case NavigationTarget.AutofillCiphers:
|
||||
case NavigationTarget.Home:
|
||||
DismissViewController(false, () => PerformSegue("loginListSegue", this));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user