mirror of
https://github.com/bitwarden/mobile.git
synced 2024-12-27 17:08:00 +01:00
[SG-705] Popup when a request for authentication comes in on a logged-in account that is not active (#2135)
* [SG-705] Added pop up to perform account switching if the user receives a login request from another account. * [SG-705] missing resource designer * [SG-705] Fixed wrong key for state service variable. * [SG-705] Fix formatting of account switch alert. * [SG-705] dotnet format run * [SG-705] Removed async * [SG-705] Refactor on App
This commit is contained in:
parent
d18efdea73
commit
eefc9bd239
@ -11,6 +11,7 @@ using Bit.Core;
|
|||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Models.Data;
|
using Bit.Core.Models.Data;
|
||||||
|
using Bit.Core.Models.Response;
|
||||||
using Bit.Core.Services;
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
@ -168,13 +169,17 @@ namespace Bit.App
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var notification = await _stateService.GetPasswordlessLoginNotificationAsync();
|
var notification = await _stateService.GetPasswordlessLoginNotificationAsync();
|
||||||
if (notification == null)
|
if (notification == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (await CheckShouldSwitchActiveUserAsync(notification))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Delay to wait for the vault page to appear
|
// Delay to wait for the vault page to appear
|
||||||
await Task.Delay(2000);
|
await Task.Delay(2000);
|
||||||
var loginRequestData = await _authService.GetPasswordlessLoginRequestByIdAsync(notification.Id);
|
var loginRequestData = await _authService.GetPasswordlessLoginRequestByIdAsync(notification.Id);
|
||||||
@ -197,6 +202,27 @@ namespace Bit.App
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<bool> CheckShouldSwitchActiveUserAsync(PasswordlessRequestNotification notification)
|
||||||
|
{
|
||||||
|
var activeUserId = await _stateService.GetActiveUserIdAsync();
|
||||||
|
if (notification.UserId == activeUserId)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var notificationUserEmail = await _stateService.GetEmailAsync(notification.UserId);
|
||||||
|
await Device.InvokeOnMainThreadAsync(async () =>
|
||||||
|
{
|
||||||
|
var result = await _deviceActionService.DisplayAlertAsync(AppResources.LogInRequested, string.Format(AppResources.LoginAttemptFromXDoYouWantToSwitchToThisAccount, notificationUserEmail), AppResources.Cancel, AppResources.Ok);
|
||||||
|
if (result == AppResources.Ok)
|
||||||
|
{
|
||||||
|
await _stateService.SetActiveUserAsync(notification.UserId);
|
||||||
|
_messagingService.Send(AccountsManagerMessageCommands.SWITCHED_ACCOUNT);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public AppOptions Options { get; private set; }
|
public AppOptions Options { get; private set; }
|
||||||
|
|
||||||
protected async override void OnStart()
|
protected async override void OnStart()
|
||||||
|
380
src/App/Resources/AppResources.Designer.cs
generated
380
src/App/Resources/AppResources.Designer.cs
generated
File diff suppressed because it is too large
Load Diff
@ -2464,4 +2464,9 @@ select Add TOTP to store the key safely</value>
|
|||||||
<data name="LoginRequestHasAlreadyExpired" xml:space="preserve">
|
<data name="LoginRequestHasAlreadyExpired" xml:space="preserve">
|
||||||
<value>Login request has already expired.</value>
|
<value>Login request has already expired.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="LoginAttemptFromXDoYouWantToSwitchToThisAccount" xml:space="preserve">
|
||||||
|
<value>Login attempt from:
|
||||||
|
{0}
|
||||||
|
Do you want to switch to this account?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
@ -146,7 +146,7 @@ namespace Bit.App.Services
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _stateService.Value.SetPasswordlessLoginNotificationAsync(passwordlessLoginMessage, passwordlessLoginMessage?.UserId);
|
await _stateService.Value.SetPasswordlessLoginNotificationAsync(passwordlessLoginMessage);
|
||||||
var userEmail = await _stateService.Value.GetEmailAsync(passwordlessLoginMessage?.UserId);
|
var userEmail = await _stateService.Value.GetEmailAsync(passwordlessLoginMessage?.UserId);
|
||||||
|
|
||||||
var notificationData = new PasswordlessNotificationData()
|
var notificationData = new PasswordlessNotificationData()
|
||||||
@ -247,14 +247,10 @@ namespace Bit.App.Services
|
|||||||
{
|
{
|
||||||
if (data is PasswordlessNotificationData passwordlessNotificationData)
|
if (data is PasswordlessNotificationData passwordlessNotificationData)
|
||||||
{
|
{
|
||||||
var notificationUserId = await _stateService.Value.GetUserIdAsync(passwordlessNotificationData.UserEmail);
|
var savedNotification = await _stateService.Value.GetPasswordlessLoginNotificationAsync();
|
||||||
if (notificationUserId != null)
|
if (savedNotification != null)
|
||||||
{
|
{
|
||||||
var savedNotification = await _stateService.Value.GetPasswordlessLoginNotificationAsync(notificationUserId);
|
await _stateService.Value.SetPasswordlessLoginNotificationAsync(null);
|
||||||
if (savedNotification != null)
|
|
||||||
{
|
|
||||||
await _stateService.Value.SetPasswordlessLoginNotificationAsync(null, notificationUserId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,8 +154,8 @@ namespace Bit.Core.Abstractions
|
|||||||
Task SaveExtensionActiveUserIdToStorageAsync(string userId);
|
Task SaveExtensionActiveUserIdToStorageAsync(string userId);
|
||||||
Task<bool> GetApprovePasswordlessLoginsAsync(string userId = null);
|
Task<bool> GetApprovePasswordlessLoginsAsync(string userId = null);
|
||||||
Task SetApprovePasswordlessLoginsAsync(bool? value, string userId = null);
|
Task SetApprovePasswordlessLoginsAsync(bool? value, string userId = null);
|
||||||
Task<PasswordlessRequestNotification> GetPasswordlessLoginNotificationAsync(string userId = null);
|
Task<PasswordlessRequestNotification> GetPasswordlessLoginNotificationAsync();
|
||||||
Task SetPasswordlessLoginNotificationAsync(PasswordlessRequestNotification value, string userId = null);
|
Task SetPasswordlessLoginNotificationAsync(PasswordlessRequestNotification value);
|
||||||
Task<UsernameGenerationOptions> GetUsernameGenerationOptionsAsync(string userId = null);
|
Task<UsernameGenerationOptions> GetUsernameGenerationOptionsAsync(string userId = null);
|
||||||
Task SetUsernameGenerationOptionsAsync(UsernameGenerationOptions value, string userId = null);
|
Task SetUsernameGenerationOptionsAsync(UsernameGenerationOptions value, string userId = null);
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
public static string EventCollectionKey = "eventCollection";
|
public static string EventCollectionKey = "eventCollection";
|
||||||
public static string RememberedEmailKey = "rememberedEmail";
|
public static string RememberedEmailKey = "rememberedEmail";
|
||||||
public static string RememberedOrgIdentifierKey = "rememberedOrgIdentifier";
|
public static string RememberedOrgIdentifierKey = "rememberedOrgIdentifier";
|
||||||
|
public static string PasswordlessLoginNotificationKey = "passwordlessLoginNotificationKey";
|
||||||
public const string PasswordlessNotificationId = "26072022";
|
public const string PasswordlessNotificationId = "26072022";
|
||||||
public const string AndroidNotificationChannelId = "general_notification_channel";
|
public const string AndroidNotificationChannelId = "general_notification_channel";
|
||||||
public const string iOSNotificationCategoryId = "dismissableCategory";
|
public const string iOSNotificationCategoryId = "dismissableCategory";
|
||||||
@ -93,7 +94,6 @@
|
|||||||
public static string LastSyncKey(string userId) => $"lastSync_{userId}";
|
public static string LastSyncKey(string userId) => $"lastSync_{userId}";
|
||||||
public static string BiometricUnlockKey(string userId) => $"biometricUnlock_{userId}";
|
public static string BiometricUnlockKey(string userId) => $"biometricUnlock_{userId}";
|
||||||
public static string ApprovePasswordlessLoginsKey(string userId) => $"approvePasswordlessLogins_{userId}";
|
public static string ApprovePasswordlessLoginsKey(string userId) => $"approvePasswordlessLogins_{userId}";
|
||||||
public static string PasswordlessLoginNofiticationKey(string userId) => $"passwordlessLoginNofitication_{userId}";
|
|
||||||
public static string UsernameGenOptionsKey(string userId) => $"usernameGenerationOptions_{userId}";
|
public static string UsernameGenOptionsKey(string userId) => $"usernameGenerationOptions_{userId}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1277,20 +1277,18 @@ namespace Bit.Core.Services
|
|||||||
await SetValueAsync(key, value, reconciledOptions);
|
await SetValueAsync(key, value, reconciledOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<PasswordlessRequestNotification> GetPasswordlessLoginNotificationAsync(string userId = null)
|
public async Task<PasswordlessRequestNotification> GetPasswordlessLoginNotificationAsync()
|
||||||
{
|
{
|
||||||
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
var options = await GetDefaultStorageOptionsAsync();
|
||||||
await GetDefaultStorageOptionsAsync());
|
var key = Constants.PasswordlessLoginNotificationKey;
|
||||||
var key = Constants.PasswordlessLoginNofiticationKey(reconciledOptions.UserId);
|
return await GetValueAsync<PasswordlessRequestNotification>(key, options);
|
||||||
return await GetValueAsync<PasswordlessRequestNotification>(key, reconciledOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SetPasswordlessLoginNotificationAsync(PasswordlessRequestNotification value, string userId = null)
|
public async Task SetPasswordlessLoginNotificationAsync(PasswordlessRequestNotification value)
|
||||||
{
|
{
|
||||||
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
var options = await GetDefaultStorageOptionsAsync();
|
||||||
await GetDefaultStorageOptionsAsync());
|
var key = Constants.PasswordlessLoginNotificationKey;
|
||||||
var key = Constants.PasswordlessLoginNofiticationKey(reconciledOptions.UserId);
|
await SetValueAsync(key, value, options);
|
||||||
await SetValueAsync(key, value, reconciledOptions);
|
|
||||||
}
|
}
|
||||||
// Helpers
|
// Helpers
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user