1
0
mirror of https://github.com/bitwarden/mobile.git synced 2024-09-26 03:42:57 +02:00
bitwarden-mobile/src/App/Services/PushNotificationListenerService.cs
Matt Portune 2e8824ce05
Account Switching (#1807)
* Account Switching (#1720)

* Account switching

* WIP

* wip

* wip

* updates to send test logic

* fixed Send tests

* fixes for theme handling on account switching and re-adding existing account

* switch fixes

* fixes

* fixes

* cleanup

* vault timeout fixes

* account list status enhancements

* logout fixes and token handling improvements

* merge latest (#1727)

* remove duplicate dependency

* fix for initial login token storage paradox (#1730)

* Fix avatar color update toolbar item issue on iOS for account switching (#1735)

* Updated account switching menu UI (#1733)

* updated account switching menu UI

* additional changes

* add key suffix to constant

* GetFirstLetters method tweaks

* Fix crash on account switching when logging out when having more than user at a time (#1740)

* single account migration to multi-account on app update (#1741)

* Account Switching Tap to dismiss (#1743)

* Added tap to dismiss on the Account switching overlay and improved a bit the code

* Fix account switching overlay background transparent on the proper place

* Fixed transparent background and the shadow on the account switching overlay

* Fix iOS top space on Account switching list overlay after modal (#1746)

* Fix top space added to Account switching list overlay after closing modal

* Fix top space added to Account switching list overlay after closing modal on lock, login and home views just in case we add modals in the future there as well

* Usability: dismiss account list on certain events (#1748)

* dismiss account list on certain events

* use new FireAndForget method for back button logic

* Create and use Account Switching overlay control (#1753)

* Added Account switching overlay control and its own ViewModel and refactored accordingly

* Fix account switching Accounts list binding update

* Implemented dismiss account switching overlay when changing tabs and when selecting the same tab. Also updated the deprecated listener on CustomTabbedRenderer on Android (#1755)

* Overriden Equals on AvatarImageSource so it doesn't get set multiple times when it's the same image thus producing blinking on tab chaged (#1756)

* Usability improvements for logout on vault timeout (#1781)

* accountswitching fixes (#1784)

* Fix for invalid PIN lock state when switching accounts (#1792)

* fix for pin lock flow

* named tuple values and updated async

* clear send service cache on account switch (#1796)

* Global theme and account removal (#1793)

* Global theme and account removal

* remove redundant call to hide account list overlay

* cleanup and additional tweaks

* add try/catch to remove account dialog flow

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
2022-02-23 12:40:17 -05:00

212 lines
7.7 KiB
C#

#if !FDROID
using System.Diagnostics;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Bit.App.Abstractions;
using System;
using Xamarin.Forms;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using System.Threading.Tasks;
using Bit.Core.Enums;
using Bit.Core;
using Bit.Core.Models.Response;
using Bit.Core.Exceptions;
namespace Bit.App.Services
{
public class PushNotificationListenerService : IPushNotificationListenerService
{
const string TAG = "##PUSH NOTIFICATIONS";
private bool _showNotification;
private bool _resolved;
private ISyncService _syncService;
private IStateService _stateService;
private IAppIdService _appIdService;
private IApiService _apiService;
private IMessagingService _messagingService;
public async Task OnMessageAsync(JObject value, string deviceType)
{
Debug.WriteLine($"{TAG} OnMessageAsync called");
Resolve();
if (value == null)
{
return;
}
_showNotification = false;
Debug.WriteLine($"{TAG} Message Arrived: {JsonConvert.SerializeObject(value)}");
NotificationResponse notification = null;
if (deviceType == Device.Android)
{
notification = value.ToObject<NotificationResponse>();
}
else
{
if (!value.TryGetValue("data", StringComparison.OrdinalIgnoreCase, out JToken dataToken) ||
dataToken == null)
{
return;
}
notification = dataToken.ToObject<NotificationResponse>();
}
Debug.WriteLine($"{TAG} - Notification object created: t:{notification?.Type} - p:{notification?.Payload}");
var appId = await _appIdService.GetAppIdAsync();
if (notification?.Payload == null || notification.ContextId == appId)
{
return;
}
var myUserId = await _stateService.GetActiveUserIdAsync();
var isAuthenticated = await _stateService.IsAuthenticatedAsync();
switch (notification.Type)
{
case NotificationType.SyncCipherUpdate:
case NotificationType.SyncCipherCreate:
var cipherCreateUpdateMessage = JsonConvert.DeserializeObject<SyncCipherNotification>(
notification.Payload);
if (isAuthenticated && cipherCreateUpdateMessage.UserId == myUserId)
{
await _syncService.SyncUpsertCipherAsync(cipherCreateUpdateMessage,
notification.Type == NotificationType.SyncCipherUpdate);
}
break;
case NotificationType.SyncFolderUpdate:
case NotificationType.SyncFolderCreate:
var folderCreateUpdateMessage = JsonConvert.DeserializeObject<SyncFolderNotification>(
notification.Payload);
if (isAuthenticated && folderCreateUpdateMessage.UserId == myUserId)
{
await _syncService.SyncUpsertFolderAsync(folderCreateUpdateMessage,
notification.Type == NotificationType.SyncFolderUpdate);
}
break;
case NotificationType.SyncLoginDelete:
case NotificationType.SyncCipherDelete:
var loginDeleteMessage = JsonConvert.DeserializeObject<SyncCipherNotification>(
notification.Payload);
if (isAuthenticated && loginDeleteMessage.UserId == myUserId)
{
await _syncService.SyncDeleteCipherAsync(loginDeleteMessage);
}
break;
case NotificationType.SyncFolderDelete:
var folderDeleteMessage = JsonConvert.DeserializeObject<SyncFolderNotification>(
notification.Payload);
if (isAuthenticated && folderDeleteMessage.UserId == myUserId)
{
await _syncService.SyncDeleteFolderAsync(folderDeleteMessage);
}
break;
case NotificationType.SyncCiphers:
case NotificationType.SyncVault:
case NotificationType.SyncSettings:
if (isAuthenticated)
{
await _syncService.FullSyncAsync(false);
}
break;
case NotificationType.SyncOrgKeys:
if (isAuthenticated)
{
await _apiService.RefreshIdentityTokenAsync();
await _syncService.FullSyncAsync(true);
}
break;
case NotificationType.LogOut:
if (isAuthenticated)
{
_messagingService.Send("logout");
}
break;
default:
break;
}
}
public async Task OnRegisteredAsync(string token, string deviceType)
{
Resolve();
Debug.WriteLine($"{TAG} - Device Registered - Token : {token}");
var isAuthenticated = await _stateService.IsAuthenticatedAsync();
if (!isAuthenticated)
{
Debug.WriteLine($"{TAG} - not auth");
return;
}
var appId = await _appIdService.GetAppIdAsync();
try
{
#if DEBUG
await _stateService.SetPushInstallationRegistrationErrorAsync(null);
#endif
await _apiService.PutDeviceTokenAsync(appId,
new Core.Models.Request.DeviceTokenRequest { PushToken = token });
Debug.WriteLine($"{TAG} Registered device with server.");
await _stateService.SetPushLastRegistrationDateAsync(DateTime.UtcNow);
if (deviceType == Device.Android)
{
await _stateService.SetPushCurrentTokenAsync(token);
}
}
#if DEBUG
catch (ApiException apiEx)
{
Debug.WriteLine($"{TAG} Failed to register device.");
await _stateService.SetPushInstallationRegistrationErrorAsync(apiEx.Error?.Message);
}
catch (Exception e)
{
await _stateService.SetPushInstallationRegistrationErrorAsync(e.Message);
throw;
}
#else
catch (ApiException)
{
}
#endif
}
public void OnUnregistered(string deviceType)
{
Debug.WriteLine($"{TAG} - Device Unnregistered");
}
public void OnError(string message, string deviceType)
{
Debug.WriteLine($"{TAG} error - {message}");
}
public bool ShouldShowNotification()
{
return _showNotification;
}
private void Resolve()
{
if (_resolved)
{
return;
}
_syncService = ServiceContainer.Resolve<ISyncService>("syncService");
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
_appIdService = ServiceContainer.Resolve<IAppIdService>("appIdService");
_apiService = ServiceContainer.Resolve<IApiService>("apiService");
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_resolved = true;
}
}
}
#endif