1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-02 16:42:50 -05:00

hub api notifications

This commit is contained in:
Kyle Spearrin
2018-08-16 12:05:01 -04:00
parent ff01ce5ca7
commit 28e6783a00
22 changed files with 320 additions and 179 deletions

View File

@ -52,6 +52,30 @@ namespace Bit.Core.Services
protected HttpClient IdentityClient { get; private set; }
protected string AccessToken { get; private set; }
protected async Task SendAsync(HttpMethod method, string path, object requestModel = null)
{
var tokenStateResponse = await HandleTokenStateAsync();
if(!tokenStateResponse)
{
return;
}
var message = new TokenHttpRequestMessage(requestModel, AccessToken)
{
Method = method,
RequestUri = new Uri(string.Concat(Client.BaseAddress, path))
};
try
{
await Client.SendAsync(message);
}
catch(Exception e)
{
_logger.LogError(12334, e, "Failed to send to {0}.", message.RequestUri.ToString());
}
}
protected async Task<bool> HandleTokenStateAsync()
{
if(_nextAuthAttempt.HasValue && DateTime.UtcNow > _nextAuthAttempt.Value)
@ -119,8 +143,11 @@ namespace Bit.Core.Services
public TokenHttpRequestMessage(object requestObject, string token)
: this(token)
{
var stringContent = JsonConvert.SerializeObject(requestObject);
Content = new StringContent(stringContent, Encoding.UTF8, "application/json");
if(requestObject != null)
{
var stringContent = JsonConvert.SerializeObject(requestObject);
Content = new StringContent(stringContent, Encoding.UTF8, "application/json");
}
}
}

View File

@ -0,0 +1,169 @@
using System;
using System.Threading.Tasks;
using Bit.Core.Models.Table;
using Bit.Core.Enums;
using Newtonsoft.Json;
using Bit.Core.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System.Net.Http;
namespace Bit.Core.Services
{
public class HubApiPushNotificationService : BaseIdentityClientService, IPushNotificationService
{
private readonly GlobalSettings _globalSettings;
private readonly IHttpContextAccessor _httpContextAccessor;
private JsonSerializerSettings _jsonSettings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
};
public HubApiPushNotificationService(
GlobalSettings globalSettings,
IHttpContextAccessor httpContextAccessor,
ILogger<HubApiPushNotificationService> logger)
: base(
globalSettings.BaseServiceUri.InternalHub,
globalSettings.BaseServiceUri.InternalIdentity,
"internal",
$"internal.{globalSettings.ProjectName}",
globalSettings.InternalIdentityKey,
logger)
{
_globalSettings = globalSettings;
_httpContextAccessor = httpContextAccessor;
}
public async Task PushSyncCipherCreateAsync(Cipher cipher)
{
await PushCipherAsync(cipher, PushType.SyncCipherCreate);
}
public async Task PushSyncCipherUpdateAsync(Cipher cipher)
{
await PushCipherAsync(cipher, PushType.SyncCipherUpdate);
}
public async Task PushSyncCipherDeleteAsync(Cipher cipher)
{
await PushCipherAsync(cipher, PushType.SyncLoginDelete);
}
private async Task PushCipherAsync(Cipher cipher, PushType type)
{
if(cipher.OrganizationId.HasValue)
{
var message = new SyncCipherPushNotification
{
Id = cipher.Id,
OrganizationId = cipher.OrganizationId,
RevisionDate = cipher.RevisionDate,
};
await SendMessageAsync(type, message, true);
}
else if(cipher.UserId.HasValue)
{
var message = new SyncCipherPushNotification
{
Id = cipher.Id,
UserId = cipher.UserId,
RevisionDate = cipher.RevisionDate,
};
await SendMessageAsync(type, message, true);
}
}
public async Task PushSyncFolderCreateAsync(Folder folder)
{
await PushFolderAsync(folder, PushType.SyncFolderCreate);
}
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 PushFolderAsync(Folder folder, PushType type)
{
var message = new SyncFolderPushNotification
{
Id = folder.Id,
UserId = folder.UserId,
RevisionDate = folder.RevisionDate
};
await SendMessageAsync(type, message, true);
}
public async Task PushSyncCiphersAsync(Guid userId)
{
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
{
UserId = userId,
Date = DateTime.UtcNow
};
await SendMessageAsync(type, message, false);
}
private async Task SendMessageAsync<T>(PushType type, T payload, bool excludeCurrentContext)
{
var contextId = GetContextIdentifier(excludeCurrentContext);
var request = new PushNotificationData<T>(type, payload, contextId);
await SendAsync(HttpMethod.Post, "/notification", request);
}
private string GetContextIdentifier(bool excludeCurrentContext)
{
if(!excludeCurrentContext)
{
return null;
}
var currentContext = _httpContextAccessor?.HttpContext?.
RequestServices.GetService(typeof(CurrentContext)) as CurrentContext;
return currentContext?.DeviceIdentifier;
}
public Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier)
{
// Noop
return Task.FromResult(0);
}
public Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier)
{
// Noop
return Task.FromResult(0);
}
}
}

View File

@ -143,7 +143,7 @@ namespace Bit.Core.Services
ExcludeCurrentContext(request);
}
await SendAsync(request);
await SendAsync(HttpMethod.Post, "/push/send", request);
}
private async Task SendPayloadToOrganizationAsync(Guid orgId, PushType type, object payload, bool excludeCurrentContext)
@ -160,31 +160,7 @@ namespace Bit.Core.Services
ExcludeCurrentContext(request);
}
await SendAsync(request);
}
private async Task SendAsync(PushSendRequestModel requestModel)
{
var tokenStateResponse = await HandleTokenStateAsync();
if(!tokenStateResponse)
{
return;
}
var message = new TokenHttpRequestMessage(requestModel, AccessToken)
{
Method = HttpMethod.Post,
RequestUri = new Uri(string.Concat(Client.BaseAddress, "/push/send"))
};
try
{
await Client.SendAsync(message);
}
catch(Exception e)
{
_logger.LogError(12334, e, "Unable to send push notification.");
}
await SendAsync(HttpMethod.Post, "/push/send", request);
}
private void ExcludeCurrentContext(PushSendRequestModel request)

View File

@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Net.Http;
using System;
using Bit.Core.Models.Api;
using Bit.Core.Enums;
using System.Linq;
@ -30,12 +29,6 @@ namespace Bit.Core.Services
public async Task CreateOrUpdateRegistrationAsync(string pushToken, string deviceId, string userId,
string identifier, DeviceType type)
{
var tokenStateResponse = await HandleTokenStateAsync();
if(!tokenStateResponse)
{
return;
}
var requestModel = new PushRegistrationRequestModel
{
DeviceId = deviceId,
@ -44,45 +37,12 @@ namespace Bit.Core.Services
Type = type,
UserId = userId
};
var message = new TokenHttpRequestMessage(requestModel, AccessToken)
{
Method = HttpMethod.Post,
RequestUri = new Uri(string.Concat(Client.BaseAddress, "/push/register"))
};
try
{
await Client.SendAsync(message);
}
catch(Exception e)
{
_logger.LogError(12335, e, "Unable to create push registration.");
}
await SendAsync(HttpMethod.Post, "/push/register", requestModel);
}
public async Task DeleteRegistrationAsync(string deviceId)
{
var tokenStateResponse = await HandleTokenStateAsync();
if(!tokenStateResponse)
{
return;
}
var message = new TokenHttpRequestMessage(AccessToken)
{
Method = HttpMethod.Delete,
RequestUri = new Uri(string.Concat(Client.BaseAddress, "/push/", deviceId))
};
try
{
await Client.SendAsync(message);
}
catch(Exception e)
{
_logger.LogError(12336, e, "Unable to delete push registration.");
}
await SendAsync(HttpMethod.Delete, string.Concat("/push/", deviceId));
}
public async Task AddUserRegistrationOrganizationAsync(IEnumerable<string> deviceIds, string organizationId)
@ -92,27 +52,8 @@ namespace Bit.Core.Services
return;
}
var tokenStateResponse = await HandleTokenStateAsync();
if(!tokenStateResponse)
{
return;
}
var requestModel = new PushUpdateRequestModel(deviceIds, organizationId);
var message = new TokenHttpRequestMessage(requestModel, AccessToken)
{
Method = HttpMethod.Put,
RequestUri = new Uri(string.Concat(Client.BaseAddress, "/push/add-organization"))
};
try
{
await Client.SendAsync(message);
}
catch(Exception e)
{
_logger.LogError(12337, e, "Unable to add user org push registration.");
}
await SendAsync(HttpMethod.Put, "/push/add-organization", requestModel);
}
public async Task DeleteUserRegistrationOrganizationAsync(IEnumerable<string> deviceIds, string organizationId)
@ -122,27 +63,8 @@ namespace Bit.Core.Services
return;
}
var tokenStateResponse = await HandleTokenStateAsync();
if(!tokenStateResponse)
{
return;
}
var requestModel = new PushUpdateRequestModel(deviceIds, organizationId);
var message = new TokenHttpRequestMessage(requestModel, AccessToken)
{
Method = HttpMethod.Put,
RequestUri = new Uri(string.Concat(Client.BaseAddress, "/push/delete-organization"))
};
try
{
await Client.SendAsync(message);
}
catch(Exception e)
{
_logger.LogError(12338, e, "Unable to delete user org push registration.");
}
await SendAsync(HttpMethod.Put, "/push/delete-organization", requestModel);
}
}
}