Browse Source

Notifo fix.

pull/613/head
Sebastian 5 years ago
parent
commit
d1f9e5c754
  1. 154
      backend/src/Squidex.Domain.Apps.Entities/History/NotifoService.cs
  2. 2
      backend/src/Squidex.Domain.Apps.Entities/Squidex.Domain.Apps.Entities.csproj

154
backend/src/Squidex.Domain.Apps.Entities/History/NotifoService.cs

@ -9,11 +9,9 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Grpc.Core;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using NodaTime; using NodaTime;
using Notifo.SDK; using Notifo.SDK;
using Notifo.Services;
using Squidex.Domain.Apps.Core; using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Events;
using Squidex.Domain.Apps.Events.Apps; using Squidex.Domain.Apps.Events.Apps;
@ -25,7 +23,6 @@ using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Tasks; using Squidex.Infrastructure.Tasks;
using Squidex.Shared.Identity; using Squidex.Shared.Identity;
using Squidex.Shared.Users; using Squidex.Shared.Users;
using static Notifo.Services.Notifications;
namespace Squidex.Domain.Apps.Entities.History namespace Squidex.Domain.Apps.Entities.History
{ {
@ -36,7 +33,7 @@ namespace Squidex.Domain.Apps.Entities.History
private readonly IUrlGenerator urlGenerator; private readonly IUrlGenerator urlGenerator;
private readonly IUserResolver userResolver; private readonly IUserResolver userResolver;
private readonly IClock clock; private readonly IClock clock;
private NotificationsClient? client; private INotifoClient? client;
public NotifoService(IOptions<NotifoOptions> options, IUrlGenerator urlGenerator, IUserResolver userResolver, IClock clock) public NotifoService(IOptions<NotifoOptions> options, IUrlGenerator urlGenerator, IUserResolver userResolver, IClock clock)
{ {
@ -58,7 +55,7 @@ namespace Squidex.Domain.Apps.Entities.History
if (options.IsConfigured()) if (options.IsConfigured())
{ {
var builder = var builder =
NotificationsClientBuilder.Create() NotifoClientBuilder.Create()
.SetApiKey(options.ApiKey); .SetApiKey(options.ApiKey);
if (!string.IsNullOrWhiteSpace(options.ApiUrl)) if (!string.IsNullOrWhiteSpace(options.ApiUrl))
@ -86,27 +83,25 @@ namespace Squidex.Domain.Apps.Entities.History
var settings = new NotificationSettingsDto(); var settings = new NotificationSettingsDto();
settings.Channels[Providers.WebPush] = new NotificationSettingDto settings[Providers.WebPush] = new NotificationSettingDto
{ {
Send = true, Send = true,
DelayInSeconds = null DelayInSeconds = null
}; };
settings.Channels[Providers.Email] = new NotificationSettingDto settings[Providers.Email] = new NotificationSettingDto
{ {
Send = true, Send = true,
DelayInSeconds = 5 * 60 DelayInSeconds = 5 * 60
}; };
var userRequest = new UpsertUserRequest var userRequest = new UpsertUserDto
{ {
AppId = options.AppId, Id = user.Id,
FullName = user.DisplayName(), FullName = user.DisplayName(),
PreferredLanguage = "en", PreferredLanguage = "en",
PreferredTimezone = null, PreferredTimezone = null,
RequiresWhitelistedTopic = true,
Settings = settings, Settings = settings,
UserId = user.Id
}; };
if (user.Email.IsEmail()) if (user.Email.IsEmail())
@ -114,9 +109,15 @@ namespace Squidex.Domain.Apps.Entities.History
userRequest.EmailAddress = user.Email; userRequest.EmailAddress = user.Email;
} }
var response = await client.UpsertUserAsync(userRequest); var response = await client.Users.PostUsersAsync(options.AppId, new UpsertUsersDto
{
Requests = new List<UpsertUserDto>
{
userRequest
}
});
await userResolver.SetClaimAsync(user.Id, SquidexClaimTypes.NotifoKey, response.User.ApiKey); await userResolver.SetClaimAsync(user.Id, SquidexClaimTypes.NotifoKey, response.First().ApiKey);
} }
public async Task HandleEventsAsync(IEnumerable<(Envelope<AppEvent> AppEvent, HistoryEvent? HistoryEvent)> events) public async Task HandleEventsAsync(IEnumerable<(Envelope<AppEvent> AppEvent, HistoryEvent? HistoryEvent)> events)
@ -137,72 +138,67 @@ namespace Squidex.Domain.Apps.Entities.History
if (publishedEvents.Any()) if (publishedEvents.Any())
{ {
using (var stream = client.PublishMany()) var requests = new List<PublishRequestDto>();
foreach (var @event in publishedEvents)
{ {
foreach (var @event in publishedEvents) var payload = @event.AppEvent.Payload;
{
var payload = @event.AppEvent.Payload;
if (payload is CommentCreated comment && IsComment(payload)) if (payload is CommentCreated comment && IsComment(payload))
{
foreach (var userId in comment.Mentions!)
{ {
foreach (var userId in comment.Mentions!) var publishRequest = new PublishRequestDto();
{
var publishRequest = new PublishRequest
{
AppId = options.AppId
};
publishRequest.Topic = $"users/{userId}"; publishRequest.Topic = $"users/{userId}";
publishRequest.Properties["SquidexApp"] = comment.AppId.Name; publishRequest.Properties["SquidexApp"] = comment.AppId.Name;
publishRequest.Preformatted = new NotificationFormattingDto(); publishRequest.Preformatted = new NotificationFormattingDto();
publishRequest.Preformatted.Subject["en"] = comment.Text; publishRequest.Preformatted.Subject["en"] = comment.Text;
if (comment.Url?.IsAbsoluteUri == true) if (comment.Url?.IsAbsoluteUri == true)
{ {
publishRequest.Preformatted.LinkUrl["en"] = comment.Url.ToString(); publishRequest.Preformatted.LinkUrl["en"] = comment.Url.ToString();
} }
SetUser(comment, publishRequest); SetUser(comment, publishRequest);
await stream.RequestStream.WriteAsync(publishRequest); requests.Add(publishRequest);
}
} }
else if (@event.HistoryEvent != null) }
{ else if (@event.HistoryEvent != null)
var historyEvent = @event.HistoryEvent; {
var historyEvent = @event.HistoryEvent;
var publishRequest = new PublishRequest var publishRequest = new PublishRequestDto
{ {
AppId = options.AppId Properties = new EventProperties()
}; };
foreach (var (key, value) in historyEvent.Parameters) foreach (var (key, value) in historyEvent.Parameters)
{ {
publishRequest.Properties.Add(key, value); publishRequest.Properties.Add(key, value);
} }
publishRequest.Properties["SquidexApp"] = payload.AppId.Name; publishRequest.Properties["SquidexApp"] = payload.AppId.Name;
if (payload is ContentEvent c && !(payload is ContentDeleted)) if (payload is ContentEvent c && !(payload is ContentDeleted))
{ {
var url = urlGenerator.ContentUI(c.AppId, c.SchemaId, c.ContentId); var url = urlGenerator.ContentUI(c.AppId, c.SchemaId, c.ContentId);
publishRequest.Properties["SquidexUrl"] = url; publishRequest.Properties["SquidexUrl"] = url;
} }
publishRequest.TemplateCode = @event.HistoryEvent.EventType; publishRequest.TemplateCode = @event.HistoryEvent.EventType;
SetUser(payload, publishRequest); SetUser(payload, publishRequest);
SetTopic(payload, publishRequest, historyEvent); SetTopic(payload, publishRequest, historyEvent);
await stream.RequestStream.WriteAsync(publishRequest); requests.Add(publishRequest);
}
} }
await stream.RequestStream.CompleteAsync();
await stream.ResponseAsync;
} }
await client.Events.PostEventsAsync(options.AppId, new PublishManyRequestDto { Requests = requests });
} }
foreach (var @event in events) foreach (var @event in events)
@ -211,20 +207,23 @@ namespace Squidex.Domain.Apps.Entities.History
{ {
case AppContributorAssigned contributorAssigned: case AppContributorAssigned contributorAssigned:
{ {
var user = await userResolver.FindByIdAsync(contributorAssigned.ContributorId); var userId = contributorAssigned.ContributorId;
var user = await userResolver.FindByIdAsync(userId);
if (user != null) if (user != null)
{ {
await UpsertUserAsync(user); await UpsertUserAsync(user);
} }
var request = BuildAllowedTopicRequest(contributorAssigned, contributorAssigned.ContributorId);
try try
{ {
await client.AddAllowedTopicAsync(request); await client.Users.PostAllowedTopicAsync(options.AppId, userId, new AddAllowedTopicRequest
{
Prefix = GetAppPrefix(contributorAssigned)
});
} }
catch (RpcException ex) when (ex.StatusCode == StatusCode.NotFound) catch (NotifoException ex) when (ex.StatusCode == 404)
{ {
break; break;
} }
@ -234,13 +233,15 @@ namespace Squidex.Domain.Apps.Entities.History
case AppContributorRemoved contributorRemoved: case AppContributorRemoved contributorRemoved:
{ {
var request = BuildAllowedTopicRequest(contributorRemoved, contributorRemoved.ContributorId); var userId = contributorRemoved.ContributorId;
try try
{ {
await client.RemoveAllowedTopicAsync(request); var prefix = GetAppPrefix(contributorRemoved);
await client.Users.DeleteAllowedTopicAsync(options.ApiKey, userId, prefix);
} }
catch (RpcException ex) when (ex.StatusCode == StatusCode.NotFound) catch (NotifoException ex) when (ex.StatusCode == 404)
{ {
break; break;
} }
@ -251,19 +252,6 @@ namespace Squidex.Domain.Apps.Entities.History
} }
} }
private AllowedTopicRequest BuildAllowedTopicRequest(AppEvent @event, string contributorId)
{
var topicRequest = new AllowedTopicRequest
{
AppId = options.AppId
};
topicRequest.UserId = contributorId;
topicRequest.TopicPrefix = GetAppPrefix(@event);
return topicRequest;
}
private static bool IsTooOld(EnvelopeHeaders headers, Instant now) private static bool IsTooOld(EnvelopeHeaders headers, Instant now)
{ {
return now - headers.Timestamp() > MaxAge; return now - headers.Timestamp() > MaxAge;
@ -274,7 +262,7 @@ namespace Squidex.Domain.Apps.Entities.History
return appEvent is CommentCreated comment && comment.Mentions?.Length > 0; return appEvent is CommentCreated comment && comment.Mentions?.Length > 0;
} }
private static void SetUser(AppEvent appEvent, PublishRequest publishRequest) private static void SetUser(AppEvent appEvent, PublishRequestDto publishRequest)
{ {
if (appEvent.Actor.IsSubject) if (appEvent.Actor.IsSubject)
{ {
@ -282,7 +270,7 @@ namespace Squidex.Domain.Apps.Entities.History
} }
} }
private static void SetTopic(AppEvent appEvent, PublishRequest publishRequest, HistoryEvent @event) private static void SetTopic(AppEvent appEvent, PublishRequestDto publishRequest, HistoryEvent @event)
{ {
var topicPrefix = GetAppPrefix(appEvent); var topicPrefix = GetAppPrefix(appEvent);
var topicSuffix = @event.Channel.Replace('.', '/').Trim(); var topicSuffix = @event.Channel.Replace('.', '/').Trim();

2
backend/src/Squidex.Domain.Apps.Entities/Squidex.Domain.Apps.Entities.csproj

@ -31,7 +31,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Orleans.Core" Version="3.3.0" /> <PackageReference Include="Microsoft.Orleans.Core" Version="3.3.0" />
<PackageReference Include="Notifo.SDK" Version="1.0.0-alpha8" /> <PackageReference Include="Notifo.SDK" Version="1.0.0-alpha9" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" /> <PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" /> <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" /> <PackageReference Include="System.Collections.Immutable" Version="5.0.0" />

Loading…
Cancel
Save