1
0
mirror of https://github.com/bitwarden/server.git synced 2025-04-08 06:28:14 -05:00

record installation devices

This commit is contained in:
Kyle Spearrin 2019-03-19 00:39:03 -04:00
parent 11fafa4a92
commit 01a293cf76
15 changed files with 255 additions and 36 deletions

View File

@ -76,12 +76,12 @@ namespace Bit.Api.Controllers
if(!string.IsNullOrWhiteSpace(model.UserId)) if(!string.IsNullOrWhiteSpace(model.UserId))
{ {
await _pushNotificationService.SendPayloadToUserAsync(Prefix(model.UserId), await _pushNotificationService.SendPayloadToUserAsync(Prefix(model.UserId),
model.Type.Value, model.Payload, Prefix(model.Identifier)); model.Type.Value, model.Payload, Prefix(model.Identifier), Prefix(model.DeviceId));
} }
else if(!string.IsNullOrWhiteSpace(model.OrganizationId)) else if(!string.IsNullOrWhiteSpace(model.OrganizationId))
{ {
await _pushNotificationService.SendPayloadToOrganizationAsync(Prefix(model.OrganizationId), await _pushNotificationService.SendPayloadToOrganizationAsync(Prefix(model.OrganizationId),
model.Type.Value, model.Payload, Prefix(model.Identifier)); model.Type.Value, model.Payload, Prefix(model.Identifier), Prefix(model.DeviceId));
} }
} }

View File

@ -8,6 +8,7 @@ namespace Bit.Core.Models.Api
{ {
public string UserId { get; set; } public string UserId { get; set; }
public string OrganizationId { get; set; } public string OrganizationId { get; set; }
public string DeviceId { get; set; }
public string Identifier { get; set; } public string Identifier { get; set; }
[Required] [Required]
public PushType? Type { get; set; } public PushType? Type { get; set; }

View File

@ -0,0 +1,36 @@
using System;
using Microsoft.WindowsAzure.Storage.Table;
namespace Bit.Core.Models.Data
{
public class InstallationDeviceEntity : TableEntity
{
public InstallationDeviceEntity() { }
public InstallationDeviceEntity(Guid installationId, Guid deviceId)
{
PartitionKey = installationId.ToString();
RowKey = deviceId.ToString();
}
public InstallationDeviceEntity(string prefixedDeviceId)
{
var parts = prefixedDeviceId.Split("_");
if(parts.Length < 2)
{
throw new ArgumentException("Not enough parts.");
}
if(!Guid.TryParse(parts[0], out var installationId) || !Guid.TryParse(parts[1], out var deviceId))
{
throw new ArgumentException("Could not parse parts.");
}
PartitionKey = parts[0];
RowKey = parts[1];
}
public static bool IsInstallationDeviceId(string deviceId)
{
return deviceId != null && deviceId.Length == 73 && deviceId[36] == '_';
}
}
}

View File

@ -0,0 +1,13 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Bit.Core.Models.Data;
namespace Bit.Core.Repositories
{
public interface IInstallationDeviceRepository
{
Task UpsertAsync(InstallationDeviceEntity entity);
Task UpsertManyAsync(IList<InstallationDeviceEntity> entities);
Task DeleteAsync(InstallationDeviceEntity entity);
}
}

View File

@ -0,0 +1,24 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Bit.Core.Models.Data;
namespace Bit.Core.Repositories.Noop
{
public class InstallationDeviceRepository : IInstallationDeviceRepository
{
public Task UpsertAsync(InstallationDeviceEntity entity)
{
return Task.FromResult(0);
}
public Task UpsertManyAsync(IList<InstallationDeviceEntity> entities)
{
return Task.FromResult(0);
}
public Task DeleteAsync(InstallationDeviceEntity entity)
{
return Task.FromResult(0);
}
}
}

View File

@ -0,0 +1,79 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Bit.Core.Models.Data;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
namespace Bit.Core.Repositories.TableStorage
{
public class InstallationDeviceRepository : IInstallationDeviceRepository
{
private readonly CloudTable _table;
public InstallationDeviceRepository(GlobalSettings globalSettings)
: this(globalSettings.Events.ConnectionString)
{ }
public InstallationDeviceRepository(string storageConnectionString)
{
var storageAccount = CloudStorageAccount.Parse(storageConnectionString);
var tableClient = storageAccount.CreateCloudTableClient();
_table = tableClient.GetTableReference("installationdevice");
}
public async Task UpsertAsync(InstallationDeviceEntity entity)
{
await _table.ExecuteAsync(TableOperation.InsertOrReplace(entity));
}
public async Task UpsertManyAsync(IList<InstallationDeviceEntity> entities)
{
if(!entities?.Any() ?? true)
{
return;
}
if(entities.Count == 1)
{
await UpsertAsync(entities.First());
return;
}
var entityGroups = entities.GroupBy(ent => ent.PartitionKey);
foreach(var group in entityGroups)
{
var groupEntities = group.ToList();
if(groupEntities.Count == 1)
{
await UpsertAsync(groupEntities.First());
continue;
}
// A batch insert can only contain 100 entities at a time
var iterations = groupEntities.Count / 100;
for(var i = 0; i <= iterations; i++)
{
var batch = new TableBatchOperation();
var batchEntities = groupEntities.Skip(i * 100).Take(100);
if(!batchEntities.Any())
{
break;
}
foreach(var entity in batchEntities)
{
batch.InsertOrReplace(entity);
}
await _table.ExecuteBatchAsync(batch);
}
}
}
public async Task DeleteAsync(InstallationDeviceEntity entity)
{
await _table.ExecuteAsync(TableOperation.Delete(entity));
}
}
}

View File

@ -19,7 +19,8 @@ namespace Bit.Core.Services
Task PushSyncOrgKeysAsync(Guid userId); Task PushSyncOrgKeysAsync(Guid userId);
Task PushSyncSettingsAsync(Guid userId); Task PushSyncSettingsAsync(Guid userId);
Task PushLogOutAsync(Guid userId); Task PushLogOutAsync(Guid userId);
Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier); Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier, string deviceId = null);
Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier); Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier,
string deviceId = null);
} }
} }

View File

@ -141,7 +141,7 @@ namespace Bit.Core.Services
private async Task SendMessageAsync<T>(PushType type, T payload, bool excludeCurrentContext) private async Task SendMessageAsync<T>(PushType type, T payload, bool excludeCurrentContext)
{ {
var contextId = GetContextIdentifier(excludeCurrentContext); var contextId = GetContextIdentifier(excludeCurrentContext);
var message = JsonConvert.SerializeObject(new PushNotificationData<T>(type, payload, contextId), var message = JsonConvert.SerializeObject(new PushNotificationData<T>(type, payload, contextId),
_jsonSettings); _jsonSettings);
var queueMessage = new CloudQueueMessage(message); var queueMessage = new CloudQueueMessage(message);
await _queue.AddMessageAsync(queueMessage); await _queue.AddMessageAsync(queueMessage);
@ -159,13 +159,15 @@ namespace Bit.Core.Services
return currentContext?.DeviceIdentifier; return currentContext?.DeviceIdentifier;
} }
public Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier) public Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier,
string deviceId = null)
{ {
// Noop // Noop
return Task.FromResult(0); return Task.FromResult(0);
} }
public Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier) public Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier,
string deviceId = null)
{ {
// Noop // Noop
return Task.FromResult(0); return Task.FromResult(0);

View File

@ -6,14 +6,19 @@ using System.Collections.Generic;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Bit.Core.Repositories;
namespace Bit.Core.Services namespace Bit.Core.Services
{ {
public class MultiServicePushNotificationService : IPushNotificationService public class MultiServicePushNotificationService : IPushNotificationService
{ {
private readonly List<IPushNotificationService> _services = new List<IPushNotificationService>(); private readonly List<IPushNotificationService> _services = new List<IPushNotificationService>();
private readonly IDeviceRepository _deviceRepository;
private readonly IInstallationDeviceRepository _installationDeviceRepository;
public MultiServicePushNotificationService( public MultiServicePushNotificationService(
IDeviceRepository deviceRepository,
IInstallationDeviceRepository installationDeviceRepository,
GlobalSettings globalSettings, GlobalSettings globalSettings,
IHttpContextAccessor httpContextAccessor, IHttpContextAccessor httpContextAccessor,
ILogger<RelayPushNotificationService> relayLogger, ILogger<RelayPushNotificationService> relayLogger,
@ -25,7 +30,8 @@ namespace Bit.Core.Services
globalSettings.Installation?.Id != null && globalSettings.Installation?.Id != null &&
CoreHelpers.SettingHasValue(globalSettings.Installation?.Key)) CoreHelpers.SettingHasValue(globalSettings.Installation?.Key))
{ {
_services.Add(new RelayPushNotificationService(globalSettings, httpContextAccessor, relayLogger)); _services.Add(new RelayPushNotificationService(_deviceRepository, globalSettings,
httpContextAccessor, relayLogger));
} }
if(CoreHelpers.SettingHasValue(globalSettings.InternalIdentityKey) && if(CoreHelpers.SettingHasValue(globalSettings.InternalIdentityKey) &&
CoreHelpers.SettingHasValue(globalSettings.BaseServiceUri.InternalNotifications)) CoreHelpers.SettingHasValue(globalSettings.BaseServiceUri.InternalNotifications))
@ -38,13 +44,17 @@ namespace Bit.Core.Services
{ {
if(CoreHelpers.SettingHasValue(globalSettings.NotificationHub.ConnectionString)) if(CoreHelpers.SettingHasValue(globalSettings.NotificationHub.ConnectionString))
{ {
_services.Add(new NotificationHubPushNotificationService(globalSettings, httpContextAccessor)); _services.Add(new NotificationHubPushNotificationService(_installationDeviceRepository,
globalSettings, httpContextAccessor));
} }
if(CoreHelpers.SettingHasValue(globalSettings.Notifications?.ConnectionString)) if(CoreHelpers.SettingHasValue(globalSettings.Notifications?.ConnectionString))
{ {
_services.Add(new AzureQueuePushNotificationService(globalSettings, httpContextAccessor)); _services.Add(new AzureQueuePushNotificationService(globalSettings, httpContextAccessor));
} }
} }
_deviceRepository = deviceRepository;
_installationDeviceRepository = installationDeviceRepository;
} }
public Task PushSyncCipherCreateAsync(Cipher cipher, IEnumerable<Guid> collectionIds) public Task PushSyncCipherCreateAsync(Cipher cipher, IEnumerable<Guid> collectionIds)
@ -113,15 +123,17 @@ namespace Bit.Core.Services
return Task.FromResult(0); return Task.FromResult(0);
} }
public Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier) public Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier,
string deviceId = null)
{ {
PushToServices((s) => s.SendPayloadToUserAsync(userId, type, payload, identifier)); PushToServices((s) => s.SendPayloadToUserAsync(userId, type, payload, identifier, deviceId));
return Task.FromResult(0); return Task.FromResult(0);
} }
public Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier) public Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier,
string deviceId = null)
{ {
PushToServices((s) => s.SendPayloadToOrganizationAsync(orgId, type, payload, identifier)); PushToServices((s) => s.SendPayloadToOrganizationAsync(orgId, type, payload, identifier, deviceId));
return Task.FromResult(0); return Task.FromResult(0);
} }

View File

@ -7,20 +7,25 @@ using Newtonsoft.Json;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Bit.Core.Models; using Bit.Core.Models;
using Bit.Core.Models.Data;
using Bit.Core.Repositories;
namespace Bit.Core.Services namespace Bit.Core.Services
{ {
public class NotificationHubPushNotificationService : IPushNotificationService public class NotificationHubPushNotificationService : IPushNotificationService
{ {
private readonly IInstallationDeviceRepository _installationDeviceRepository;
private readonly GlobalSettings _globalSettings; private readonly GlobalSettings _globalSettings;
private readonly IHttpContextAccessor _httpContextAccessor; private readonly IHttpContextAccessor _httpContextAccessor;
private NotificationHubClient _client = null; private NotificationHubClient _client = null;
public NotificationHubPushNotificationService( public NotificationHubPushNotificationService(
IInstallationDeviceRepository installationDeviceRepository,
GlobalSettings globalSettings, GlobalSettings globalSettings,
IHttpContextAccessor httpContextAccessor) IHttpContextAccessor httpContextAccessor)
{ {
_installationDeviceRepository = installationDeviceRepository;
_globalSettings = globalSettings; _globalSettings = globalSettings;
_httpContextAccessor = httpContextAccessor; _httpContextAccessor = httpContextAccessor;
_client = NotificationHubClient.CreateClientFromConnectionString( _client = NotificationHubClient.CreateClientFromConnectionString(
@ -141,16 +146,26 @@ namespace Bit.Core.Services
await SendPayloadToUserAsync(orgId.ToString(), type, payload, GetContextIdentifier(excludeCurrentContext)); await SendPayloadToUserAsync(orgId.ToString(), type, payload, GetContextIdentifier(excludeCurrentContext));
} }
public async Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier) public async Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier,
string deviceId = null)
{ {
var tag = BuildTag($"template:payload_userId:{userId}", identifier); var tag = BuildTag($"template:payload_userId:{userId}", identifier);
await SendPayloadAsync(tag, type, payload); await SendPayloadAsync(tag, type, payload);
if(InstallationDeviceEntity.IsInstallationDeviceId(deviceId))
{
await _installationDeviceRepository.UpsertAsync(new InstallationDeviceEntity(deviceId));
}
} }
public async Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier) public async Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier,
string deviceId = null)
{ {
var tag = BuildTag($"template:payload && organizationId:{orgId}", identifier); var tag = BuildTag($"template:payload && organizationId:{orgId}", identifier);
await SendPayloadAsync(tag, type, payload); await SendPayloadAsync(tag, type, payload);
if(InstallationDeviceEntity.IsInstallationDeviceId(deviceId))
{
await _installationDeviceRepository.UpsertAsync(new InstallationDeviceEntity(deviceId));
}
} }
private string GetContextIdentifier(bool excludeCurrentContext) private string GetContextIdentifier(bool excludeCurrentContext)

View File

@ -4,18 +4,23 @@ using Microsoft.Azure.NotificationHubs;
using Bit.Core.Enums; using Bit.Core.Enums;
using System.Linq; using System.Linq;
using System; using System;
using Bit.Core.Models.Data;
using Bit.Core.Repositories;
namespace Bit.Core.Services namespace Bit.Core.Services
{ {
public class NotificationHubPushRegistrationService : IPushRegistrationService public class NotificationHubPushRegistrationService : IPushRegistrationService
{ {
private readonly IInstallationDeviceRepository _installationDeviceRepository;
private readonly GlobalSettings _globalSettings; private readonly GlobalSettings _globalSettings;
private NotificationHubClient _client = null; private NotificationHubClient _client = null;
public NotificationHubPushRegistrationService( public NotificationHubPushRegistrationService(
IInstallationDeviceRepository installationDeviceRepository,
GlobalSettings globalSettings) GlobalSettings globalSettings)
{ {
_installationDeviceRepository = installationDeviceRepository;
_globalSettings = globalSettings; _globalSettings = globalSettings;
_client = NotificationHubClient.CreateClientFromConnectionString( _client = NotificationHubClient.CreateClientFromConnectionString(
_globalSettings.NotificationHub.ConnectionString, _globalSettings.NotificationHub.ConnectionString,
@ -83,6 +88,10 @@ namespace Bit.Core.Services
userId, identifier); userId, identifier);
await _client.CreateOrUpdateInstallationAsync(installation); await _client.CreateOrUpdateInstallationAsync(installation);
if(InstallationDeviceEntity.IsInstallationDeviceId(deviceId))
{
await _installationDeviceRepository.UpsertAsync(new InstallationDeviceEntity(deviceId));
}
} }
private void BuildInstallationTemplate(Installation installation, string templateId, string templateBody, private void BuildInstallationTemplate(Installation installation, string templateId, string templateBody,
@ -118,6 +127,10 @@ namespace Bit.Core.Services
try try
{ {
await _client.DeleteInstallationAsync(deviceId); await _client.DeleteInstallationAsync(deviceId);
if(InstallationDeviceEntity.IsInstallationDeviceId(deviceId))
{
await _installationDeviceRepository.DeleteAsync(new InstallationDeviceEntity(deviceId));
}
} }
catch(Exception e) catch(Exception e)
{ {
@ -131,12 +144,22 @@ namespace Bit.Core.Services
public async Task AddUserRegistrationOrganizationAsync(IEnumerable<string> deviceIds, string organizationId) public async Task AddUserRegistrationOrganizationAsync(IEnumerable<string> deviceIds, string organizationId)
{ {
await PatchTagsForUserDevicesAsync(deviceIds, UpdateOperationType.Add, $"organizationId:{organizationId}"); await PatchTagsForUserDevicesAsync(deviceIds, UpdateOperationType.Add, $"organizationId:{organizationId}");
if(deviceIds.Any() && InstallationDeviceEntity.IsInstallationDeviceId(deviceIds.First()))
{
var entities = deviceIds.Select(e => new InstallationDeviceEntity(e));
await _installationDeviceRepository.UpsertManyAsync(entities.ToList());
}
} }
public async Task DeleteUserRegistrationOrganizationAsync(IEnumerable<string> deviceIds, string organizationId) public async Task DeleteUserRegistrationOrganizationAsync(IEnumerable<string> deviceIds, string organizationId)
{ {
await PatchTagsForUserDevicesAsync(deviceIds, UpdateOperationType.Remove, await PatchTagsForUserDevicesAsync(deviceIds, UpdateOperationType.Remove,
$"organizationId:{organizationId}"); $"organizationId:{organizationId}");
if(deviceIds.Any() && InstallationDeviceEntity.IsInstallationDeviceId(deviceIds.First()))
{
var entities = deviceIds.Select(e => new InstallationDeviceEntity(e));
await _installationDeviceRepository.UpsertManyAsync(entities.ToList());
}
} }
private async Task PatchTagsForUserDevicesAsync(IEnumerable<string> deviceIds, UpdateOperationType op, private async Task PatchTagsForUserDevicesAsync(IEnumerable<string> deviceIds, UpdateOperationType op,

View File

@ -161,13 +161,15 @@ namespace Bit.Core.Services
return currentContext?.DeviceIdentifier; return currentContext?.DeviceIdentifier;
} }
public Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier) public Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier,
string deviceId = null)
{ {
// Noop // Noop
return Task.FromResult(0); return Task.FromResult(0);
} }
public Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier) public Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier,
string deviceId = null)
{ {
// Noop // Noop
return Task.FromResult(0); return Task.FromResult(0);

View File

@ -8,15 +8,18 @@ using System.Net.Http;
using Bit.Core.Models.Api; using Bit.Core.Models.Api;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Collections.Generic; using System.Collections.Generic;
using Bit.Core.Repositories;
namespace Bit.Core.Services namespace Bit.Core.Services
{ {
public class RelayPushNotificationService : BaseIdentityClientService, IPushNotificationService public class RelayPushNotificationService : BaseIdentityClientService, IPushNotificationService
{ {
private readonly IDeviceRepository _deviceRepository;
private readonly IHttpContextAccessor _httpContextAccessor; private readonly IHttpContextAccessor _httpContextAccessor;
private readonly ILogger<RelayPushNotificationService> _logger; private readonly ILogger<RelayPushNotificationService> _logger;
public RelayPushNotificationService( public RelayPushNotificationService(
IDeviceRepository deviceRepository,
GlobalSettings globalSettings, GlobalSettings globalSettings,
IHttpContextAccessor httpContextAccessor, IHttpContextAccessor httpContextAccessor,
ILogger<RelayPushNotificationService> logger) ILogger<RelayPushNotificationService> logger)
@ -28,6 +31,7 @@ namespace Bit.Core.Services
globalSettings.Installation.Key, globalSettings.Installation.Key,
logger) logger)
{ {
_deviceRepository = deviceRepository;
_httpContextAccessor = httpContextAccessor; _httpContextAccessor = httpContextAccessor;
_logger = logger; _logger = logger;
} }
@ -143,12 +147,8 @@ namespace Bit.Core.Services
Type = type, Type = type,
Payload = payload Payload = payload
}; };
if(excludeCurrentContext) await AddCurrentContextAsync(request, excludeCurrentContext);
{
ExcludeCurrentContext(request);
}
await SendAsync(HttpMethod.Post, "push/send", request); await SendAsync(HttpMethod.Post, "push/send", request);
} }
@ -161,30 +161,36 @@ namespace Bit.Core.Services
Payload = payload Payload = payload
}; };
if(excludeCurrentContext) await AddCurrentContextAsync(request, excludeCurrentContext);
{
ExcludeCurrentContext(request);
}
await SendAsync(HttpMethod.Post, "push/send", request); await SendAsync(HttpMethod.Post, "push/send", request);
} }
private void ExcludeCurrentContext(PushSendRequestModel request) private async Task AddCurrentContextAsync(PushSendRequestModel request, bool addIdentifier)
{ {
var currentContext = _httpContextAccessor?.HttpContext?. var currentContext = _httpContextAccessor?.HttpContext?.
RequestServices.GetService(typeof(CurrentContext)) as CurrentContext; RequestServices.GetService(typeof(CurrentContext)) as CurrentContext;
if(!string.IsNullOrWhiteSpace(currentContext?.DeviceIdentifier)) if(!string.IsNullOrWhiteSpace(currentContext?.DeviceIdentifier))
{ {
request.Identifier = currentContext.DeviceIdentifier; var device = await _deviceRepository.GetByIdentifierAsync(currentContext.DeviceIdentifier);
if(device != null)
{
request.DeviceId = device.Id.ToString();
}
if(addIdentifier)
{
request.Identifier = currentContext.DeviceIdentifier;
}
} }
} }
public Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier) public Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier,
string deviceId = null)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier) public Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier,
string deviceId = null)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

View File

@ -63,12 +63,14 @@ namespace Bit.Core.Services
return Task.FromResult(0); return Task.FromResult(0);
} }
public Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier) public Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier,
string deviceId = null)
{ {
return Task.FromResult(0); return Task.FromResult(0);
} }
public Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier) public Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier,
string deviceId = null)
{ {
return Task.FromResult(0); return Task.FromResult(0);
} }

View File

@ -20,6 +20,7 @@ using System;
using System.IO; using System.IO;
using SqlServerRepos = Bit.Core.Repositories.SqlServer; using SqlServerRepos = Bit.Core.Repositories.SqlServer;
using PostgreSqlRepos = Bit.Core.Repositories.PostgreSql; using PostgreSqlRepos = Bit.Core.Repositories.PostgreSql;
using NoopRepos = Bit.Core.Repositories.Noop;
using System.Threading.Tasks; using System.Threading.Tasks;
using TableStorageRepos = Bit.Core.Repositories.TableStorage; using TableStorageRepos = Bit.Core.Repositories.TableStorage;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
@ -58,10 +59,12 @@ namespace Bit.Core.Utilities
if(globalSettings.SelfHosted) if(globalSettings.SelfHosted)
{ {
services.AddSingleton<IEventRepository, SqlServerRepos.EventRepository>(); services.AddSingleton<IEventRepository, SqlServerRepos.EventRepository>();
services.AddSingleton<IInstallationDeviceRepository, NoopRepos.InstallationDeviceRepository>();
} }
else else
{ {
services.AddSingleton<IEventRepository, TableStorageRepos.EventRepository>(); services.AddSingleton<IEventRepository, TableStorageRepos.EventRepository>();
services.AddSingleton<IInstallationDeviceRepository, TableStorageRepos.InstallationDeviceRepository>();
} }
} }