1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-15 15:53:44 +00:00

sync service

This commit is contained in:
Kyle Spearrin
2019-04-17 12:12:43 -04:00
parent 808fcea655
commit 818414eb37
7 changed files with 262 additions and 7 deletions

View File

@@ -1,16 +1,16 @@
using Bit.Core.Abstractions;
using Bit.Core.Exceptions;
using Bit.Core.Models.Data;
using Bit.Core.Models.Response;
using Bit.Core.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Bit.Core.Services
{
public class SyncService
public class SyncService : ISyncService
{
private const string Keys_LastSyncFormat = "lastSync_{0}";
@@ -58,7 +58,7 @@ namespace Bit.Core.Services
return await _storageService.GetAsync<DateTime?>(string.Format(Keys_LastSyncFormat, userId));
}
public async Task SetLastSync(DateTime date)
public async Task SetLastSyncAsync(DateTime date)
{
var userId = await _userService.GetUserIdAsync();
if(userId == null)
@@ -68,6 +68,188 @@ namespace Bit.Core.Services
await _storageService.SaveAsync(string.Format(Keys_LastSyncFormat, userId), date);
}
public async Task<bool> FullSyncAsync(bool forceSync)
{
SyncStarted();
var isAuthenticated = await _userService.IsAuthenticatedAsync();
if(!isAuthenticated)
{
return SyncCompleted(false);
}
var now = DateTime.UtcNow;
var needsSyncResult = await NeedsSyncingAsync(forceSync);
var needsSync = needsSyncResult.Item1;
var skipped = needsSyncResult.Item2;
if(skipped)
{
return SyncCompleted(false);
}
if(!needsSync)
{
await SetLastSyncAsync(now);
return SyncCompleted(false);
}
var userId = await _userService.GetUserIdAsync();
try
{
var response = await _apiService.GetSyncAsync();
await SyncProfileAsync(response.Profile);
await SyncFoldersAsync(userId, response.Folders);
await SyncCollectionsAsync(response.Collections);
await SyncCiphersAsync(userId, response.Ciphers);
await SyncSettingsAsync(userId, response.Domains);
await SetLastSyncAsync(now);
return SyncCompleted(true);
}
catch
{
return SyncCompleted(false);
}
}
public async Task<bool> SyncUpsertFolderAsync(SyncFolderNotification notification, bool isEdit)
{
SyncStarted();
if(await _userService.IsAuthenticatedAsync())
{
try
{
var localFolder = await _folderService.GetAsync(notification.Id);
if((!isEdit && localFolder == null) ||
(isEdit && localFolder != null && localFolder.RevisionDate < notification.RevisionDate))
{
var remoteFolder = await _apiService.GetFolderAsync(notification.Id);
if(remoteFolder != null)
{
var userId = await _userService.GetUserIdAsync();
await _folderService.UpsertAsync(new FolderData(remoteFolder, userId));
_messagingService.Send("syncedUpsertedFolder", new Dictionary<string, string>
{
["folderId"] = notification.Id
});
return SyncCompleted(true);
}
}
}
catch { }
}
return SyncCompleted(false);
}
public async Task<bool> SyncDeleteFolderAsync(SyncFolderNotification notification)
{
SyncStarted();
if(await _userService.IsAuthenticatedAsync())
{
await _folderService.DeleteAsync(notification.Id);
_messagingService.Send("syncedDeletedFolder", new Dictionary<string, string>
{
["folderId"] = notification.Id
});
return SyncCompleted(true);
}
return SyncCompleted(false);
}
public async Task<bool> SyncUpsertCipherAsync(SyncCipherNotification notification, bool isEdit)
{
SyncStarted();
if(await _userService.IsAuthenticatedAsync())
{
try
{
var shouldUpdate = true;
var localCipher = await _cipherService.GetAsync(notification.Id);
if(localCipher != null && localCipher.RevisionDate >= notification.RevisionDate)
{
shouldUpdate = false;
}
var checkCollections = false;
if(shouldUpdate)
{
if(isEdit)
{
shouldUpdate = localCipher != null;
checkCollections = true;
}
else
{
if(notification.CollectionIds == null || notification.OrganizationId == null)
{
shouldUpdate = localCipher == null;
}
else
{
shouldUpdate = false;
checkCollections = true;
}
}
}
if(!shouldUpdate && checkCollections && notification.OrganizationId != null &&
notification.CollectionIds != null && notification.CollectionIds.Any())
{
var collections = await _collectionService.GetAllAsync();
if(collections != null)
{
foreach(var c in collections)
{
if(notification.CollectionIds.Contains(c.Id))
{
shouldUpdate = true;
break;
}
}
}
}
if(shouldUpdate)
{
var remoteCipher = await _apiService.GetCipherAsync(notification.Id);
if(remoteCipher != null)
{
var userId = await _userService.GetUserIdAsync();
await _cipherService.UpsertAsync(new CipherData(remoteCipher, userId));
_messagingService.Send("syncedUpsertedCipher", new Dictionary<string, string>
{
["cipherId"] = notification.Id
});
return SyncCompleted(true);
}
}
}
catch(ApiException e)
{
if(e.Error != null && e.Error.StatusCode == System.Net.HttpStatusCode.NotFound && isEdit)
{
await _cipherService.DeleteAsync(notification.Id);
_messagingService.Send("syncedDeletedCipher", new Dictionary<string, string>
{
["cipherId"] = notification.Id
});
return SyncCompleted(true);
}
}
}
return SyncCompleted(false);
}
public async Task<bool> SyncDeleteCipherAsync(SyncCipherNotification notification)
{
SyncStarted();
if(await _userService.IsAuthenticatedAsync())
{
await _cipherService.DeleteAsync(notification.Id);
_messagingService.Send("syncedDeletedCipher", new Dictionary<string, string>
{
["cipherId"] = notification.Id
});
return SyncCompleted(true);
}
return SyncCompleted(false);
}
// Helpers
private void SyncStarted()
@@ -76,7 +258,7 @@ namespace Bit.Core.Services
_messagingService.Send("syncStarted");
}
private bool SyncCompelted(bool successfully)
private bool SyncCompleted(bool successfully)
{
SyncInProgress = false;
_messagingService.Send("syncCompleted", new Dictionary<string, object> { ["successfully"] = successfully });