Files
server/src/Core/Services/Implementations/NotificationHubPushRegistrationService.cs

195 lines
7.1 KiB
C#
Raw Normal View History

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Azure.NotificationHubs;
2017-08-11 08:57:31 -04:00
using Bit.Core.Enums;
using System.Linq;
using System;
namespace Bit.Core.Services
{
public class NotificationHubPushRegistrationService : IPushRegistrationService
{
private readonly GlobalSettings _globalSettings;
private NotificationHubClient _client = null;
private DateTime? _clientExpires = null;
2017-05-26 22:52:50 -04:00
public NotificationHubPushRegistrationService(
2017-08-11 08:57:31 -04:00
GlobalSettings globalSettings)
{
_globalSettings = globalSettings;
}
public async Task CreateOrUpdateRegistrationAsync(string pushToken, string deviceId, string userId,
2017-08-11 08:57:31 -04:00
string identifier, DeviceType type)
{
2017-08-11 08:57:31 -04:00
if(string.IsNullOrWhiteSpace(pushToken))
{
return;
}
2017-08-11 08:57:31 -04:00
var installation = new Installation
{
2017-08-11 08:57:31 -04:00
InstallationId = deviceId,
PushChannel = pushToken,
2017-05-26 22:52:50 -04:00
Templates = new Dictionary<string, InstallationTemplate>()
};
installation.Tags = new List<string>
{
2017-08-11 08:57:31 -04:00
$"userId:{userId}"
};
2017-08-11 08:57:31 -04:00
if(!string.IsNullOrWhiteSpace(identifier))
{
2017-08-11 08:57:31 -04:00
installation.Tags.Add("deviceIdentifier:" + identifier);
}
2017-05-26 22:52:50 -04:00
string payloadTemplate = null, messageTemplate = null, badgeMessageTemplate = null;
2017-08-11 08:57:31 -04:00
switch(type)
{
2017-08-11 08:57:31 -04:00
case DeviceType.Android:
2017-06-02 16:52:54 -04:00
payloadTemplate = "{\"data\":{\"data\":{\"type\":\"#(type)\",\"payload\":\"$(payload)\"}}}";
messageTemplate = "{\"data\":{\"data\":{\"type\":\"#(type)\"}," +
"\"notification\":{\"title\":\"$(title)\",\"body\":\"$(message)\"}}}";
2017-05-26 22:52:50 -04:00
installation.Platform = NotificationPlatform.Gcm;
break;
2017-08-11 08:57:31 -04:00
case DeviceType.iOS:
2017-05-26 22:52:50 -04:00
payloadTemplate = "{\"data\":{\"type\":\"#(type)\",\"payload\":\"$(payload)\"}," +
"\"aps\":{\"alert\":null,\"badge\":null,\"content-available\":1}}";
messageTemplate = "{\"data\":{\"type\":\"#(type)\"}," +
"\"aps\":{\"alert\":\"$(message)\",\"badge\":null,\"content-available\":1}}";
badgeMessageTemplate = "{\"data\":{\"type\":\"#(type)\"}," +
"\"aps\":{\"alert\":\"$(message)\",\"badge\":\"#(badge)\",\"content-available\":1}}";
installation.Platform = NotificationPlatform.Apns;
break;
2017-08-11 08:57:31 -04:00
case DeviceType.AndroidAmazon:
2017-05-26 22:52:50 -04:00
payloadTemplate = "{\"data\":{\"type\":\"#(type)\",\"payload\":\"$(payload)\"}}";
messageTemplate = "{\"data\":{\"type\":\"#(type)\",\"message\":\"$(message)\"}}";
installation.Platform = NotificationPlatform.Adm;
break;
default:
break;
}
2017-08-11 08:57:31 -04:00
BuildInstallationTemplate(installation, "payload", payloadTemplate, userId, identifier);
BuildInstallationTemplate(installation, "message", messageTemplate, userId, identifier);
BuildInstallationTemplate(installation, "badgeMessage", badgeMessageTemplate ?? messageTemplate,
userId, identifier);
2017-05-26 22:52:50 -04:00
await RenewClientAndExecuteAsync(async client =>
await client.CreateOrUpdateInstallationAsync(installation));
}
2017-08-11 08:57:31 -04:00
private void BuildInstallationTemplate(Installation installation, string templateId, string templateBody,
string userId, string identifier)
2017-05-26 22:52:50 -04:00
{
if(templateBody == null)
{
return;
}
var fullTemplateId = $"template:{templateId}";
var template = new InstallationTemplate
{
Body = templateBody,
Tags = new List<string>
{
fullTemplateId,
$"{fullTemplateId}_userId:{userId}"
}
};
2017-08-11 08:57:31 -04:00
if(!string.IsNullOrWhiteSpace(identifier))
2017-05-26 22:52:50 -04:00
{
2017-08-11 08:57:31 -04:00
template.Tags.Add($"{fullTemplateId}_deviceIdentifier:{identifier}");
2017-05-26 22:52:50 -04:00
}
installation.Templates.Add(fullTemplateId, template);
}
2017-08-11 08:57:31 -04:00
public async Task DeleteRegistrationAsync(string deviceId)
{
try
{
await RenewClientAndExecuteAsync(async client => await client.DeleteInstallationAsync(deviceId));
}
catch(Exception e)
{
2017-11-14 09:35:48 -05:00
if(e.InnerException == null || !e.InnerException.Message.Contains("(404) Not Found"))
{
throw e;
}
}
}
2017-05-26 22:52:50 -04:00
2017-08-11 08:57:31 -04:00
public async Task AddUserRegistrationOrganizationAsync(IEnumerable<string> deviceIds, string organizationId)
2017-05-26 22:52:50 -04:00
{
2017-08-11 08:57:31 -04:00
await PatchTagsForUserDevicesAsync(deviceIds, UpdateOperationType.Add, $"organizationId:{organizationId}");
2017-05-26 22:52:50 -04:00
}
2017-08-11 08:57:31 -04:00
public async Task DeleteUserRegistrationOrganizationAsync(IEnumerable<string> deviceIds, string organizationId)
2017-05-26 22:52:50 -04:00
{
2017-08-11 08:57:31 -04:00
await PatchTagsForUserDevicesAsync(deviceIds, UpdateOperationType.Remove,
$"organizationId:{organizationId}");
2017-05-26 22:52:50 -04:00
}
private async Task PatchTagsForUserDevicesAsync(IEnumerable<string> deviceIds, UpdateOperationType op,
string tag)
2017-05-26 22:52:50 -04:00
{
2017-08-11 08:57:31 -04:00
if(!deviceIds.Any())
{
return;
}
2017-05-26 22:52:50 -04:00
var operation = new PartialUpdateOperation
{
Operation = op,
2017-11-14 09:35:48 -05:00
Path = "/tags"
2017-05-26 22:52:50 -04:00
};
2017-11-14 09:35:48 -05:00
if(op == UpdateOperationType.Add)
{
operation.Value = tag;
}
else if(op == UpdateOperationType.Remove)
{
operation.Path += $"/{tag}";
}
2017-08-11 08:57:31 -04:00
foreach(var id in deviceIds)
2017-05-26 22:52:50 -04:00
{
try
{
await RenewClientAndExecuteAsync(async client =>
await client.PatchInstallationAsync(id, new List<PartialUpdateOperation> { operation }));
}
catch(Exception e)
{
2017-11-14 09:35:48 -05:00
if(e.InnerException == null || !e.InnerException.Message.Contains("(404) Not Found"))
{
throw e;
}
}
2017-05-26 22:52:50 -04:00
}
}
private async Task RenewClientAndExecuteAsync(Func<NotificationHubClient, Task> task)
{
var now = DateTime.UtcNow;
if(_client == null || !_clientExpires.HasValue || _clientExpires.Value < now)
{
_clientExpires = now.Add(TimeSpan.FromMinutes(30));
_client = NotificationHubClient.CreateClientFromConnectionString(
_globalSettings.NotificationHub.ConnectionString,
_globalSettings.NotificationHub.HubName);
}
await task(_client);
}
}
}