diff --git a/src/Core/Enums/PushType.cs b/src/Core/Enums/PushType.cs index e919e92006..5d36113833 100644 --- a/src/Core/Enums/PushType.cs +++ b/src/Core/Enums/PushType.cs @@ -6,6 +6,13 @@ SyncCipherCreate = 1, SyncLoginDelete = 2, SyncFolderDelete = 3, - SyncCiphers = 4 + SyncCiphers = 4, + + SyncVault = 5, + SyncOrgKeys = 6, + SyncFolderCreate = 7, + SyncFolderUpdate = 8, + SyncCipherDelete = 9, + SyncSettings = 10 } } diff --git a/src/Core/Services/IPushService.cs b/src/Core/Services/IPushService.cs index 70aff578f9..57253113cd 100644 --- a/src/Core/Services/IPushService.cs +++ b/src/Core/Services/IPushService.cs @@ -9,6 +9,12 @@ namespace Bit.Core.Services Task PushSyncCipherCreateAsync(Cipher cipher); Task PushSyncCipherUpdateAsync(Cipher cipher); Task PushSyncCipherDeleteAsync(Cipher cipher); + Task PushSyncFolderCreateAsync(Folder folder); + Task PushSyncFolderUpdateAsync(Folder folder); + Task PushSyncFolderDeleteAsync(Folder folder); Task PushSyncCiphersAsync(Guid userId); + Task PushSyncVaultAsync(Guid userId); + Task PushSyncOrgKeysAsync(Guid userId); + Task PushSyncSettingsAsync(Guid userId); } } diff --git a/src/Core/Services/Implementations/CipherService.cs b/src/Core/Services/Implementations/CipherService.cs index d0afb7878b..630320f847 100644 --- a/src/Core/Services/Implementations/CipherService.cs +++ b/src/Core/Services/Implementations/CipherService.cs @@ -53,7 +53,7 @@ namespace Bit.Core.Services await _cipherRepository.CreateAsync(cipher); // push - //await _pushService.PushSyncCipherCreateAsync(cipher); + await _pushService.PushSyncCipherCreateAsync(cipher); } else { @@ -61,7 +61,7 @@ namespace Bit.Core.Services await _cipherRepository.ReplaceAsync(cipher); // push - //await _pushService.PushSyncCipherUpdateAsync(cipher); + await _pushService.PushSyncCipherUpdateAsync(cipher); } } @@ -75,7 +75,7 @@ namespace Bit.Core.Services await _cipherRepository.DeleteAsync(cipher); // push - //await _pushService.PushSyncCipherDeleteAsync(cipher); + await _pushService.PushSyncCipherDeleteAsync(cipher); } public async Task SaveFolderAsync(Folder folder) @@ -85,7 +85,7 @@ namespace Bit.Core.Services await _folderRepository.CreateAsync(folder); // push - //await _pushService.PushSyncCipherCreateAsync(cipher); + await _pushService.PushSyncFolderCreateAsync(folder); } else { @@ -93,7 +93,7 @@ namespace Bit.Core.Services await _folderRepository.UpsertAsync(folder); // push - //await _pushService.PushSyncCipherUpdateAsync(cipher); + await _pushService.PushSyncFolderUpdateAsync(folder); } } @@ -102,7 +102,7 @@ namespace Bit.Core.Services await _folderRepository.DeleteAsync(folder); // push - //await _pushService.PushSyncCipherDeleteAsync(cipher); + await _pushService.PushSyncFolderDeleteAsync(folder); } public async Task ShareAsync(Cipher cipher, Guid organizationId, IEnumerable subvaultIds, Guid sharingUserId) @@ -129,7 +129,7 @@ namespace Bit.Core.Services await _cipherRepository.ReplaceAsync(cipher, subvaultIds); // push - //await _pushService.PushSyncCipherUpdateAsync(cipher); + await _pushService.PushSyncCipherUpdateAsync(cipher); } public async Task SaveSubvaultsAsync(Cipher cipher, IEnumerable subvaultIds, Guid savingUserId, bool orgAdmin) @@ -156,7 +156,7 @@ namespace Bit.Core.Services } // push - //await _pushService.PushSyncCipherUpdateAsync(cipher); + await _pushService.PushSyncCipherUpdateAsync(cipher); } public async Task ImportCiphersAsync( @@ -202,7 +202,7 @@ namespace Bit.Core.Services var userId = folders.FirstOrDefault()?.UserId ?? ciphers.FirstOrDefault()?.UserId; if(userId.HasValue) { - await _pushService.PushSyncCiphersAsync(userId.Value); + await _pushService.PushSyncVaultAsync(userId.Value); } } diff --git a/src/Core/Services/Implementations/OrganizationService.cs b/src/Core/Services/Implementations/OrganizationService.cs index 2195f3be8d..163544ce3c 100644 --- a/src/Core/Services/Implementations/OrganizationService.cs +++ b/src/Core/Services/Implementations/OrganizationService.cs @@ -23,6 +23,7 @@ namespace Bit.Core.Services private readonly IUserRepository _userRepository; private readonly IDataProtector _dataProtector; private readonly IMailService _mailService; + private readonly IPushService _pushService; public OrganizationService( IOrganizationRepository organizationRepository, @@ -31,7 +32,8 @@ namespace Bit.Core.Services ISubvaultUserRepository subvaultUserRepository, IUserRepository userRepository, IDataProtectionProvider dataProtectionProvider, - IMailService mailService) + IMailService mailService, + IPushService pushService) { _organizationRepository = organizationRepository; _organizationUserRepository = organizationUserRepository; @@ -40,6 +42,7 @@ namespace Bit.Core.Services _userRepository = userRepository; _dataProtector = dataProtectionProvider.CreateProtector("OrganizationServiceDataProtector"); _mailService = mailService; + _pushService = pushService; } public async Task GetBillingAsync(Organization organization) { @@ -747,7 +750,7 @@ namespace Bit.Core.Services orgUser.Email = null; await _organizationUserRepository.ReplaceAsync(orgUser); - // TODO: send notification emails to org admins + // TODO: send notification emails to org admins and accepting user? return orgUser; } @@ -774,6 +777,9 @@ namespace Bit.Core.Services await _mailService.SendOrganizationConfirmedEmailAsync(org.Name, user.Email); } + // push + await _pushService.PushSyncOrgKeysAsync(orgUser.UserId.Value); + return orgUser; } diff --git a/src/Core/Services/Implementations/PushSharpPushService.cs b/src/Core/Services/Implementations/PushSharpPushService.cs index b3815e66f3..0571d314e1 100644 --- a/src/Core/Services/Implementations/PushSharpPushService.cs +++ b/src/Core/Services/Implementations/PushSharpPushService.cs @@ -54,9 +54,6 @@ namespace Bit.Core.Services { switch(cipher.Type) { - //case CipherType.Folder: - // await PushCipherAsync(cipher, PushType.SyncFolderDelete); - // break; case CipherType.Login: await PushCipherAsync(cipher, PushType.SyncLoginDelete); break; @@ -65,13 +62,35 @@ namespace Bit.Core.Services } } + public async Task PushSyncFolderCreateAsync(Folder folder) + { + await PushFolderAsync(folder, PushType.SyncCipherCreate); + } + + public async Task PushSyncFolderUpdateAsync(Folder folder) + { + await PushFolderAsync(folder, PushType.SyncFolderUpdate); + } + + public async Task PushSyncFolderDeleteAsync(Folder folder) + { + await PushFolderAsync(folder, PushType.SyncFolderDelete); + } + private async Task PushCipherAsync(Cipher cipher, PushType type) { + if(!cipher.UserId.HasValue) + { + // No push for org ciphers at the moment. + return; + } + var message = new SyncCipherPushNotification { Type = type, Id = cipher.Id, - UserId = cipher.UserId.Value, + UserId = cipher.UserId, + OrganizationId = cipher.OrganizationId, RevisionDate = cipher.RevisionDate, Aps = new PushNotification.AppleData { ContentAvailable = 1 } }; @@ -85,11 +104,51 @@ namespace Bit.Core.Services await PushToAllUserDevicesAsync(cipher.UserId.Value, JObject.FromObject(message), excludedTokens); } + private async Task PushFolderAsync(Folder folder, PushType type) + { + var message = new SyncFolderPushNotification + { + Type = type, + Id = folder.Id, + UserId = folder.UserId, + RevisionDate = folder.RevisionDate, + Aps = new PushNotification.AppleData { ContentAvailable = 1 } + }; + + var excludedTokens = new List(); + if(!string.IsNullOrWhiteSpace(_currentContext.DeviceIdentifier)) + { + excludedTokens.Add(_currentContext.DeviceIdentifier); + } + + await PushToAllUserDevicesAsync(folder.UserId, JObject.FromObject(message), excludedTokens); + } + public async Task PushSyncCiphersAsync(Guid userId) { - var message = new SyncCiphersPushNotification + await PushSyncUserAsync(userId, PushType.SyncCiphers); + } + + public async Task PushSyncVaultAsync(Guid userId) + { + await PushSyncUserAsync(userId, PushType.SyncVault); + } + + public async Task PushSyncOrgKeysAsync(Guid userId) + { + await PushSyncUserAsync(userId, PushType.SyncOrgKeys); + } + + public async Task PushSyncSettingsAsync(Guid userId) + { + await PushSyncUserAsync(userId, PushType.SyncSettings); + } + + private async Task PushSyncUserAsync(Guid userId, PushType type) + { + var message = new SyncUserPushNotification { - Type = PushType.SyncCiphers, + Type = PushType.SyncOrgKeys, UserId = userId, Date = DateTime.UtcNow, Aps = new PushNotification.AppleData { ContentAvailable = 1 } @@ -296,19 +355,24 @@ namespace Bit.Core.Services } } - private abstract class SyncPushNotification : PushNotification - { - public Guid UserId { get; set; } - } - - private class SyncCipherPushNotification : SyncPushNotification + private class SyncCipherPushNotification : PushNotification { public Guid Id { get; set; } + public Guid? UserId { get; set; } + public Guid? OrganizationId { get; set; } public DateTime RevisionDate { get; set; } } - private class SyncCiphersPushNotification : SyncPushNotification + private class SyncFolderPushNotification : PushNotification { + public Guid Id { get; set; } + public Guid UserId { get; set; } + public DateTime RevisionDate { get; set; } + } + + private class SyncUserPushNotification : PushNotification + { + public Guid UserId { get; set; } public DateTime Date { get; set; } } } diff --git a/src/Core/Services/Implementations/UserService.cs b/src/Core/Services/Implementations/UserService.cs index 10e2f59e4a..584af5846c 100644 --- a/src/Core/Services/Implementations/UserService.cs +++ b/src/Core/Services/Implementations/UserService.cs @@ -19,6 +19,7 @@ namespace Bit.Core.Services private readonly IUserRepository _userRepository; private readonly ICipherRepository _cipherRepository; private readonly IMailService _mailService; + private readonly IPushService _pushService; private readonly IdentityErrorDescriber _identityErrorDescriber; private readonly IdentityOptions _identityOptions; private readonly IPasswordHasher _passwordHasher; @@ -29,6 +30,7 @@ namespace Bit.Core.Services IUserRepository userRepository, ICipherRepository cipherRepository, IMailService mailService, + IPushService pushService, IUserStore store, IOptions optionsAccessor, IPasswordHasher passwordHasher, @@ -53,6 +55,7 @@ namespace Bit.Core.Services _userRepository = userRepository; _cipherRepository = cipherRepository; _mailService = mailService; + _pushService = pushService; _identityOptions = optionsAccessor?.Value ?? new IdentityOptions(); _identityErrorDescriber = errors; _passwordHasher = passwordHasher; @@ -125,6 +128,9 @@ namespace Bit.Core.Services user.RevisionDate = user.AccountRevisionDate = DateTime.UtcNow; await _userRepository.ReplaceAsync(user); + + // push + await _pushService.PushSyncSettingsAsync(user.Id); } public async Task RegisterUserAsync(User user, string masterPassword)