mirror of
https://github.com/bitwarden/mobile
synced 2026-01-04 01:23:15 +00:00
push notification services
This commit is contained in:
14
src/App/Abstractions/IPushNotificationListenerService.cs
Normal file
14
src/App/Abstractions/IPushNotificationListenerService.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IPushNotificationListenerService
|
||||
{
|
||||
Task OnMessageAsync(JObject values, string device);
|
||||
Task OnRegisteredAsync(string token, string device);
|
||||
void OnUnregistered(string device);
|
||||
void OnError(string message, string device);
|
||||
bool ShouldShowNotification();
|
||||
}
|
||||
}
|
||||
11
src/App/Abstractions/IPushNotificationService.cs
Normal file
11
src/App/Abstractions/IPushNotificationService.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IPushNotificationService
|
||||
{
|
||||
Task<string> GetTokenAsync();
|
||||
Task RegisterAsync();
|
||||
Task UnregisterAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
using Bit.App.Resources;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Resources;
|
||||
using Bit.Core;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Utilities;
|
||||
@@ -12,6 +14,8 @@ namespace Bit.App.Pages
|
||||
{
|
||||
private readonly IBroadcasterService _broadcasterService;
|
||||
private readonly ISyncService _syncService;
|
||||
private readonly IPushNotificationService _pushNotificationService;
|
||||
private readonly IStorageService _storageService;
|
||||
private readonly GroupingsPageViewModel _vm;
|
||||
private readonly string _pageName;
|
||||
|
||||
@@ -23,6 +27,8 @@ namespace Bit.App.Pages
|
||||
SetActivityIndicator(_mainContent);
|
||||
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
|
||||
_syncService = ServiceContainer.Resolve<ISyncService>("syncService");
|
||||
_pushNotificationService = ServiceContainer.Resolve<IPushNotificationService>("pushNotificationService");
|
||||
_storageService = ServiceContainer.Resolve<IStorageService>("storageService");
|
||||
_vm = BindingContext as GroupingsPageViewModel;
|
||||
_vm.Page = this;
|
||||
_vm.MainPage = mainPage;
|
||||
@@ -71,6 +77,30 @@ namespace Bit.App.Pages
|
||||
}
|
||||
}
|
||||
}, _mainContent);
|
||||
|
||||
// Push registration
|
||||
var lastPushRegistration = await _storageService.GetAsync<DateTime?>(Constants.PushLastRegistrationDateKey);
|
||||
lastPushRegistration = lastPushRegistration.GetValueOrDefault(DateTime.MinValue);
|
||||
if(Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
var pushPromptShow = await _storageService.GetAsync<bool?>(Constants.PushInitialPromptShownKey);
|
||||
if(!pushPromptShow.GetValueOrDefault(false))
|
||||
{
|
||||
await _storageService.SaveAsync(Constants.PushInitialPromptShownKey, true);
|
||||
await DisplayAlert(AppResources.EnableAutomaticSyncing, AppResources.PushNotificationAlert,
|
||||
AppResources.OkGotIt);
|
||||
}
|
||||
if(!pushPromptShow.GetValueOrDefault(false) ||
|
||||
DateTime.UtcNow - lastPushRegistration > TimeSpan.FromDays(1))
|
||||
{
|
||||
await _pushNotificationService.RegisterAsync();
|
||||
}
|
||||
}
|
||||
else if(Device.RuntimePlatform == Device.Android &&
|
||||
DateTime.UtcNow - lastPushRegistration > TimeSpan.FromDays(1))
|
||||
{
|
||||
await _pushNotificationService.RegisterAsync();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDisappearing()
|
||||
|
||||
32
src/App/Services/NoopPushNotificationListenerService.cs
Normal file
32
src/App/Services/NoopPushNotificationListenerService.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Bit.App.Abstractions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bit.App.Services
|
||||
{
|
||||
public class NoopPushNotificationListenerService : IPushNotificationListenerService
|
||||
{
|
||||
public Task OnMessageAsync(JObject value, string deviceType)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task OnRegisteredAsync(string token, string deviceType)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public void OnUnregistered(string deviceType)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnError(string message, string deviceType)
|
||||
{
|
||||
}
|
||||
|
||||
public bool ShouldShowNotification()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
src/App/Services/NoopPushNotificationService.cs
Normal file
23
src/App/Services/NoopPushNotificationService.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Abstractions;
|
||||
|
||||
namespace Bit.App.Services
|
||||
{
|
||||
public class NoopPushNotificationService : IPushNotificationService
|
||||
{
|
||||
public Task<string> GetTokenAsync()
|
||||
{
|
||||
return Task.FromResult(null as string);
|
||||
}
|
||||
|
||||
public Task RegisterAsync()
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task UnregisterAsync()
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
187
src/App/Services/PushNotificationListenerService.cs
Normal file
187
src/App/Services/PushNotificationListenerService.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
#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
|
||||
{
|
||||
private bool _showNotification;
|
||||
private bool _resolved;
|
||||
private IStorageService _storageService;
|
||||
private ISyncService _syncService;
|
||||
private IUserService _userService;
|
||||
private IAppIdService _appIdService;
|
||||
private IApiService _apiService;
|
||||
private IMessagingService _messagingService;
|
||||
|
||||
public async Task OnMessageAsync(JObject value, string deviceType)
|
||||
{
|
||||
Resolve();
|
||||
if(value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_showNotification = false;
|
||||
Debug.WriteLine("Message Arrived: {0}", 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>();
|
||||
}
|
||||
|
||||
var appId = await _appIdService.GetAppIdAsync();
|
||||
if(notification?.Payload == null || notification.ContextId == appId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var myUserId = await _userService.GetUserIdAsync();
|
||||
var isAuthenticated = await _userService.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(string.Format("Push Notification - Device Registered - Token : {0}", token));
|
||||
var isAuthenticated = await _userService.IsAuthenticatedAsync();
|
||||
if(!isAuthenticated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var appId = await _appIdService.GetAppIdAsync();
|
||||
try
|
||||
{
|
||||
await _apiService.PutDeviceTokenAsync(appId,
|
||||
new Core.Models.Request.DeviceTokenRequest { PushToken = token });
|
||||
Debug.WriteLine("Registered device with server.");
|
||||
await _storageService.SaveAsync(Constants.PushLastRegistrationDateKey, DateTime.UtcNow);
|
||||
if(deviceType == Device.Android)
|
||||
{
|
||||
await _storageService.SaveAsync(Constants.PushCurrentTokenKey, token);
|
||||
}
|
||||
}
|
||||
catch(ApiException)
|
||||
{
|
||||
Debug.WriteLine("Failed to register device.");
|
||||
}
|
||||
}
|
||||
|
||||
public void OnUnregistered(string deviceType)
|
||||
{
|
||||
Debug.WriteLine("Push Notification - Device Unnregistered");
|
||||
}
|
||||
|
||||
public void OnError(string message, string deviceType)
|
||||
{
|
||||
Debug.WriteLine(string.Format("Push notification error - {0}", message));
|
||||
}
|
||||
|
||||
public bool ShouldShowNotification()
|
||||
{
|
||||
return _showNotification;
|
||||
}
|
||||
|
||||
private void Resolve()
|
||||
{
|
||||
if(_resolved)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_storageService = ServiceContainer.Resolve<IStorageService>("storageService");
|
||||
_syncService = ServiceContainer.Resolve<ISyncService>("syncService");
|
||||
_userService = ServiceContainer.Resolve<IUserService>("userService");
|
||||
_appIdService = ServiceContainer.Resolve<IAppIdService>("appIdService");
|
||||
_apiService = ServiceContainer.Resolve<IApiService>("apiService");
|
||||
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
|
||||
_resolved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user