From 61e31684bf4ccb55afae25750de9eb9887177f45 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Wed, 14 Feb 2024 19:13:23 +0100 Subject: [PATCH] Cancel events. (#218) * Cancel events. * Fix tests * Update dependencies * Fix mail catcher. --- ...fo.Domain.Integrations.Abstractions.csproj | 2 +- .../Notifo.Domain.Integrations.csproj | 14 +- .../Integrations/ConditionParser.cs | 6 +- .../src/Notifo.Domain/Notifo.Domain.csproj | 12 +- .../UserNotifications/CancelRequest.cs | 21 + .../IUserNotificationService.cs | 2 + .../UserNotificationService.cs | 12 + .../AuthenticationBuilderExtensions.cs | 40 ++ .../Notifo.Identity/Notifo.Identity.csproj | 9 +- .../Notifo.Identity/NotifoIdentityOptions.cs | 29 ++ backend/src/Notifo.Identity/OidcHandler.cs | 36 ++ .../Bson/ReadonlyDictionarySerializer.cs | 23 +- ...adonlyDictionarySerializer{TKey,TValue}.cs | 30 ++ .../Bson/ReadonlyListSerializer.cs | 23 +- .../Bson/ReadonlyListSerializer{T}.cs | 30 ++ .../Json/JsonServiceExtensions.cs | 8 +- .../MongoDb/MongoClientFactory.cs | 11 +- .../src/Notifo.Infrastructure/NodaPatterns.cs | 27 ++ .../Notifo.Infrastructure.csproj | 34 +- .../Scheduling/IScheduler.cs | 6 +- .../Implementation/DelegatingScheduler.cs | 11 +- .../TimerBased/ISchedulerStore.cs | 5 +- .../MongoDb/MongoDbSchedulerStore.cs | 53 +- .../TimerBased/SchedulerBatch.cs | 2 +- .../TimerBased/TimerScheduling.cs | 11 +- .../Controllers/Events/Dtos/CancelEventDto.cs | 48 ++ .../Events/Dtos/CancelResponseDto.cs | 16 + .../Api/Controllers/Events/Dtos/PublishDto.cs | 5 + .../Controllers/Events/EventsController.cs | 28 +- backend/src/Notifo/Notifo.csproj | 26 +- backend/src/Notifo/appsettings.json | 14 + backend/tests/Benchmarks/Benchmarks.csproj | 4 +- ...hemaTests.Should_build_schema.verified.txt | 8 + ...s.Should_build_schema_as_json.verified.txt | 5 +- .../Channels/Email/MjmlSchemaTests.cs | 1 - .../UserNotificationExtensionsTests.cs | 1 - .../Notifo.Domain.Tests.csproj | 8 +- .../Notifo.Identity.Tests.csproj | 6 +- .../Scheduling/MongoDbSchedulerStoreTests.cs | 40 +- .../NodaPatternsTest.cs | 40 ++ .../Notifo.Infrastructure.Tests.csproj | 8 +- frontend/src/app/service/service.ts | 81 +++- frontend/src/app/shared/components/Forms.tsx | 4 +- .../TestSuite/TestSuite.ApiTests/AppTests.cs | 1 - .../TestSuite.ApiTests/EventsTests.cs | 104 ++++ .../TestSuite.ApiTests/IntegrationTests.cs | 1 - .../TestSuite.ApiTests/NotificationTests.cs | 1 - .../TestSuite.ApiTests/TemplatesTests.cs | 1 - .../TestSuite.ApiTests.csproj | 14 +- .../TestSuite.ApiTests/UsersTests.cs | 1 - .../TestSuite.LoadTests.csproj | 8 +- .../TestSuite.Shared/TestSuite.Shared.csproj | 6 +- tools/TestSuite/docker-compose.yml | 6 +- tools/sdk/CodeGenerator/CodeGenerator.csproj | 6 +- tools/sdk/Directory.Build.props | 2 +- .../Notifo.SDK.Tests/Notifo.SDK.Tests.csproj | 4 +- tools/sdk/Notifo.SDK/Generated.cs | 455 ++++++++++++------ tools/sdk/Notifo.SDK/Notifo.SDK.csproj | 2 +- 58 files changed, 1114 insertions(+), 298 deletions(-) create mode 100644 backend/src/Notifo.Domain/UserNotifications/CancelRequest.cs create mode 100644 backend/src/Notifo.Identity/OidcHandler.cs create mode 100644 backend/src/Notifo.Infrastructure/Collections/Bson/ReadonlyDictionarySerializer{TKey,TValue}.cs create mode 100644 backend/src/Notifo.Infrastructure/Collections/Bson/ReadonlyListSerializer{T}.cs create mode 100644 backend/src/Notifo.Infrastructure/NodaPatterns.cs create mode 100644 backend/src/Notifo/Areas/Api/Controllers/Events/Dtos/CancelEventDto.cs create mode 100644 backend/src/Notifo/Areas/Api/Controllers/Events/Dtos/CancelResponseDto.cs create mode 100644 backend/tests/Notifo.Infrastructure.Tests/NodaPatternsTest.cs create mode 100644 tools/TestSuite/TestSuite.ApiTests/EventsTests.cs diff --git a/backend/src/Notifo.Domain.Integrations.Abstractions/Notifo.Domain.Integrations.Abstractions.csproj b/backend/src/Notifo.Domain.Integrations.Abstractions/Notifo.Domain.Integrations.Abstractions.csproj index 64021121..c132f01b 100644 --- a/backend/src/Notifo.Domain.Integrations.Abstractions/Notifo.Domain.Integrations.Abstractions.csproj +++ b/backend/src/Notifo.Domain.Integrations.Abstractions/Notifo.Domain.Integrations.Abstractions.csproj @@ -10,7 +10,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/backend/src/Notifo.Domain.Integrations/Notifo.Domain.Integrations.csproj b/backend/src/Notifo.Domain.Integrations/Notifo.Domain.Integrations.csproj index 73600dbb..127a810a 100644 --- a/backend/src/Notifo.Domain.Integrations/Notifo.Domain.Integrations.csproj +++ b/backend/src/Notifo.Domain.Integrations/Notifo.Domain.Integrations.csproj @@ -9,31 +9,31 @@ - + - - + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + - + diff --git a/backend/src/Notifo.Domain/Integrations/ConditionParser.cs b/backend/src/Notifo.Domain/Integrations/ConditionParser.cs index 03058e08..65992eb7 100644 --- a/backend/src/Notifo.Domain/Integrations/ConditionParser.cs +++ b/backend/src/Notifo.Domain/Integrations/ConditionParser.cs @@ -14,7 +14,7 @@ namespace Notifo.Domain.Integrations; internal static class ConditionParser { - private static readonly ParserOptions DefaultParserOptions = new ParserOptions { Tolerant = true }; + private static readonly JavaScriptParser Parser = new JavaScriptParser(new ParserOptions { Tolerant = true }); private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(10); private static readonly IMemoryCache Cache = new MemoryCache(Options.Create(new MemoryCacheOptions())); @@ -26,9 +26,7 @@ public static Script Parse(string script) { entry.AbsoluteExpirationRelativeToNow = CacheDuration; - var parser = new JavaScriptParser(script, DefaultParserOptions); - - return parser.ParseScript(); + return Parser.ParseScript(script); })!; } } diff --git a/backend/src/Notifo.Domain/Notifo.Domain.csproj b/backend/src/Notifo.Domain/Notifo.Domain.csproj index c4ba23e4..54ddbf20 100644 --- a/backend/src/Notifo.Domain/Notifo.Domain.csproj +++ b/backend/src/Notifo.Domain/Notifo.Domain.csproj @@ -21,18 +21,18 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - + diff --git a/backend/src/Notifo.Domain/UserNotifications/CancelRequest.cs b/backend/src/Notifo.Domain/UserNotifications/CancelRequest.cs new file mode 100644 index 00000000..fe195c5a --- /dev/null +++ b/backend/src/Notifo.Domain/UserNotifications/CancelRequest.cs @@ -0,0 +1,21 @@ +// ========================================================================== +// Notifo.io +// ========================================================================== +// Copyright (c) Sebastian Stehle +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Notifo.Domain.UserNotifications; + +public sealed class CancelRequest +{ + public string AppId { get; set; } + + public string UserId { get; set; } + + public string EventId { get; set; } + + public string? GroupKey { get; set; } + + public bool Test { get; set; } +} diff --git a/backend/src/Notifo.Domain/UserNotifications/IUserNotificationService.cs b/backend/src/Notifo.Domain/UserNotifications/IUserNotificationService.cs index 69a70d57..f18e4442 100644 --- a/backend/src/Notifo.Domain/UserNotifications/IUserNotificationService.cs +++ b/backend/src/Notifo.Domain/UserNotifications/IUserNotificationService.cs @@ -18,4 +18,6 @@ public interface IUserNotificationService Task TrackSeenAsync(params TrackingToken[] tokens); Task TrackConfirmedAsync(params TrackingToken[] token); + + Task CancelAsync(CancelRequest request); } diff --git a/backend/src/Notifo.Domain/UserNotifications/UserNotificationService.cs b/backend/src/Notifo.Domain/UserNotifications/UserNotificationService.cs index 293c5f1e..1c420adb 100644 --- a/backend/src/Notifo.Domain/UserNotifications/UserNotificationService.cs +++ b/backend/src/Notifo.Domain/UserNotifications/UserNotificationService.cs @@ -283,6 +283,13 @@ public async Task HandleAsync(ConfirmMessage message, } } + public async Task CancelAsync(CancelRequest request) + { + Guard.NotNull(request); + + return await userEventQueue.CompleteAsync(request.EventId, ScheduleKey(request), default); + } + public async Task TrackDeliveredAsync(params TrackingToken[] tokens) { Guard.NotNull(tokens); @@ -393,6 +400,11 @@ private async Task MarkFailedAsync(UserEventMessage userEvent, LogMessage messag return context; } + private static string ScheduleKey(CancelRequest request) + { + return $"{request.AppId}_{request.UserId}_{request.Test}_{request.GroupKey.OrDefault(request.EventId)}"; + } + private static string ScheduleKey(UserEventMessage userEvent) { return $"{userEvent.AppId}_{userEvent.UserId}_{userEvent.Test}_{userEvent.GroupKey.OrDefault(userEvent.EventId)}"; diff --git a/backend/src/Notifo.Identity/AuthenticationBuilderExtensions.cs b/backend/src/Notifo.Identity/AuthenticationBuilderExtensions.cs index 5ecb96ab..997a2d67 100644 --- a/backend/src/Notifo.Identity/AuthenticationBuilderExtensions.cs +++ b/backend/src/Notifo.Identity/AuthenticationBuilderExtensions.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.Extensions.DependencyInjection; using Notifo.Identity; @@ -40,4 +41,43 @@ public static AuthenticationBuilder AddGithub(this AuthenticationBuilder authBui return authBuilder; } + + public static AuthenticationBuilder AddOidc(this AuthenticationBuilder authBuilder, NotifoIdentityOptions identityOptions) + { + if (identityOptions.IsOidcConfigured()) + { + var displayName = !string.IsNullOrWhiteSpace(identityOptions.OidcName) ? identityOptions.OidcName : OpenIdConnectDefaults.DisplayName; + + authBuilder.AddOpenIdConnect("ExternalOidc", displayName, options => + { + options.Authority = identityOptions.OidcAuthority; + options.ClientId = identityOptions.OidcClient; + options.ClientSecret = identityOptions.OidcSecret; + options.RequireHttpsMetadata = identityOptions.RequiresHttps; + options.Events = new OidcHandler(identityOptions); + + if (!string.IsNullOrEmpty(identityOptions.OidcMetadataAddress)) + { + options.MetadataAddress = identityOptions.OidcMetadataAddress; + } + + if (!string.IsNullOrEmpty(identityOptions.OidcResponseType)) + { + options.ResponseType = identityOptions.OidcResponseType; + } + + options.GetClaimsFromUserInfoEndpoint = identityOptions.OidcGetClaimsFromUserInfoEndpoint; + + if (identityOptions.OidcScopes != null) + { + foreach (var scope in identityOptions.OidcScopes) + { + options.Scope.Add(scope); + } + } + }); + } + + return authBuilder; + } } diff --git a/backend/src/Notifo.Identity/Notifo.Identity.csproj b/backend/src/Notifo.Identity/Notifo.Identity.csproj index 621760ad..b649f87e 100644 --- a/backend/src/Notifo.Identity/Notifo.Identity.csproj +++ b/backend/src/Notifo.Identity/Notifo.Identity.csproj @@ -10,13 +10,14 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + + diff --git a/backend/src/Notifo.Identity/NotifoIdentityOptions.cs b/backend/src/Notifo.Identity/NotifoIdentityOptions.cs index 09243b84..3a440697 100644 --- a/backend/src/Notifo.Identity/NotifoIdentityOptions.cs +++ b/backend/src/Notifo.Identity/NotifoIdentityOptions.cs @@ -23,8 +23,37 @@ public sealed class NotifoIdentityOptions public string GoogleSecret { get; set; } + public string OidcName { get; set; } + + public string OidcClient { get; set; } + + public string OidcSecret { get; set; } + + public string OidcAuthority { get; set; } + + public string OidcMetadataAddress { get; set; } + + public string OidcRoleClaimType { get; set; } + + public string OidcResponseType { get; set; } + + public string OidcOnSignoutRedirectUrl { get; set; } + + public string[] OidcScopes { get; set; } + + public bool OidcGetClaimsFromUserInfoEndpoint { get; set; } + + public bool OidcOverridePermissionsWithCustomClaimsOnLogin { get; set; } + + public bool RequiresHttps { get; set; } + public NotifoIdentityUser[] Users { get; set; } + public bool IsOidcConfigured() + { + return !string.IsNullOrWhiteSpace(OidcAuthority) && !string.IsNullOrWhiteSpace(OidcClient); + } + public bool IsAdminClientConfigured() { return !string.IsNullOrWhiteSpace(AdminClientId) && !string.IsNullOrWhiteSpace(AdminClientSecret); diff --git a/backend/src/Notifo.Identity/OidcHandler.cs b/backend/src/Notifo.Identity/OidcHandler.cs new file mode 100644 index 00000000..29cd1913 --- /dev/null +++ b/backend/src/Notifo.Identity/OidcHandler.cs @@ -0,0 +1,36 @@ +// ========================================================================== +// Notifo.io +// ========================================================================== +// Copyright (c) Sebastian Stehle +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Security.Claims; +using Microsoft.AspNetCore.Authentication.OpenIdConnect; + +namespace Notifo.Identity; + +public sealed class OidcHandler : OpenIdConnectEvents +{ + private readonly NotifoIdentityOptions options; + + public OidcHandler(NotifoIdentityOptions options) + { + this.options = options; + } + + public override Task RedirectToIdentityProviderForSignOut(RedirectContext context) + { + if (!string.IsNullOrEmpty(options.OidcOnSignoutRedirectUrl)) + { + var logoutUri = options.OidcOnSignoutRedirectUrl; + + context.Response.Redirect(logoutUri); + context.HandleResponse(); + + return Task.CompletedTask; + } + + return base.RedirectToIdentityProviderForSignOut(context); + } +} diff --git a/backend/src/Notifo.Infrastructure/Collections/Bson/ReadonlyDictionarySerializer.cs b/backend/src/Notifo.Infrastructure/Collections/Bson/ReadonlyDictionarySerializer.cs index fcf07c72..326ccd65 100644 --- a/backend/src/Notifo.Infrastructure/Collections/Bson/ReadonlyDictionarySerializer.cs +++ b/backend/src/Notifo.Infrastructure/Collections/Bson/ReadonlyDictionarySerializer.cs @@ -6,25 +6,20 @@ // ========================================================================== using MongoDB.Bson.Serialization; -using MongoDB.Bson.Serialization.Serializers; namespace Notifo.Infrastructure.Collections.Bson; -public sealed class ReadonlyDictionarySerializer : ClassSerializerBase> where TKey : notnull +public static class ReadonlyDictionarySerializer { - private readonly Type innerType = typeof(Dictionary); + private static volatile int isRegistered; - protected override ReadonlyDictionary DeserializeValue(BsonDeserializationContext context, BsonDeserializationArgs args) + public static void Register() { - var inner = BsonSerializer.Deserialize>(context.Reader); - - return new ReadonlyDictionary(inner); - } - - protected override void SerializeValue(BsonSerializationContext context, BsonSerializationArgs args, ReadonlyDictionary value) - { - var inner = new Dictionary(value); - - BsonSerializer.Serialize(context.Writer, innerType, inner); + if (Interlocked.Increment(ref isRegistered) == 1) + { + BsonSerializer.RegisterGenericSerializerDefinition( + typeof(ReadonlyDictionary<,>), + typeof(ReadonlyDictionarySerializer<,>)); + } } } diff --git a/backend/src/Notifo.Infrastructure/Collections/Bson/ReadonlyDictionarySerializer{TKey,TValue}.cs b/backend/src/Notifo.Infrastructure/Collections/Bson/ReadonlyDictionarySerializer{TKey,TValue}.cs new file mode 100644 index 00000000..fcf07c72 --- /dev/null +++ b/backend/src/Notifo.Infrastructure/Collections/Bson/ReadonlyDictionarySerializer{TKey,TValue}.cs @@ -0,0 +1,30 @@ +// ========================================================================== +// Notifo.io +// ========================================================================== +// Copyright (c) Sebastian Stehle +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Notifo.Infrastructure.Collections.Bson; + +public sealed class ReadonlyDictionarySerializer : ClassSerializerBase> where TKey : notnull +{ + private readonly Type innerType = typeof(Dictionary); + + protected override ReadonlyDictionary DeserializeValue(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var inner = BsonSerializer.Deserialize>(context.Reader); + + return new ReadonlyDictionary(inner); + } + + protected override void SerializeValue(BsonSerializationContext context, BsonSerializationArgs args, ReadonlyDictionary value) + { + var inner = new Dictionary(value); + + BsonSerializer.Serialize(context.Writer, innerType, inner); + } +} diff --git a/backend/src/Notifo.Infrastructure/Collections/Bson/ReadonlyListSerializer.cs b/backend/src/Notifo.Infrastructure/Collections/Bson/ReadonlyListSerializer.cs index 5ed04ed4..582efd53 100644 --- a/backend/src/Notifo.Infrastructure/Collections/Bson/ReadonlyListSerializer.cs +++ b/backend/src/Notifo.Infrastructure/Collections/Bson/ReadonlyListSerializer.cs @@ -6,25 +6,20 @@ // ========================================================================== using MongoDB.Bson.Serialization; -using MongoDB.Bson.Serialization.Serializers; namespace Notifo.Infrastructure.Collections.Bson; -public sealed class ReadonlyListSerializer : ClassSerializerBase> +public static class ReadonlyListSerializer { - private readonly Type innerType = typeof(List); + private static volatile int isRegistered; - protected override ReadonlyList DeserializeValue(BsonDeserializationContext context, BsonDeserializationArgs args) + public static void Register() { - var inner = BsonSerializer.Deserialize>(context.Reader); - - return new ReadonlyList(inner); - } - - protected override void SerializeValue(BsonSerializationContext context, BsonSerializationArgs args, ReadonlyList value) - { - var inner = new List(value); - - BsonSerializer.Serialize(context.Writer, innerType, inner); + if (Interlocked.Increment(ref isRegistered) == 1) + { + BsonSerializer.RegisterGenericSerializerDefinition( + typeof(ReadonlyList<>), + typeof(ReadonlyListSerializer<>)); + } } } diff --git a/backend/src/Notifo.Infrastructure/Collections/Bson/ReadonlyListSerializer{T}.cs b/backend/src/Notifo.Infrastructure/Collections/Bson/ReadonlyListSerializer{T}.cs new file mode 100644 index 00000000..5ed04ed4 --- /dev/null +++ b/backend/src/Notifo.Infrastructure/Collections/Bson/ReadonlyListSerializer{T}.cs @@ -0,0 +1,30 @@ +// ========================================================================== +// Notifo.io +// ========================================================================== +// Copyright (c) Sebastian Stehle +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Notifo.Infrastructure.Collections.Bson; + +public sealed class ReadonlyListSerializer : ClassSerializerBase> +{ + private readonly Type innerType = typeof(List); + + protected override ReadonlyList DeserializeValue(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var inner = BsonSerializer.Deserialize>(context.Reader); + + return new ReadonlyList(inner); + } + + protected override void SerializeValue(BsonSerializationContext context, BsonSerializationArgs args, ReadonlyList value) + { + var inner = new List(value); + + BsonSerializer.Serialize(context.Writer, innerType, inner); + } +} diff --git a/backend/src/Notifo.Infrastructure/Json/JsonServiceExtensions.cs b/backend/src/Notifo.Infrastructure/Json/JsonServiceExtensions.cs index 959c0b8f..02464b97 100644 --- a/backend/src/Notifo.Infrastructure/Json/JsonServiceExtensions.cs +++ b/backend/src/Notifo.Infrastructure/Json/JsonServiceExtensions.cs @@ -9,6 +9,8 @@ using System.Text.Json.Serialization; using NodaTime; using NodaTime.Serialization.SystemTextJson; +using NodaTime.Text; +using Notifo.Infrastructure; using Notifo.Infrastructure.Collections.Json; using Notifo.Infrastructure.Json; using Squidex.Messaging; @@ -45,7 +47,11 @@ public static JsonSerializerOptions Configure(this JsonSerializerOptions options options.Converters.Add(new JsonReadonlyListConverterFactory()); options.Converters.Add(new JsonStringEnumConverter()); options.Converters.Add(new JsonTimeSpanConverter()); - options.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb); + + options.ConfigureForNodaTime(new NodaJsonSettings(DateTimeZoneProviders.Tzdb) + { + LocalTimeConverter = new NodaPatternConverter(NodaPatterns.VariablePrecisionIso) + }); configure(options); diff --git a/backend/src/Notifo.Infrastructure/MongoDb/MongoClientFactory.cs b/backend/src/Notifo.Infrastructure/MongoDb/MongoClientFactory.cs index 8c6483b6..57fb62ed 100644 --- a/backend/src/Notifo.Infrastructure/MongoDb/MongoClientFactory.cs +++ b/backend/src/Notifo.Infrastructure/MongoDb/MongoClientFactory.cs @@ -11,7 +11,6 @@ using MongoDB.Bson.Serialization.Serializers; using MongoDB.Driver; using MongoDB.Driver.Linq; -using Notifo.Infrastructure.Collections; using Notifo.Infrastructure.Collections.Bson; namespace Notifo.Infrastructure.MongoDb; @@ -55,13 +54,7 @@ public static void RegisterDefaultSerializers() InstantSerializer.Register(); LocalDateSerializer.Register(); LocalTimeSerializer.Register(); - - BsonSerializer.RegisterGenericSerializerDefinition( - typeof(ReadonlyList<>), - typeof(ReadonlyListSerializer<>)); - - BsonSerializer.RegisterGenericSerializerDefinition( - typeof(ReadonlyDictionary<,>), - typeof(ReadonlyDictionarySerializer<,>)); + ReadonlyDictionarySerializer.Register(); + ReadonlyListSerializer.Register(); } } diff --git a/backend/src/Notifo.Infrastructure/NodaPatterns.cs b/backend/src/Notifo.Infrastructure/NodaPatterns.cs new file mode 100644 index 00000000..373f7dfd --- /dev/null +++ b/backend/src/Notifo.Infrastructure/NodaPatterns.cs @@ -0,0 +1,27 @@ +// ========================================================================== +// Notifo.io +// ========================================================================== +// Copyright (c) Sebastian Stehle +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using NodaTime; +using NodaTime.Text; + +namespace Notifo.Infrastructure; + +public static class NodaPatterns +{ + public static readonly LocalTimePattern HourIsoPatternImpl = + LocalTimePattern.CreateWithInvariantCulture("HH"); + + public static readonly LocalTimePattern HourMinuteIsoPatternImpl = + LocalTimePattern.CreateWithInvariantCulture("HH':'mm"); + + public static readonly IPattern VariablePrecisionIso = new CompositePatternBuilder + { + { LocalTimePattern.ExtendedIso, time => true }, + { HourMinuteIsoPatternImpl, time => false }, + { HourIsoPatternImpl, time => false }, + }.Build(); +} diff --git a/backend/src/Notifo.Infrastructure/Notifo.Infrastructure.csproj b/backend/src/Notifo.Infrastructure/Notifo.Infrastructure.csproj index b374fb8c..fe840547 100644 --- a/backend/src/Notifo.Infrastructure/Notifo.Infrastructure.csproj +++ b/backend/src/Notifo.Infrastructure/Notifo.Infrastructure.csproj @@ -10,7 +10,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -20,29 +20,29 @@ - + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/backend/src/Notifo.Infrastructure/Scheduling/IScheduler.cs b/backend/src/Notifo.Infrastructure/Scheduling/IScheduler.cs index d093e51a..b4cbab75 100644 --- a/backend/src/Notifo.Infrastructure/Scheduling/IScheduler.cs +++ b/backend/src/Notifo.Infrastructure/Scheduling/IScheduler.cs @@ -11,7 +11,11 @@ namespace Notifo.Infrastructure.Scheduling; public interface IScheduler { - void Complete(string key); + Task CompleteAsync(string key, + CancellationToken ct = default); + + Task CompleteAsync(string key, string groupKey, + CancellationToken ct = default); Task ScheduleAsync(string key, T job, Instant dueTime, bool canInline, CancellationToken ct = default); diff --git a/backend/src/Notifo.Infrastructure/Scheduling/Implementation/DelegatingScheduler.cs b/backend/src/Notifo.Infrastructure/Scheduling/Implementation/DelegatingScheduler.cs index fdb8624b..af202c96 100644 --- a/backend/src/Notifo.Infrastructure/Scheduling/Implementation/DelegatingScheduler.cs +++ b/backend/src/Notifo.Infrastructure/Scheduling/Implementation/DelegatingScheduler.cs @@ -18,9 +18,16 @@ public DelegatingScheduler(IScheduling scheduling) this.scheduling = scheduling; } - public void Complete(string key) + public Task CompleteAsync(string key, + CancellationToken ct = default) + { + return scheduling.CompleteAsync(key, ct); + } + + public Task CompleteAsync(string key, string groupKey, + CancellationToken ct = default) { - scheduling.Complete(key); + return scheduling.CompleteAsync(key, groupKey, ct); } public Task ScheduleAsync(string key, T job, Instant dueTime, bool canInline, diff --git a/backend/src/Notifo.Infrastructure/Scheduling/Implementation/TimerBased/ISchedulerStore.cs b/backend/src/Notifo.Infrastructure/Scheduling/Implementation/TimerBased/ISchedulerStore.cs index 074bfd9e..f68be142 100644 --- a/backend/src/Notifo.Infrastructure/Scheduling/Implementation/TimerBased/ISchedulerStore.cs +++ b/backend/src/Notifo.Infrastructure/Scheduling/Implementation/TimerBased/ISchedulerStore.cs @@ -14,7 +14,10 @@ public interface ISchedulerStore Task CompleteAsync(string id, CancellationToken ct = default); - Task CompleteByKeyAsync(string key, + Task CompleteByKeyAsync(string key, + CancellationToken ct = default); + + Task CompleteByKeyAsync(string key, string groupKey, CancellationToken ct = default); Task?> DequeueAsync(Instant time, diff --git a/backend/src/Notifo.Infrastructure/Scheduling/Implementation/TimerBased/MongoDb/MongoDbSchedulerStore.cs b/backend/src/Notifo.Infrastructure/Scheduling/Implementation/TimerBased/MongoDb/MongoDbSchedulerStore.cs index 5e92d7d7..1e6cdde0 100644 --- a/backend/src/Notifo.Infrastructure/Scheduling/Implementation/TimerBased/MongoDb/MongoDbSchedulerStore.cs +++ b/backend/src/Notifo.Infrastructure/Scheduling/Implementation/TimerBased/MongoDb/MongoDbSchedulerStore.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using MongoDB.Bson.Serialization; using MongoDB.Driver; using NodaTime; using Notifo.Infrastructure.MongoDb; @@ -15,6 +16,17 @@ public sealed class MongoDbSchedulerStore : MongoDbRepository>(cm => + { + cm.AutoMap(); + + cm.MapProperty(x => x.GroupKey) + .SetElementName("Key"); + }); + } + public MongoDbSchedulerStore(IMongoDatabase database, SchedulerOptions options) : base(database) { @@ -32,7 +44,7 @@ protected override async Task SetupCollectionAsync(IMongoCollection>( IndexKeys - .Ascending(x => x.Key) + .Ascending(x => x.GroupKey) .Ascending(x => x.Progressing) .Ascending(x => x.DueTime)), null, ct); @@ -92,11 +104,11 @@ public async Task EnqueueGroupedAsync(string key, string groupKey, T job, Instan { using (Telemetry.Activities.StartActivity("MongoDbSchedulerStore/EnqueueGroupedAsync")) { - await Collection.UpdateOneAsync(x => x.Key == groupKey && !x.Progressing && x.DueTime <= dueTime, + await Collection.UpdateOneAsync(x => x.GroupKey == groupKey && !x.Progressing && x.DueTime <= dueTime, Update - .SetOnInsert(x => x.DueTime, dueTime) .SetOnInsert(x => x.Id, Guid.NewGuid().ToString()) - .SetOnInsert(x => x.Key, groupKey) + .SetOnInsert(x => x.DueTime, dueTime) + .SetOnInsert(x => x.GroupKey, groupKey) .SetOnInsert(x => x.Progressing, false) .SetOnInsert(x => x.ProgressingStarted, null) .SetOnInsert(x => x.RetryCount, retryCount) @@ -110,11 +122,11 @@ public async Task EnqueueAsync(string key, T job, Instant dueTime, int retryCoun { using (Telemetry.Activities.StartActivity("MongoDbSchedulerStore/EnqueueScheduledAsync")) { - await Collection.UpdateOneAsync(x => x.Key == key && !x.Progressing, + await Collection.UpdateOneAsync(x => x.GroupKey == key && !x.Progressing, Update - .SetOnInsert(x => x.DueTime, dueTime) .SetOnInsert(x => x.Id, Guid.NewGuid().ToString()) - .SetOnInsert(x => x.Key, key) + .SetOnInsert(x => x.DueTime, dueTime) + .SetOnInsert(x => x.GroupKey, key) .SetOnInsert(x => x.Progressing, false) .SetOnInsert(x => x.ProgressingStarted, null) .SetOnInsert(x => x.RetryCount, retryCount) @@ -132,12 +144,35 @@ public async Task CompleteAsync(string id, } } - public async Task CompleteByKeyAsync(string key, + public async Task CompleteByKeyAsync(string key, + CancellationToken ct = default) + { + using (Telemetry.Activities.StartActivity("MongoDbSchedulerStore/CompleteByKeyAsync")) + { + var result = await Collection.DeleteOneAsync(x => x.GroupKey == key, ct); + + return result.DeletedCount == 1; + } + } + + public async Task CompleteByKeyAsync(string key, string groupKey, CancellationToken ct = default) { using (Telemetry.Activities.StartActivity("MongoDbSchedulerStore/CompleteByKeyAsync")) { - await Collection.DeleteOneAsync(x => x.Key == key, ct); + var result = + await Collection.FindOneAndUpdateAsync(x => x.GroupKey == groupKey, + Update.Unset($"JobsV2.{key}"), + cancellationToken: ct); + + var hasDeleted = result?.JobsV2?.ContainsKey(key) == true; + + if (result?.JobsV2?.Count == 1 && hasDeleted) + { + await Collection.DeleteOneAsync(x => x.Id == result.Id, ct); + } + + return hasDeleted; } } } diff --git a/backend/src/Notifo.Infrastructure/Scheduling/Implementation/TimerBased/SchedulerBatch.cs b/backend/src/Notifo.Infrastructure/Scheduling/Implementation/TimerBased/SchedulerBatch.cs index 546b01aa..41ba5683 100644 --- a/backend/src/Notifo.Infrastructure/Scheduling/Implementation/TimerBased/SchedulerBatch.cs +++ b/backend/src/Notifo.Infrastructure/Scheduling/Implementation/TimerBased/SchedulerBatch.cs @@ -13,7 +13,7 @@ public sealed class SchedulerBatch { public string Id { get; set; } - public string Key { get; set; } + public string GroupKey { get; set; } public bool Progressing { get; set; } diff --git a/backend/src/Notifo.Infrastructure/Scheduling/Implementation/TimerBased/TimerScheduling.cs b/backend/src/Notifo.Infrastructure/Scheduling/Implementation/TimerBased/TimerScheduling.cs index 0a7e10f4..4c0d1961 100644 --- a/backend/src/Notifo.Infrastructure/Scheduling/Implementation/TimerBased/TimerScheduling.cs +++ b/backend/src/Notifo.Infrastructure/Scheduling/Implementation/TimerBased/TimerScheduling.cs @@ -109,9 +109,16 @@ public async Task ScheduleGroupedAsync(string key, string groupKey, T job, Insta } } - public void Complete(string key) + public Task CompleteAsync(string key, + CancellationToken ct = default) + { + return schedulerStore.CompleteByKeyAsync(key, ct); + } + + public Task CompleteAsync(string key, string groupKey, + CancellationToken ct = default) { - schedulerStore.CompleteByKeyAsync(key).Forget(); + return schedulerStore.CompleteByKeyAsync(key, groupKey, ct); } public Task SubscribeAsync(ScheduleSuccessCallback onSuccess, ScheduleErrorCallback onError, diff --git a/backend/src/Notifo/Areas/Api/Controllers/Events/Dtos/CancelEventDto.cs b/backend/src/Notifo/Areas/Api/Controllers/Events/Dtos/CancelEventDto.cs new file mode 100644 index 00000000..ac098cab --- /dev/null +++ b/backend/src/Notifo/Areas/Api/Controllers/Events/Dtos/CancelEventDto.cs @@ -0,0 +1,48 @@ +// ========================================================================== +// Notifo.io +// ========================================================================== +// Copyright (c) Sebastian Stehle +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.ComponentModel.DataAnnotations; +using Notifo.Areas.Api.OpenApi; +using Notifo.Domain.UserNotifications; +using Notifo.Infrastructure.Reflection; + +namespace Notifo.Areas.Api.Controllers.Events.Dtos; + +[OpenApiRequest] +public class CancelEventDto +{ + /// + /// The user ID for which the event was created. + /// + [Required] + public string UserId { get; set; } + + /// + /// The event ID. + /// + [Required] + public string EventId { get; set; } + + /// + /// The grouping key to combine notifications. + /// + public string? GroupKey { get; set; } + + /// + /// True when using test integrations. + /// + public bool Test { get; set; } + + public CancelRequest ToRequest(string appId) + { + var result = SimpleMapper.Map(this, new CancelRequest()); + + result.AppId = appId; + + return result; + } +} diff --git a/backend/src/Notifo/Areas/Api/Controllers/Events/Dtos/CancelResponseDto.cs b/backend/src/Notifo/Areas/Api/Controllers/Events/Dtos/CancelResponseDto.cs new file mode 100644 index 00000000..fa89e32e --- /dev/null +++ b/backend/src/Notifo/Areas/Api/Controllers/Events/Dtos/CancelResponseDto.cs @@ -0,0 +1,16 @@ +// ========================================================================== +// Notifo.io +// ========================================================================== +// Copyright (c) Sebastian Stehle +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Notifo.Areas.Api.Controllers.Events.Dtos; + +public class CancelResponseDto +{ + /// + /// True if something has been cancelled. + /// + public bool HasCancelled { get; set; } +} diff --git a/backend/src/Notifo/Areas/Api/Controllers/Events/Dtos/PublishDto.cs b/backend/src/Notifo/Areas/Api/Controllers/Events/Dtos/PublishDto.cs index 87854742..6fdaa575 100644 --- a/backend/src/Notifo/Areas/Api/Controllers/Events/Dtos/PublishDto.cs +++ b/backend/src/Notifo/Areas/Api/Controllers/Events/Dtos/PublishDto.cs @@ -23,6 +23,11 @@ public sealed class PublishDto [Required] public string Topic { get; set; } + /// + /// A custom ID. + /// + public string? Id { get; set; } + /// /// A custom id to identity the creator. /// diff --git a/backend/src/Notifo/Areas/Api/Controllers/Events/EventsController.cs b/backend/src/Notifo/Areas/Api/Controllers/Events/EventsController.cs index 5194cbd2..ae17e783 100644 --- a/backend/src/Notifo/Areas/Api/Controllers/Events/EventsController.cs +++ b/backend/src/Notifo/Areas/Api/Controllers/Events/EventsController.cs @@ -9,6 +9,7 @@ using Notifo.Areas.Api.Controllers.Events.Dtos; using Notifo.Domain.Events; using Notifo.Domain.Identity; +using Notifo.Domain.UserNotifications; using Notifo.Infrastructure; using Notifo.Infrastructure.Validation; using Notifo.Pipeline; @@ -20,13 +21,16 @@ public sealed class EventsController : BaseController { private readonly IEventStore eventStore; private readonly IEventPublisher eventPublisher; + private readonly IUserNotificationService userNotificationService; public EventsController( IEventStore eventStore, - IEventPublisher eventPublisher) + IEventPublisher eventPublisher, + IUserNotificationService userNotificationService) { this.eventStore = eventStore; this.eventPublisher = eventPublisher; + this.userNotificationService = userNotificationService; } /// @@ -78,6 +82,28 @@ public async Task PostEvents(string appId, [FromBody] PublishMany return NoContent(); } + /// + /// Cancels a scheduled event. + /// + /// The app where the events belongs to. + /// The cancel request. + /// Events cancelled, if found.. + /// App not found.. + [HttpDelete("api/apps/{appId:notEmpty}/events/")] + [AppPermission(NotifoRoles.AppAdmin)] + [Produces(typeof(CancelResponseDto))] + public async Task CancelEvent(string appId, [FromBody] CancelEventDto request) + { + var hasDeleted = await userNotificationService.CancelAsync(request.ToRequest(appId)); + + var response = new CancelResponseDto + { + HasCancelled = hasDeleted + }; + + return Ok(response); + } + /// /// Publish an event for the current user. /// diff --git a/backend/src/Notifo/Notifo.csproj b/backend/src/Notifo/Notifo.csproj index a4b4251c..b2a51559 100644 --- a/backend/src/Notifo/Notifo.csproj +++ b/backend/src/Notifo/Notifo.csproj @@ -9,31 +9,31 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + + - - + + - + - - + + - + - + diff --git a/backend/src/Notifo/appsettings.json b/backend/src/Notifo/appsettings.json index 32334b3e..2cdb2127 100644 --- a/backend/src/Notifo/appsettings.json +++ b/backend/src/Notifo/appsettings.json @@ -263,6 +263,20 @@ "googleClient": "1006817248705-do88a58ledirlu4i1iri7hrc9b0nb6e9.apps.googleusercontent.com", "googleSecret": "AQtFyExcJFfPMfAyCe3Lq_KD", + // Settings for your custom oidc server. + "oidcName": "OIDC", + "oidcAuthority": "", + "oidcClient": "", + "oidcSecret": "", + "oidcMetadataAddress": "", + "oidcScopes": [ + "email" + ], + "oidcResponseType": "id_token", // or "code" + "oidcGetClaimsFromUserInfoEndpoint": false, + "oidcOverridePermissionsWithCustomClaimsOnLogin": false, + "oidcOnSignoutRedirectUrl": "", + // Initial users. "users": [ { diff --git a/backend/tests/Benchmarks/Benchmarks.csproj b/backend/tests/Benchmarks/Benchmarks.csproj index ae028828..e199f3bc 100644 --- a/backend/tests/Benchmarks/Benchmarks.csproj +++ b/backend/tests/Benchmarks/Benchmarks.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -12,7 +12,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/backend/tests/Notifo.Domain.Tests/Channels/Email/MjmlSchemaTests.Should_build_schema.verified.txt b/backend/tests/Notifo.Domain.Tests/Channels/Email/MjmlSchemaTests.Should_build_schema.verified.txt index 60a5fdca..428ed4d9 100644 --- a/backend/tests/Notifo.Domain.Tests/Channels/Email/MjmlSchemaTests.Should_build_schema.verified.txt +++ b/backend/tests/Notifo.Domain.Tests/Channels/Email/MjmlSchemaTests.Should_build_schema.verified.txt @@ -790,6 +790,10 @@ ] }, mjml: { + Attributes: { + dir: null, + lang: null + }, Children: [ mj-body, mj-head, @@ -1585,6 +1589,10 @@ ] }, mjml: { + Attributes: { + dir: null, + lang: null + }, Children: [ mj-body, mj-head, diff --git a/backend/tests/Notifo.Domain.Tests/Channels/Email/MjmlSchemaTests.Should_build_schema_as_json.verified.txt b/backend/tests/Notifo.Domain.Tests/Channels/Email/MjmlSchemaTests.Should_build_schema_as_json.verified.txt index 6fc16234..42a0e6e7 100644 --- a/backend/tests/Notifo.Domain.Tests/Channels/Email/MjmlSchemaTests.Should_build_schema_as_json.verified.txt +++ b/backend/tests/Notifo.Domain.Tests/Channels/Email/MjmlSchemaTests.Should_build_schema_as_json.verified.txt @@ -558,7 +558,10 @@ "children": null }, "mjml": { - "attrs": {}, + "attrs": { + "dir": null, + "lang": null + }, "children": [ "mj-body", "mj-head", diff --git a/backend/tests/Notifo.Domain.Tests/Channels/Email/MjmlSchemaTests.cs b/backend/tests/Notifo.Domain.Tests/Channels/Email/MjmlSchemaTests.cs index 770d8745..f1d42e72 100644 --- a/backend/tests/Notifo.Domain.Tests/Channels/Email/MjmlSchemaTests.cs +++ b/backend/tests/Notifo.Domain.Tests/Channels/Email/MjmlSchemaTests.cs @@ -11,7 +11,6 @@ namespace Notifo.Domain.Channels.Email; -[UsesVerify] public class MjmlSchemaTests { private readonly IMjmlRenderer mjmlRenderer = new MjmlRenderer(); diff --git a/backend/tests/Notifo.Domain.Tests/Integrations/Firebase/UserNotificationExtensionsTests.cs b/backend/tests/Notifo.Domain.Tests/Integrations/Firebase/UserNotificationExtensionsTests.cs index 31c67d77..ccdc513e 100644 --- a/backend/tests/Notifo.Domain.Tests/Integrations/Firebase/UserNotificationExtensionsTests.cs +++ b/backend/tests/Notifo.Domain.Tests/Integrations/Firebase/UserNotificationExtensionsTests.cs @@ -9,7 +9,6 @@ namespace Notifo.Domain.Integrations.Firebase; -[UsesVerify] public class UserNotificationExtensionsTests { private readonly Guid id = Guid.Parse("d9e3afe8-06a2-493e-b7a7-03a4aba61544"); diff --git a/backend/tests/Notifo.Domain.Tests/Notifo.Domain.Tests.csproj b/backend/tests/Notifo.Domain.Tests/Notifo.Domain.Tests.csproj index c285af48..f09e134b 100644 --- a/backend/tests/Notifo.Domain.Tests/Notifo.Domain.Tests.csproj +++ b/backend/tests/Notifo.Domain.Tests/Notifo.Domain.Tests.csproj @@ -13,14 +13,14 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/backend/tests/Notifo.Identity.Tests/Notifo.Identity.Tests.csproj b/backend/tests/Notifo.Identity.Tests/Notifo.Identity.Tests.csproj index bd49d31b..02f5dea3 100644 --- a/backend/tests/Notifo.Identity.Tests/Notifo.Identity.Tests.csproj +++ b/backend/tests/Notifo.Identity.Tests/Notifo.Identity.Tests.csproj @@ -11,12 +11,12 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/backend/tests/Notifo.Infrastructure.Tests/MongoDb/Scheduling/MongoDbSchedulerStoreTests.cs b/backend/tests/Notifo.Infrastructure.Tests/MongoDb/Scheduling/MongoDbSchedulerStoreTests.cs index 7d43feaf..fa8bafd4 100644 --- a/backend/tests/Notifo.Infrastructure.Tests/MongoDb/Scheduling/MongoDbSchedulerStoreTests.cs +++ b/backend/tests/Notifo.Infrastructure.Tests/MongoDb/Scheduling/MongoDbSchedulerStoreTests.cs @@ -50,8 +50,8 @@ public async Task Should_schedule_grouped_with_delay() var delay1 = Duration.FromSeconds(60 * 1000); var delay2 = Duration.FromSeconds(120 * 1000); - await _.Store.EnqueueGroupedAsync("3", "2", 3, now.Plus(delay1), 0, default); - await _.Store.EnqueueGroupedAsync("4", "2", 4, now.Plus(delay2), 0, default); + await _.Store.EnqueueGroupedAsync("1", "group-a", 1, now.Plus(delay1), 0, default); + await _.Store.EnqueueGroupedAsync("2", "group-a", 2, now.Plus(delay2), 0, default); var notDequeued = await _.Store.DequeueAsync(now, default); @@ -60,7 +60,7 @@ public async Task Should_schedule_grouped_with_delay() var dequeued = await _.Store.DequeueAsync(now.Plus(delay2), default); Assert.NotNull(dequeued); - Assert.Equal([3, 4], dequeued!.GetAllJobs()); + Assert.Equal([1, 2], dequeued!.GetAllJobs()); } [Fact] @@ -81,4 +81,38 @@ public async Task Should_schedule_grouped_with_delay_and_eliminate_duplicates() Assert.NotNull(dequeued); Assert.Equal([4], dequeued!.GetAllJobs()); } + + [Fact] + public async Task Should_remove_key_from_group() + { + var delay1 = Duration.FromSeconds(60 * 1000); + var delay2 = Duration.FromSeconds(120 * 1000); + + await _.Store.EnqueueGroupedAsync("1", "group-a", 1, now.Plus(delay1), 0, default); + await _.Store.EnqueueGroupedAsync("2", "group-a", 2, now.Plus(delay2), 0, default); + + await _.Store.CompleteByKeyAsync("1", "group-a", default); + + var dequeued = await _.Store.DequeueAsync(now.Plus(delay2), default); + + Assert.NotNull(dequeued); + Assert.Equal([2], dequeued!.GetAllJobs()); + } + + [Fact] + public async Task Should_remove_multiple_keys_from_group() + { + var delay1 = Duration.FromSeconds(60 * 1000); + var delay2 = Duration.FromSeconds(120 * 1000); + + await _.Store.EnqueueGroupedAsync("1", "group-a", 1, now.Plus(delay1), 0, default); + await _.Store.EnqueueGroupedAsync("1", "group-a", 1, now.Plus(delay2), 0, default); + + await _.Store.CompleteByKeyAsync("1", "group-a", default); + await _.Store.CompleteByKeyAsync("1", "group-a", default); + + var dequeued = await _.Store.DequeueAsync(now.Plus(delay2), default); + + Assert.Null(dequeued); + } } diff --git a/backend/tests/Notifo.Infrastructure.Tests/NodaPatternsTest.cs b/backend/tests/Notifo.Infrastructure.Tests/NodaPatternsTest.cs new file mode 100644 index 00000000..8576790e --- /dev/null +++ b/backend/tests/Notifo.Infrastructure.Tests/NodaPatternsTest.cs @@ -0,0 +1,40 @@ +// ========================================================================== +// Notifo.io +// ========================================================================== +// Copyright (c) Sebastian Stehle +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using NodaTime; + +namespace Notifo.Infrastructure; + +public class NodaPatternsTest +{ + [Fact] + public void Should_parse_and_format_hour_minutes() + { + var parsed = NodaPatterns.VariablePrecisionIso.Parse("12:15").Value; + + Assert.Equal(new LocalTime(12, 15), parsed); + Assert.Equal("12:15:00", NodaPatterns.VariablePrecisionIso.Format(parsed)); + } + + [Fact] + public void Should_parse_and_format_hour_minutes_seconds() + { + var parsed = NodaPatterns.VariablePrecisionIso.Parse("12:15:42").Value; + + Assert.Equal(new LocalTime(12, 15, 42), parsed); + Assert.Equal("12:15:42", NodaPatterns.VariablePrecisionIso.Format(parsed)); + } + + [Fact] + public void Should_parse_and_format_hour_minutes_seconds_milliseconds() + { + var parsed = NodaPatterns.VariablePrecisionIso.Parse("12:15:42.123").Value; + + Assert.Equal(new LocalTime(12, 15, 42, 123), parsed); + Assert.Equal("12:15:42.123", NodaPatterns.VariablePrecisionIso.Format(parsed)); + } +} diff --git a/backend/tests/Notifo.Infrastructure.Tests/Notifo.Infrastructure.Tests.csproj b/backend/tests/Notifo.Infrastructure.Tests/Notifo.Infrastructure.Tests.csproj index cfc4698b..abb4883f 100644 --- a/backend/tests/Notifo.Infrastructure.Tests/Notifo.Infrastructure.Tests.csproj +++ b/backend/tests/Notifo.Infrastructure.Tests/Notifo.Infrastructure.Tests.csproj @@ -11,13 +11,13 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/frontend/src/app/service/service.ts b/frontend/src/app/service/service.ts index 953a8bca..65809b27 100644 --- a/frontend/src/app/service/service.ts +++ b/frontend/src/app/service/service.ts @@ -1,6 +1,6 @@ //---------------------- // -// Generated using the NSwag toolchain v14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) +// Generated using the NSwag toolchain v14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) // //---------------------- @@ -3406,6 +3406,67 @@ export class EventsClient { return Promise.resolve(null as any); } + /** + * Cancels a scheduled event. + * @param appId The app where the events belongs to. + * @param request The cancel request. + */ + cancelEvent(appId: string, request: CancelEventDto): Promise { + let url_ = this.baseUrl + "/api/apps/{appId}/events"; + if (appId === undefined || appId === null) + throw new Error("The parameter 'appId' must be defined."); + url_ = url_.replace("{appId}", encodeURIComponent("" + appId)); + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(request); + + let options_: RequestInit = { + body: content_, + method: "DELETE", + headers: { + "Content-Type": "application/json", + "Accept": "application/json" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processCancelEvent(_response); + }); + } + + protected processCancelEvent(response: Response): Promise { + const status = response.status; + let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; + if (status === 200) { + return response.text().then((_responseText) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as CancelResponseDto; + return result200; + }); + } else if (status === 404) { + return response.text().then((_responseText) => { + return throwException("App not found.", status, _responseText, _headers); + }); + } else if (status === 400) { + return response.text().then((_responseText) => { + let result400: any = null; + result400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ErrorDto; + return throwException("Validation error.", status, _responseText, _headers, result400); + }); + } else if (status === 500) { + return response.text().then((_responseText) => { + let result500: any = null; + result500 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ErrorDto; + return throwException("Operation failed.", status, _responseText, _headers, result500); + }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } + /** * Publish an event for the current user. * @param request The publish request. @@ -6618,6 +6679,8 @@ export interface PublishManyDto { export interface PublishDto { /** The topic path. */ topic: string; + /** A custom ID. */ + id?: string | undefined; /** A custom id to identity the creator. */ creatorId?: string | undefined; /** The template code. */ @@ -6648,6 +6711,22 @@ export interface PublishDto { timeToLiveInSeconds?: number | undefined; } +export interface CancelResponseDto { + /** True if something has been cancelled. */ + hasCancelled: boolean; +} + +export interface CancelEventDto { + /** The user ID for which the event was created. */ + userId: string; + /** The event ID. */ + eventId: string; + /** The grouping key to combine notifications. */ + groupKey?: string | undefined; + /** True when using test integrations. */ + test?: boolean; +} + export interface MjmlSchema { "!top": string[]; diff --git a/frontend/src/app/shared/components/Forms.tsx b/frontend/src/app/shared/components/Forms.tsx index 15260862..32cc87bd 100644 --- a/frontend/src/app/shared/components/Forms.tsx +++ b/frontend/src/app/shared/components/Forms.tsx @@ -472,7 +472,7 @@ const InputLocalizedText = (props: LocalizedFormProps) => { return (
- +
{ return (
- +
{ public ClientFixture _ { get; } diff --git a/tools/TestSuite/TestSuite.ApiTests/EventsTests.cs b/tools/TestSuite/TestSuite.ApiTests/EventsTests.cs new file mode 100644 index 00000000..86e1fbd9 --- /dev/null +++ b/tools/TestSuite/TestSuite.ApiTests/EventsTests.cs @@ -0,0 +1,104 @@ +// ========================================================================== +// Notifo.io +// ========================================================================== +// Copyright (c) Sebastian Stehle +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Notifo.SDK; +using TestSuite.Fixtures; + +#pragma warning disable SA1300 // Element should begin with upper-case letter +#pragma warning disable SA1507 // Code should not contain multiple blank lines in a row + +namespace TestSuite.ApiTests; + +public class EventsTests : IClassFixture +{ + public CreatedAppFixture _ { get; set; } + + public EventsTests(CreatedAppFixture fixture) + { + _ = fixture; + } + + [Fact] + public async Task Should_cancel_unknown_event() + { + var hasCancelled = await PollCancelAsync(Guid.NewGuid().ToString(), "event"); + + Assert.False(hasCancelled); + } + + [Fact] + public async Task Should_cancel_known_event() + { + // STEP 1: Create user + var userRequest = new UpsertUsersDto + { + Requests = + [ + new UpsertUserDto(), + ] + }; + + var users_0 = await _.Client.Users.PostUsersAsync(_.AppId, userRequest); + var user_0 = users_0.First(); + + + // STEP 2: Publish event. + var eventId = Guid.NewGuid().ToString(); + + var publishRequest = new PublishManyDto + { + Requests = + [ + new PublishDto + { + Topic = $"users/{user_0.Id}", + Preformatted = new NotificationFormattingDto + { + Subject = new LocalizedText + { + ["en"] = Guid.NewGuid().ToString() + } + }, + Scheduling = new SchedulingDto + { + Date = DateTime.Now.AddDays(20), + Time = new TimeSpan(12, 0, 0), + }, + Id = eventId, + }, + ] + }; + + await _.Client.Events.PostEventsAsync(_.AppId, publishRequest); + + + // STEP 3: Retry until deleted. + var hasCancelled = await PollCancelAsync(user_0.Id, eventId); + + Assert.True(hasCancelled); + } + + private async Task PollCancelAsync(string userId, string eventId) + { + var request = new CancelEventDto { UserId = userId, Test = false, EventId = eventId }; + + using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30))) + { + while (!cts.IsCancellationRequested) + { + var result = await _.Client.Events.CancelEventAsync(_.AppId, request); + + if (result.HasCancelled) + { + return true; + } + } + } + + return false; + } +} diff --git a/tools/TestSuite/TestSuite.ApiTests/IntegrationTests.cs b/tools/TestSuite/TestSuite.ApiTests/IntegrationTests.cs index 0b2e73ad..65564bf1 100644 --- a/tools/TestSuite/TestSuite.ApiTests/IntegrationTests.cs +++ b/tools/TestSuite/TestSuite.ApiTests/IntegrationTests.cs @@ -12,7 +12,6 @@ namespace TestSuite.ApiTests; -[UsesVerify] public class IntegrationTests : IClassFixture { public CreatedAppFixture _ { get; set; } diff --git a/tools/TestSuite/TestSuite.ApiTests/NotificationTests.cs b/tools/TestSuite/TestSuite.ApiTests/NotificationTests.cs index 3ca57883..bd072409 100644 --- a/tools/TestSuite/TestSuite.ApiTests/NotificationTests.cs +++ b/tools/TestSuite/TestSuite.ApiTests/NotificationTests.cs @@ -13,7 +13,6 @@ namespace TestSuite.ApiTests; -[UsesVerify] public partial class NotificationTests : IClassFixture { private readonly string subject = Guid.NewGuid().ToString(); diff --git a/tools/TestSuite/TestSuite.ApiTests/TemplatesTests.cs b/tools/TestSuite/TestSuite.ApiTests/TemplatesTests.cs index df9927ed..876c774f 100644 --- a/tools/TestSuite/TestSuite.ApiTests/TemplatesTests.cs +++ b/tools/TestSuite/TestSuite.ApiTests/TemplatesTests.cs @@ -13,7 +13,6 @@ namespace TestSuite.ApiTests; -[UsesVerify] public class TemplatesTests : IClassFixture { public CreatedAppFixture _ { get; set; } diff --git a/tools/TestSuite/TestSuite.ApiTests/TestSuite.ApiTests.csproj b/tools/TestSuite/TestSuite.ApiTests/TestSuite.ApiTests.csproj index c53ff616..a936f21a 100644 --- a/tools/TestSuite/TestSuite.ApiTests/TestSuite.ApiTests.csproj +++ b/tools/TestSuite/TestSuite.ApiTests/TestSuite.ApiTests.csproj @@ -7,18 +7,18 @@ enable - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + - - - + + + all runtime; build; native; contentfiles; analyzers diff --git a/tools/TestSuite/TestSuite.ApiTests/UsersTests.cs b/tools/TestSuite/TestSuite.ApiTests/UsersTests.cs index dee3723b..cc707fed 100644 --- a/tools/TestSuite/TestSuite.ApiTests/UsersTests.cs +++ b/tools/TestSuite/TestSuite.ApiTests/UsersTests.cs @@ -13,7 +13,6 @@ namespace TestSuite.ApiTests; -[UsesVerify] public class UsersTests : IClassFixture { public CreatedAppFixture _ { get; set; } diff --git a/tools/TestSuite/TestSuite.LoadTests/TestSuite.LoadTests.csproj b/tools/TestSuite/TestSuite.LoadTests/TestSuite.LoadTests.csproj index 3103bd11..93809436 100644 --- a/tools/TestSuite/TestSuite.LoadTests/TestSuite.LoadTests.csproj +++ b/tools/TestSuite/TestSuite.LoadTests/TestSuite.LoadTests.csproj @@ -7,14 +7,14 @@ enable - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + all runtime; build; native; contentfiles; analyzers diff --git a/tools/TestSuite/TestSuite.Shared/TestSuite.Shared.csproj b/tools/TestSuite/TestSuite.Shared/TestSuite.Shared.csproj index ea8c4fdb..94b9a803 100644 --- a/tools/TestSuite/TestSuite.Shared/TestSuite.Shared.csproj +++ b/tools/TestSuite/TestSuite.Shared/TestSuite.Shared.csproj @@ -7,18 +7,18 @@ enable - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + diff --git a/tools/TestSuite/docker-compose.yml b/tools/TestSuite/docker-compose.yml index 8ef64098..1f1872f7 100644 --- a/tools/TestSuite/docker-compose.yml +++ b/tools/TestSuite/docker-compose.yml @@ -22,6 +22,8 @@ services: - internal depends_on: - mongo + - mailcatcher + - webhookcatcher notifo2: image: notifo-local @@ -44,6 +46,8 @@ services: - internal depends_on: - mongo + - mailcatcher + - webhookcatcher resizer: image: squidex/resizer:dev-40 @@ -61,7 +65,7 @@ services: - internal mailcatcher: - image: jeanberu/mailcatcher + image: jeanberu/mailcatcher:0.8.0 ports: - "1025:1025" - "1080:1080" diff --git a/tools/sdk/CodeGenerator/CodeGenerator.csproj b/tools/sdk/CodeGenerator/CodeGenerator.csproj index 515ecedc..861c760c 100644 --- a/tools/sdk/CodeGenerator/CodeGenerator.csproj +++ b/tools/sdk/CodeGenerator/CodeGenerator.csproj @@ -7,12 +7,12 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/tools/sdk/Directory.Build.props b/tools/sdk/Directory.Build.props index 05eede2d..671a14fc 100644 --- a/tools/sdk/Directory.Build.props +++ b/tools/sdk/Directory.Build.props @@ -11,7 +11,7 @@ https://gibt.com/notifo.io/notifo true snupkg - 1.7.4 + 1.7.5 diff --git a/tools/sdk/Notifo.SDK.Tests/Notifo.SDK.Tests.csproj b/tools/sdk/Notifo.SDK.Tests/Notifo.SDK.Tests.csproj index 84d8d3e7..0aa75dd0 100644 --- a/tools/sdk/Notifo.SDK.Tests/Notifo.SDK.Tests.csproj +++ b/tools/sdk/Notifo.SDK.Tests/Notifo.SDK.Tests.csproj @@ -7,10 +7,10 @@ - + - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tools/sdk/Notifo.SDK/Generated.cs b/tools/sdk/Notifo.SDK/Generated.cs index 7a06884e..c0725d5a 100644 --- a/tools/sdk/Notifo.SDK/Generated.cs +++ b/tools/sdk/Notifo.SDK/Generated.cs @@ -1,6 +1,6 @@ //---------------------- // -// Generated using the NSwag toolchain v14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) +// Generated using the NSwag toolchain v14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) // //---------------------- @@ -20,7 +20,7 @@ namespace Notifo.SDK { using System = global::System; - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface IUserClient { @@ -108,7 +108,7 @@ public partial interface IUserClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UserClient : IUserClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -1015,7 +1015,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface IUsersClient { @@ -1144,7 +1144,7 @@ public partial interface IUsersClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UsersClient : IUsersClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -2529,7 +2529,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface ITopicsClient { @@ -2568,7 +2568,7 @@ public partial interface ITopicsClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class TopicsClient : ITopicsClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -3034,7 +3034,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface ITemplatesClient { @@ -3072,7 +3072,7 @@ public partial interface ITemplatesClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class TemplatesClient : ITemplatesClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -3527,7 +3527,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface ISystemUsersClient { @@ -3599,7 +3599,7 @@ public partial interface ISystemUsersClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SystemUsersClient : ISystemUsersClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -4484,7 +4484,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface IPingClient { @@ -4523,7 +4523,7 @@ public partial interface IPingClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class PingClient : IPingClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -4913,7 +4913,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface INotificationsClient { @@ -4994,7 +4994,7 @@ public partial interface INotificationsClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class NotificationsClient : INotificationsClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -5809,7 +5809,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface IMobilePushClient { @@ -5841,7 +5841,7 @@ public partial interface IMobilePushClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class MobilePushClient : IMobilePushClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -6255,7 +6255,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface IMediaClient { @@ -6379,7 +6379,7 @@ public partial interface IMediaClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class MediaClient : IMediaClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -7495,7 +7495,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface ILogsClient { @@ -7516,7 +7516,7 @@ public partial interface ILogsClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class LogsClient : ILogsClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -7783,7 +7783,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface IEventsClient { @@ -7810,6 +7810,15 @@ public partial interface IEventsClient /// A server side error occurred. System.Threading.Tasks.Task PostEventsAsync(string appId, PublishManyDto request, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// + /// Cancels a scheduled event. + /// + /// The app where the events belongs to. + /// The cancel request. + /// A server side error occurred. + System.Threading.Tasks.Task CancelEventAsync(string appId, CancelEventDto request, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// /// Publish an event for the current user. @@ -7821,7 +7830,7 @@ public partial interface IEventsClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class EventsClient : IEventsClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -8075,6 +8084,120 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() } } + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// + /// Cancels a scheduled event. + /// + /// The app where the events belongs to. + /// The cancel request. + /// A server side error occurred. + public virtual async System.Threading.Tasks.Task CancelEventAsync(string appId, CancelEventDto request, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + if (appId == null) + throw new System.ArgumentNullException("appId"); + + if (request == null) + throw new System.ArgumentNullException("request"); + + var client_ = _httpClientProvider.Get(); + #pragma warning disable CS0219 // Variable is assigned but its value is never used + var disposeClient_ = false; + #pragma warning restore CS0219 // Variable is assigned but its value is never used + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(request, _settings.Value); + var content_ = new System.Net.Http.StringContent(json_); + content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); + request_.Content = content_; + request_.Method = new System.Net.Http.HttpMethod("DELETE"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); + + var urlBuilder_ = new System.Text.StringBuilder(); + + // Operation Path: "api/apps/{appId}/events" + urlBuilder_.Append("api/apps/"); + urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(appId, System.Globalization.CultureInfo.InvariantCulture))); + urlBuilder_.Append("/events"); + + PrepareRequest(client_, request_, urlBuilder_); + + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + var disposeResponse_ = true; + try + { + var headers_ = new System.Collections.Generic.Dictionary>(); + foreach (var item_ in response_.Headers) + headers_[item_.Key] = item_.Value; + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 200 || status_ == 201) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new NotifoException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + return objectResponse_.Object; + } + else + if (status_ == 404) + { + string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new NotifoException("App not found.", status_, responseText_, headers_, null); + } + else + if (status_ == 400) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new NotifoException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new NotifoException("Validation error.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + if (status_ == 500) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new NotifoException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new NotifoException("Operation failed.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new NotifoException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); + } + } + finally + { + if (disposeResponse_) + response_.Dispose(); + } + } + } + finally + { + _httpClientProvider.Return(client_); + } + } + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// /// Publish an event for the current user. @@ -8290,7 +8413,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface IDiagnosticsClient { @@ -8312,7 +8435,7 @@ public partial interface IDiagnosticsClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class DiagnosticsClient : IDiagnosticsClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -8628,7 +8751,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface IConfigsClient { @@ -8650,7 +8773,7 @@ public partial interface IConfigsClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ConfigsClient : IConfigsClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -8958,7 +9081,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface IEmailTemplatesClient { @@ -9075,7 +9198,7 @@ public partial interface IEmailTemplatesClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class EmailTemplatesClient : IEmailTemplatesClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -10431,7 +10554,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface IMessagingTemplatesClient { @@ -10521,7 +10644,7 @@ public partial interface IMessagingTemplatesClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class MessagingTemplatesClient : IMessagingTemplatesClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -11577,7 +11700,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface ISmsTemplatesClient { @@ -11667,7 +11790,7 @@ public partial interface ISmsTemplatesClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SmsTemplatesClient : ISmsTemplatesClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -12723,7 +12846,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial interface IAppsClient { @@ -12825,7 +12948,7 @@ public partial interface IAppsClient } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class AppsClient : IAppsClient { private Notifo.SDK.Configuration.IHttpClientProvider _httpClientProvider; @@ -14021,7 +14144,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ProfileDto { /// @@ -14086,7 +14209,7 @@ public partial class ProfileDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ChannelSettingDto { /// @@ -14139,7 +14262,7 @@ public partial class ChannelSettingDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public enum ChannelSend { @@ -14157,7 +14280,7 @@ public enum ChannelSend } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public enum ChannelCondition { @@ -14175,7 +14298,7 @@ public enum ChannelCondition } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public enum ChannelRequired { @@ -14190,13 +14313,13 @@ public enum ChannelRequired } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class NotificationProperties : System.Collections.Generic.Dictionary { } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ErrorDto { /// @@ -14237,7 +14360,7 @@ public partial class ErrorDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class AdminProfileDto { /// @@ -14248,7 +14371,7 @@ public partial class AdminProfileDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UpdateProfileDto { /// @@ -14289,7 +14412,7 @@ public partial class UpdateProfileDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UserTopicDto { /// @@ -14327,7 +14450,7 @@ public partial class UserTopicDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public enum TopicChannel { @@ -14339,7 +14462,7 @@ public enum TopicChannel } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ListResponseDtoOfSubscriptionDto { /// @@ -14357,7 +14480,7 @@ public partial class ListResponseDtoOfSubscriptionDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SubscriptionDto { /// @@ -14382,7 +14505,7 @@ public partial class SubscriptionDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SchedulingDto { /// @@ -14422,7 +14545,7 @@ public partial class SchedulingDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public enum SchedulingType { @@ -14439,7 +14562,7 @@ public enum SchedulingType ///
ISO-8601. This corresponds with System.DayOfWeek except for Sunday, which ///
is 7 in the ISO numbering and 0 in System.DayOfWeek. ///
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public enum IsoDayOfWeek { @@ -14469,7 +14592,7 @@ public enum IsoDayOfWeek } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SubscribeManyDto { /// @@ -14486,7 +14609,7 @@ public partial class SubscribeManyDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SubscribeDto { /// @@ -14516,7 +14639,7 @@ public partial class SubscribeDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ListResponseDtoOfUserDto { /// @@ -14534,7 +14657,7 @@ public partial class ListResponseDtoOfUserDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UserDto { /// @@ -14655,7 +14778,7 @@ public partial class UserDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class MobilePushTokenDto { /// @@ -14687,7 +14810,7 @@ public partial class MobilePushTokenDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public enum MobileDeviceType { @@ -14702,7 +14825,7 @@ public enum MobileDeviceType } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class WebPushSubscriptionDto { /// @@ -14714,7 +14837,7 @@ public partial class WebPushSubscriptionDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UserPropertyDto { /// @@ -14738,7 +14861,7 @@ public partial class UserPropertyDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UpsertUsersDto { /// @@ -14750,7 +14873,7 @@ public partial class UpsertUsersDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UpsertUserDto { /// @@ -14821,7 +14944,7 @@ public partial class UpsertUserDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class AddAllowedTopicDto { /// @@ -14833,7 +14956,7 @@ public partial class AddAllowedTopicDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ListResponseDtoOfTopicDto { /// @@ -14851,7 +14974,7 @@ public partial class ListResponseDtoOfTopicDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class TopicDto { /// @@ -14914,13 +15037,13 @@ public partial class TopicDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class LocalizedText : System.Collections.Generic.Dictionary { } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public enum TopicQueryScope { @@ -14935,7 +15058,7 @@ public enum TopicQueryScope } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UpsertTopicsDto { /// @@ -14947,7 +15070,7 @@ public partial class UpsertTopicsDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UpsertTopicDto { /// @@ -14982,7 +15105,7 @@ public partial class UpsertTopicDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ListResponseDtoOfTemplateDto { /// @@ -15000,7 +15123,7 @@ public partial class ListResponseDtoOfTemplateDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class TemplateDto { /// @@ -15040,7 +15163,7 @@ public partial class TemplateDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class NotificationFormattingDto { /// @@ -15101,7 +15224,7 @@ public partial class NotificationFormattingDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public enum ConfirmMode { @@ -15113,7 +15236,7 @@ public enum ConfirmMode } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UpsertTemplatesDto { /// @@ -15125,7 +15248,7 @@ public partial class UpsertTemplatesDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UpsertTemplateDto { /// @@ -15150,7 +15273,7 @@ public partial class UpsertTemplateDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ListResponseDtoOfSystemUserDto { /// @@ -15168,7 +15291,7 @@ public partial class ListResponseDtoOfSystemUserDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SystemUserDto { /// @@ -15206,7 +15329,7 @@ public partial class SystemUserDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class CreateSystemUserDto { /// @@ -15231,7 +15354,7 @@ public partial class CreateSystemUserDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UpdateSystemUserDto { /// @@ -15256,7 +15379,7 @@ public partial class UpdateSystemUserDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class InfoDto { /// @@ -15268,7 +15391,7 @@ public partial class InfoDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ListResponseDtoOfUserNotificationDetailsDto { /// @@ -15286,7 +15409,7 @@ public partial class ListResponseDtoOfUserNotificationDetailsDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UserNotificationDetailsDto : UserNotificationBaseDto { /// @@ -15316,7 +15439,7 @@ public partial class UserNotificationDetailsDto : UserNotificationBaseDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UserNotificationChannelDto { /// @@ -15353,7 +15476,7 @@ public partial class UserNotificationChannelDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ChannelSendInfoDto { /// @@ -15404,7 +15527,7 @@ public partial class ChannelSendInfoDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public enum DeliveryStatus { @@ -15428,13 +15551,13 @@ public enum DeliveryStatus } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SendConfiguration : System.Collections.Generic.Dictionary { } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class HandledInfoDto { /// @@ -15452,7 +15575,7 @@ public partial class HandledInfoDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public abstract partial class UserNotificationBaseDto { /// @@ -15575,7 +15698,7 @@ public abstract partial class UserNotificationBaseDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ListResponseDtoOfUserNotificationDto { /// @@ -15593,7 +15716,7 @@ public partial class ListResponseDtoOfUserNotificationDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UserNotificationDto : UserNotificationBaseDto { /// @@ -15610,7 +15733,7 @@ public partial class UserNotificationDto : UserNotificationBaseDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public enum DeviceNotificationsQueryScope { @@ -15625,7 +15748,7 @@ public enum DeviceNotificationsQueryScope } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class TrackNotificationDto { /// @@ -15661,7 +15784,7 @@ public partial class TrackNotificationDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ListResponseDtoOfMobilePushTokenDto { /// @@ -15679,7 +15802,7 @@ public partial class ListResponseDtoOfMobilePushTokenDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class MobilePushTokenDto2 { /// @@ -15705,7 +15828,7 @@ public partial class MobilePushTokenDto2 } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class RegisterMobileTokenDto { /// @@ -15729,7 +15852,7 @@ public partial class RegisterMobileTokenDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ListResponseDtoOfMediaDto { /// @@ -15747,7 +15870,7 @@ public partial class ListResponseDtoOfMediaDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class MediaDto { /// @@ -15815,7 +15938,7 @@ public partial class MediaDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public enum MediaType { @@ -15833,13 +15956,13 @@ public enum MediaType } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class MediaMetadata : System.Collections.Generic.Dictionary { } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public enum ResizeMode { @@ -15866,7 +15989,7 @@ public enum ResizeMode } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ListResponseDtoOfLogEntryDto { /// @@ -15884,7 +16007,7 @@ public partial class ListResponseDtoOfLogEntryDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class LogEntryDto { /// @@ -15929,7 +16052,7 @@ public partial class LogEntryDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ListResponseDtoOfEventDto { /// @@ -15947,7 +16070,7 @@ public partial class ListResponseDtoOfEventDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class EventDto { /// @@ -16038,7 +16161,7 @@ public partial class EventDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class PublishManyDto { /// @@ -16050,7 +16173,7 @@ public partial class PublishManyDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class PublishDto { /// @@ -16060,6 +16183,12 @@ public partial class PublishDto [System.ComponentModel.DataAnnotations.Required] public string Topic { get; set; } + /// + /// A custom ID. + /// + [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Id { get; set; } + /// /// A custom id to identity the creator. /// @@ -16146,7 +16275,49 @@ public partial class PublishDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class CancelResponseDto + { + /// + /// True if something has been cancelled. + /// + [Newtonsoft.Json.JsonProperty("hasCancelled", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool HasCancelled { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class CancelEventDto + { + /// + /// The user ID for which the event was created. + /// + [Newtonsoft.Json.JsonProperty("userId", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [System.ComponentModel.DataAnnotations.Required] + public string UserId { get; set; } + + /// + /// The event ID. + /// + [Newtonsoft.Json.JsonProperty("eventId", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [System.ComponentModel.DataAnnotations.Required] + public string EventId { get; set; } + + /// + /// The grouping key to combine notifications. + /// + [Newtonsoft.Json.JsonProperty("groupKey", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string GroupKey { get; set; } + + /// + /// True when using test integrations. + /// + [Newtonsoft.Json.JsonProperty("test", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool Test { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class MjmlSchema { [Newtonsoft.Json.JsonProperty("!top", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -16164,7 +16335,7 @@ public System.Collections.Generic.IDictionary AdditionalProperti } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class EmailPreviewDto { /// @@ -16181,7 +16352,7 @@ public partial class EmailPreviewDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class EmailPreviewErrorDto { /// @@ -16205,7 +16376,7 @@ public partial class EmailPreviewErrorDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class EmailPreviewRequestDto { /// @@ -16224,7 +16395,7 @@ public partial class EmailPreviewRequestDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public enum EmailPreviewType { @@ -16236,7 +16407,7 @@ public enum EmailPreviewType } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ListResponseDtoOfChannelTemplateDto { /// @@ -16254,7 +16425,7 @@ public partial class ListResponseDtoOfChannelTemplateDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ChannelTemplateDto { /// @@ -16285,7 +16456,7 @@ public partial class ChannelTemplateDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ChannelTemplateDetailsDtoOfEmailTemplateDto { /// @@ -16330,7 +16501,7 @@ public partial class ChannelTemplateDetailsDtoOfEmailTemplateDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class EmailTemplateDto { /// @@ -16367,13 +16538,13 @@ public partial class EmailTemplateDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class CreateChannelTemplateDto { } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class CreateChannelTemplateLanguageDto { /// @@ -16385,7 +16556,7 @@ public partial class CreateChannelTemplateLanguageDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UpdateChannelTemplateDtoOfEmailTemplateDto { /// @@ -16408,7 +16579,7 @@ public partial class UpdateChannelTemplateDtoOfEmailTemplateDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ChannelTemplateDetailsDtoOfMessagingTemplateDto { /// @@ -16453,7 +16624,7 @@ public partial class ChannelTemplateDetailsDtoOfMessagingTemplateDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class MessagingTemplateDto { /// @@ -16465,7 +16636,7 @@ public partial class MessagingTemplateDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UpdateChannelTemplateDtoOfMessagingTemplateDto { /// @@ -16488,7 +16659,7 @@ public partial class UpdateChannelTemplateDtoOfMessagingTemplateDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ChannelTemplateDetailsDtoOfSmsTemplateDto { /// @@ -16533,7 +16704,7 @@ public partial class ChannelTemplateDetailsDtoOfSmsTemplateDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SmsTemplateDto { /// @@ -16545,7 +16716,7 @@ public partial class SmsTemplateDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UpdateChannelTemplateDtoOfSmsTemplateDto { /// @@ -16568,7 +16739,7 @@ public partial class UpdateChannelTemplateDtoOfSmsTemplateDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class AppDto { /// @@ -16629,7 +16800,7 @@ public partial class AppDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class AppDetailsDto { /// @@ -16703,7 +16874,7 @@ public partial class AppDetailsDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class AppContributorDto { /// @@ -16729,7 +16900,7 @@ public partial class AppContributorDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UpsertAppDto { /// @@ -16794,7 +16965,7 @@ public partial class UpsertAppDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class AddContributorDto { /// @@ -16812,7 +16983,7 @@ public partial class AddContributorDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ConfiguredIntegrationsDto { /// @@ -16831,7 +17002,7 @@ public partial class ConfiguredIntegrationsDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ConfiguredIntegrationDto { /// @@ -16882,7 +17053,7 @@ public partial class ConfiguredIntegrationDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public enum IntegrationStatus { @@ -16900,7 +17071,7 @@ public enum IntegrationStatus } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class IntegrationDefinitionDto { /// @@ -16939,7 +17110,7 @@ public partial class IntegrationDefinitionDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class IntegrationPropertyDto { /// @@ -17025,7 +17196,7 @@ public partial class IntegrationPropertyDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public enum PropertyType { @@ -17046,7 +17217,7 @@ public enum PropertyType } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class IntegrationCreatedDto { /// @@ -17065,7 +17236,7 @@ public partial class IntegrationCreatedDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class CreateIntegrationDto { /// @@ -17102,7 +17273,7 @@ public partial class CreateIntegrationDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UpdateIntegrationDto { /// @@ -17138,7 +17309,7 @@ public partial class UpdateIntegrationDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] internal class DateFormatConverter : Newtonsoft.Json.Converters.IsoDateTimeConverter { public DateFormatConverter() @@ -17147,7 +17318,7 @@ public DateFormatConverter() } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class FileParameter { public FileParameter(System.IO.Stream data) @@ -17174,7 +17345,7 @@ public FileParameter(System.IO.Stream data, string fileName, string contentType) public string ContentType { get; private set; } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class FileResponse : System.IDisposable { private System.IDisposable _client; @@ -17211,7 +17382,7 @@ public void Dispose() } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class NotifoException : System.Exception { public int StatusCode { get; private set; } @@ -17234,7 +17405,7 @@ public override string ToString() } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class NotifoException : NotifoException { public TResult Result { get; private set; } diff --git a/tools/sdk/Notifo.SDK/Notifo.SDK.csproj b/tools/sdk/Notifo.SDK/Notifo.SDK.csproj index cb5e991a..7440ab66 100644 --- a/tools/sdk/Notifo.SDK/Notifo.SDK.csproj +++ b/tools/sdk/Notifo.SDK/Notifo.SDK.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive