Add support for browser push (#308)
Co-authored-by: Patrick Ngo <pango@microsoft.com>
This commit is contained in:
Родитель
7100b5928e
Коммит
87fca6b3d6
|
@ -4,6 +4,7 @@
|
|||
// license information.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System.Text.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Azure.NotificationHubs.Tests
|
||||
|
@ -151,6 +152,34 @@ namespace Microsoft.Azure.NotificationHubs.Tests
|
|||
Assert.Equal(ChannelUri, installation.PushChannel);
|
||||
Assert.Equal(NotificationPlatform.Mpns, installation.Platform);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanCreateBrowserInstallation()
|
||||
{
|
||||
var installation = new BrowserInstallation();
|
||||
|
||||
Assert.Equal(NotificationPlatform.Browser, installation.Platform);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanCreateBrowserInstallationWithBrowserPushSubscription()
|
||||
{
|
||||
var browserPushSubscription = new BrowserPushSubscription
|
||||
{
|
||||
Endpoint = "foo",
|
||||
P256DH = "bar",
|
||||
Auth = "baz",
|
||||
};
|
||||
|
||||
var installation = new BrowserInstallation(InstallationId, browserPushSubscription);
|
||||
var pushSubscription = JsonSerializer.Deserialize<BrowserPushSubscription>(installation.PushChannel);
|
||||
|
||||
Assert.NotNull(pushSubscription);
|
||||
Assert.Equal(browserPushSubscription.Endpoint, pushSubscription.Endpoint);
|
||||
Assert.Equal(browserPushSubscription.P256DH, pushSubscription.P256DH);
|
||||
Assert.Equal(browserPushSubscription.Auth, pushSubscription.Auth);
|
||||
Assert.Equal(NotificationPlatform.Browser, installation.Platform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace Microsoft.Azure.NotificationHubs.DotNetCore.Tests
|
|||
Assert.Equal($"application/json;charset={Encoding.UTF8.WebName}", new TemplateNotification(new Dictionary<string, string>()).ContentType);
|
||||
Assert.Equal("application/json", new AdmNotification("{\"data\":{\"key1\":\"value1\"}}").ContentType);
|
||||
Assert.Equal("application/x-www-form-urlencoded", new BaiduNotification("{\"title\":\"Title\",\"description\":\"Description\"}").ContentType);
|
||||
Assert.Equal($"application/json;charset={Encoding.UTF8.WebName}", new BrowserNotification("{\"title\": \"Title\", \"message\": \"Hello World!\"}").ContentType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System.Runtime.Serialization;
|
||||
using Microsoft.Azure.NotificationHubs.Messaging;
|
||||
|
||||
namespace Microsoft.Azure.NotificationHubs
|
||||
{
|
||||
[DataContract(Name = ManagementStrings.BrowserCredential, Namespace = ManagementStrings.Namespace)]
|
||||
public class BrowserCredential : PnsCredential
|
||||
{
|
||||
internal const string AppPlatformName = "browser";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets web push subject
|
||||
/// </summary>
|
||||
public string Subject
|
||||
{
|
||||
get { return base[nameof(Subject)]; }
|
||||
set { base[nameof(Subject)] = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets VAPID public key.
|
||||
/// </summary>
|
||||
public string VapidPublicKey
|
||||
{
|
||||
get { return base[nameof(VapidPublicKey)]; }
|
||||
set { base[nameof(VapidPublicKey)] = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets VAPID private key.
|
||||
/// </summary>
|
||||
public string VapidPrivateKey
|
||||
{
|
||||
get { return base[nameof(VapidPrivateKey)]; }
|
||||
set { base[nameof(VapidPrivateKey)] = value; }
|
||||
}
|
||||
|
||||
internal override string AppPlatform => AppPlatformName;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether the credential is equal with the specific object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// true if the credential is equal with the specific object; otherwise, false.
|
||||
/// </returns>
|
||||
/// <param name="other">The other object to compare.</param>
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
var otherCredential = other as BrowserCredential;
|
||||
if (otherCredential == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (otherCredential.Subject == Subject && otherCredential.VapidPublicKey == VapidPublicKey && otherCredential.VapidPrivateKey == VapidPrivateKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the hash code for the credentials.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The hash code for the credentials.
|
||||
/// </returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return unchecked(Subject.GetHashCode() ^ VapidPublicKey.GetHashCode() ^ VapidPrivateKey.GetHashCode());
|
||||
}
|
||||
|
||||
/// <summary>Validates the browser credential.</summary>
|
||||
/// <param name="allowLocalMockPns">true to allow local mock PNS; otherwise, false.</param>
|
||||
protected override void OnValidate(bool allowLocalMockPns)
|
||||
{
|
||||
if (Properties == null || Properties.Count > 3)
|
||||
{
|
||||
throw new InvalidDataContractException(SRClient.BrowserRequiredProperties);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Subject))
|
||||
{
|
||||
throw new InvalidDataContractException(SRClient.BrowserSubjectNotSpecified);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(VapidPublicKey))
|
||||
{
|
||||
throw new InvalidDataContractException(SRClient.BrowserVapidPublicKeyNotSpecified);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(VapidPrivateKey))
|
||||
{
|
||||
throw new InvalidDataContractException(SRClient.BrowserVapidPrivateKeyNotSpecified);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Microsoft.Azure.NotificationHubs
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represents a browser installation.
|
||||
/// </summary>
|
||||
public class BrowserInstallation : Installation
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:Microsoft.Azure.NotificationHubs.BrowserInstallation"/> class.
|
||||
/// </summary>
|
||||
public BrowserInstallation()
|
||||
{
|
||||
Platform = NotificationPlatform.Browser;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:Microsoft.Azure.NotificationHubs.BrowserInstallation"/> class.
|
||||
/// </summary>
|
||||
/// <param name="installationId">The unique identifier for the installation.</param>
|
||||
/// <param name="browserPushSubscription">The browser push subscription.</param>
|
||||
public BrowserInstallation(string installationId, BrowserPushSubscription browserPushSubscription) : this()
|
||||
{
|
||||
InstallationId = installationId ?? throw new ArgumentNullException(nameof(installationId));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(browserPushSubscription.Endpoint))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(browserPushSubscription.Endpoint));
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(browserPushSubscription.P256DH))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(browserPushSubscription.P256DH));
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(browserPushSubscription.Auth))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(browserPushSubscription.Auth));
|
||||
}
|
||||
|
||||
PushChannel = JsonSerializer.Serialize(browserPushSubscription);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//----------------------------------------------------------------
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Azure.NotificationHubs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a browser notification.
|
||||
/// </summary>
|
||||
public class BrowserNotification : Notification, INativeNotification
|
||||
{
|
||||
private static string contentType = $"application/json;charset={Encoding.UTF8.WebName}";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:Microsoft.Azure.NotificationHubs.BrowserNotification"/> class.
|
||||
/// </summary>
|
||||
/// <param name="payload">The notification payload.</param>
|
||||
public BrowserNotification(string payload) : base(null, null, contentType)
|
||||
{
|
||||
Body = payload;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The platform type.
|
||||
/// </summary>
|
||||
protected override string PlatformType => BrowserCredential.AppPlatformName;
|
||||
|
||||
/// <summary>
|
||||
/// Validate and populates the headers.
|
||||
/// </summary>
|
||||
protected override void OnValidateAndPopulateHeaders()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Microsoft.Azure.NotificationHubs
|
||||
{
|
||||
public class BrowserPushSubscription
|
||||
{
|
||||
[JsonPropertyName("endpoint")]
|
||||
public string Endpoint { get; set; }
|
||||
|
||||
[JsonPropertyName("p256dh")]
|
||||
public string P256DH { get; set; }
|
||||
|
||||
[JsonPropertyName("auth")]
|
||||
public string Auth { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text.Json;
|
||||
using Microsoft.Azure.NotificationHubs.Messaging;
|
||||
|
||||
namespace Microsoft.Azure.NotificationHubs
|
||||
{
|
||||
[DataContract(Name = ManagementStrings.BrowserRegistrationDescription, Namespace = ManagementStrings.Namespace)]
|
||||
public class BrowserRegistrationDescription : RegistrationDescription
|
||||
{
|
||||
private const string PlatformName = "browser";
|
||||
private BrowserPushSubscription _browserPushSubscription;
|
||||
|
||||
/// <summary>
|
||||
/// Browser push endpoint from PNS.
|
||||
/// </summary>
|
||||
[DataMember(Name = ManagementStrings.BrowserEndpoint, Order = 2001, IsRequired = true)]
|
||||
public string Endpoint
|
||||
{
|
||||
get
|
||||
{
|
||||
return _browserPushSubscription?.Endpoint;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_browserPushSubscription != null)
|
||||
{
|
||||
_browserPushSubscription.Endpoint = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Browser push P256DH key from PNS.
|
||||
/// </summary>
|
||||
[DataMember(Name = ManagementStrings.BrowserP256DH, Order = 2002, IsRequired = true)]
|
||||
public string P256DH
|
||||
{
|
||||
get
|
||||
{
|
||||
return _browserPushSubscription?.P256DH;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_browserPushSubscription != null)
|
||||
{
|
||||
_browserPushSubscription.P256DH = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Browser push authentication secret from PNS.
|
||||
/// </summary>
|
||||
[DataMember(Name = ManagementStrings.BrowserAuth, Order = 2003, IsRequired = true)]
|
||||
public string Auth
|
||||
{
|
||||
get
|
||||
{
|
||||
return _browserPushSubscription?.Auth;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_browserPushSubscription != null)
|
||||
{
|
||||
_browserPushSubscription.Auth = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates instance of <see cref="T:Microsoft.Azure.NotificationHubs.BrowserRegistrationDescription"/> class copying fields from another instance.
|
||||
/// </summary>
|
||||
/// <param name="sourceRegistration">Another <see cref="T:Microsoft.Azure.NotificationHubs.BrowserRegistrationDescription"/> instance whose fields values will be copied.</param>
|
||||
public BrowserRegistrationDescription(BrowserRegistrationDescription sourceRegistration) : base(sourceRegistration)
|
||||
{
|
||||
var browserPushSubscription = new BrowserPushSubscription
|
||||
{
|
||||
Endpoint = sourceRegistration.Endpoint,
|
||||
P256DH = sourceRegistration.P256DH,
|
||||
Auth = sourceRegistration.Auth,
|
||||
};
|
||||
|
||||
ValidateBrowserPushSubscription(browserPushSubscription);
|
||||
|
||||
_browserPushSubscription = browserPushSubscription;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates instance of <see cref="T:Microsoft.Azure.NotificationHubs.BrowserRegistrationDescription"/> class.
|
||||
/// </summary>
|
||||
/// <param name="browserPushSubscription">The browser push subscription.</param>
|
||||
public BrowserRegistrationDescription(BrowserPushSubscription browserPushSubscription) : this(browserPushSubscription, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates instance of <see cref="T:Microsoft.Azure.NotificationHubs.BrowserRegistrationDescription"/> class.
|
||||
/// </summary>
|
||||
/// <param name="browserPushSubscription">The browser push subscription.</param>
|
||||
/// <param name="tags">Collection of tags. Tags can be used for audience targeting purposes.</param>
|
||||
public BrowserRegistrationDescription(BrowserPushSubscription browserPushSubscription, IEnumerable<string> tags)
|
||||
: this(string.Empty, browserPushSubscription, tags)
|
||||
{
|
||||
}
|
||||
|
||||
internal BrowserRegistrationDescription(string notificationHubPath, BrowserPushSubscription browserPushSubscription, IEnumerable<string> tags) : base(notificationHubPath)
|
||||
{
|
||||
ValidateBrowserPushSubscription(browserPushSubscription);
|
||||
|
||||
_browserPushSubscription = new BrowserPushSubscription
|
||||
{
|
||||
Endpoint = browserPushSubscription.Endpoint,
|
||||
P256DH = browserPushSubscription.P256DH,
|
||||
Auth = browserPushSubscription.Auth,
|
||||
};
|
||||
|
||||
if (tags != null)
|
||||
{
|
||||
Tags = new HashSet<string>(tags);
|
||||
}
|
||||
}
|
||||
|
||||
internal override string AppPlatForm
|
||||
{
|
||||
get { return BrowserCredential.AppPlatformName; }
|
||||
}
|
||||
|
||||
internal override string RegistrationType
|
||||
{
|
||||
get { return BrowserCredential.AppPlatformName; }
|
||||
}
|
||||
|
||||
internal override string PlatformType
|
||||
{
|
||||
get { return BrowserCredential.AppPlatformName; }
|
||||
}
|
||||
|
||||
internal override string GetPnsHandle() => JsonSerializer.Serialize(_browserPushSubscription);
|
||||
|
||||
internal override void SetPnsHandle(string pnsHandle)
|
||||
{
|
||||
var browserPushSubscription = JsonSerializer.Deserialize<BrowserPushSubscription>(pnsHandle);
|
||||
Endpoint = browserPushSubscription.Endpoint;
|
||||
P256DH = browserPushSubscription.P256DH;
|
||||
Auth = browserPushSubscription.Auth;
|
||||
|
||||
_browserPushSubscription = browserPushSubscription;
|
||||
}
|
||||
|
||||
internal override RegistrationDescription Clone()
|
||||
{
|
||||
return new BrowserRegistrationDescription(this);
|
||||
}
|
||||
|
||||
private void ValidateBrowserPushSubscription(BrowserPushSubscription browserPushSubscription)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(browserPushSubscription.Endpoint))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(browserPushSubscription.Endpoint));
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(browserPushSubscription.P256DH))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(browserPushSubscription.P256DH));
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(browserPushSubscription.Auth))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(browserPushSubscription.Auth));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Json;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Azure.NotificationHubs.Messaging;
|
||||
|
||||
namespace Microsoft.Azure.NotificationHubs
|
||||
{
|
||||
public class BrowserTemplateRegistrationDescription : BrowserRegistrationDescription
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates instance of <see cref="T:Microsoft.Azure.NotificationHubs.BrowserTemplateRegistrationDescription"/> class by copying fields from the given instance
|
||||
/// </summary>
|
||||
/// <param name="sourceRegistration">Another <see cref="T:Microsoft.Azure.NotificationHubs.BrowserTemplateRegistrationDescription"/> instance whose fields values are copied from</param>
|
||||
public BrowserTemplateRegistrationDescription(BrowserTemplateRegistrationDescription sourceRegistration)
|
||||
: base(sourceRegistration)
|
||||
{
|
||||
BodyTemplate = sourceRegistration.BodyTemplate;
|
||||
TemplateName = sourceRegistration.TemplateName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates instance of <see cref="T:Microsoft.Azure.NotificationHubs.BrowserTemplateRegistrationDescription"/> class
|
||||
/// </summary>
|
||||
/// <param name="browserPushSubscription">The browser push subscription.</param>
|
||||
public BrowserTemplateRegistrationDescription(BrowserPushSubscription browserPushSubscription)
|
||||
: base(browserPushSubscription)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates instance of <see cref="T:Microsoft.Azure.NotificationHubs.BrowserTemplateRegistrationDescription"/> class
|
||||
/// </summary>
|
||||
/// <param name="browserPushSubscription">The browser push subscription.</param>
|
||||
/// <param name="jsonPayload">Payload template.</param>
|
||||
public BrowserTemplateRegistrationDescription(BrowserPushSubscription browserPushSubscription, string jsonPayload)
|
||||
: this(string.Empty, browserPushSubscription, jsonPayload, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates instance of <see cref="T:Microsoft.Azure.NotificationHubs.FcmV1TemplateRegistrationDescription"/> class
|
||||
/// </summary>
|
||||
/// <param name="browserPushSubscription">The browser push subscription.</param>
|
||||
/// <param name="jsonPayload">Payload template.</param>
|
||||
/// <param name="tags">Collection of tags. Tags can be used for audience targeting purposes.</param>
|
||||
public BrowserTemplateRegistrationDescription(BrowserPushSubscription browserPushSubscription, string jsonPayload, IEnumerable<string> tags)
|
||||
: this(string.Empty, browserPushSubscription, jsonPayload, tags)
|
||||
{
|
||||
}
|
||||
|
||||
internal BrowserTemplateRegistrationDescription(string notificationHubPath, BrowserPushSubscription browserPushSubscription, string jsonPayload, IEnumerable<string> tags)
|
||||
: base(notificationHubPath, browserPushSubscription, tags)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(jsonPayload))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(jsonPayload));
|
||||
}
|
||||
|
||||
BodyTemplate = new CDataMember(jsonPayload);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a template body for notification payload which may contain placeholders to be filled in with actual data during the send operation
|
||||
/// </summary>
|
||||
[DataMember(Name = ManagementStrings.BodyTemplate, IsRequired = true, Order = 3001)]
|
||||
public CDataMember BodyTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a name of the template
|
||||
/// </summary>
|
||||
[DataMember(Name = ManagementStrings.TemplateName, IsRequired = false, Order = 3002)]
|
||||
public string TemplateName { get; set; }
|
||||
|
||||
internal override string AppPlatForm
|
||||
{
|
||||
get
|
||||
{
|
||||
return BrowserCredential.AppPlatformName;
|
||||
}
|
||||
}
|
||||
|
||||
internal override string RegistrationType
|
||||
{
|
||||
get
|
||||
{
|
||||
return RegistrationDescription.TemplateRegistrationType;
|
||||
}
|
||||
}
|
||||
|
||||
internal override string PlatformType
|
||||
{
|
||||
get
|
||||
{
|
||||
return BrowserCredential.AppPlatformName + RegistrationDescription.TemplateRegistrationType;
|
||||
}
|
||||
}
|
||||
|
||||
internal override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
|
||||
try
|
||||
{
|
||||
using (XmlReader reader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(BodyTemplate), new XmlDictionaryReaderQuotas()))
|
||||
{
|
||||
XDocument payloadDocument = XDocument.Load(reader);
|
||||
|
||||
foreach (XElement element in payloadDocument.Root.DescendantsAndSelf())
|
||||
{
|
||||
foreach (XAttribute attribute in element.Attributes())
|
||||
{
|
||||
ExpressionEvaluator.Validate(attribute.Value);
|
||||
}
|
||||
|
||||
if (!element.HasElements && !string.IsNullOrEmpty(element.Value))
|
||||
{
|
||||
ExpressionEvaluator.Validate(element.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// We get an ugly and misleading error message when this exception happens -> The XmlReader state should be Interactive.
|
||||
// Hence we are using a more friendlier error message
|
||||
throw new XmlException(SRClient.FailedToDeserializeBodyTemplate);
|
||||
}
|
||||
|
||||
ValidateTemplateName();
|
||||
}
|
||||
|
||||
private void ValidateTemplateName()
|
||||
{
|
||||
if (TemplateName != null)
|
||||
{
|
||||
if (TemplateName.Length > RegistrationSDKHelper.TemplateMaxLength)
|
||||
{
|
||||
throw new InvalidDataContractException(string.Format(SRClient.TemplateNameLengthExceedsLimit, RegistrationSDKHelper.TemplateMaxLength));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal override RegistrationDescription Clone()
|
||||
{
|
||||
return new BrowserTemplateRegistrationDescription(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -41,6 +41,8 @@ namespace Microsoft.Azure.NotificationHubs.Messaging
|
|||
public const string MpnsTemplateRegistrationDescription = "MpnsTemplateRegistrationDescription";
|
||||
public const string AdmRegistrationDescription = "AdmRegistrationDescription";
|
||||
public const string AdmTemplateRegistrationDescription = "AdmTemplateRegistrationDescription";
|
||||
public const string BrowserRegistrationDescription = "BrowserRegistrationDescription";
|
||||
public const string BrowserTemplateRegistrationDescription = "BrowserTemplateRegistrationDescription";
|
||||
public const string PnsCredential = "PnsCredential";
|
||||
public const string PnsCredentials = "PnsCredentials";
|
||||
public const string GcmCredential = "GcmCredential";
|
||||
|
@ -50,12 +52,16 @@ namespace Microsoft.Azure.NotificationHubs.Messaging
|
|||
public const string WnsCredential = "WnsCredential";
|
||||
public const string ApnsCredential = "ApnsCredential";
|
||||
public const string AdmCredential = "AdmCredential";
|
||||
public const string BrowserCredential = "BrowserCredential";
|
||||
public const string GcmRegistrationId = "GcmRegistrationId";
|
||||
public const string FcmRegistrationId = "FcmRegistrationId";
|
||||
public const string FcmV1RegistrationId = "FcmV1RegistrationId";
|
||||
public const string BaiduUserId = "BaiduUserId";
|
||||
public const string BaiduChannelId = "BaiduChannelId";
|
||||
public const string MpnsCredential = "MpnsCredential";
|
||||
public const string BrowserEndpoint = "Endpoint";
|
||||
public const string BrowserP256DH = "P256DH";
|
||||
public const string BrowserAuth = "Auth";
|
||||
public const string MpnsHeaders = "MpnsHeaders";
|
||||
public const string ApnsHeaders = "ApnsHeaders";
|
||||
public const string MpnsHeader = "MpnsHeader";
|
||||
|
@ -105,6 +111,7 @@ namespace Microsoft.Azure.NotificationHubs.Messaging
|
|||
public const string FcmV1OutcomeCounts = "FcmV1OutcomeCounts";
|
||||
public const string AdmOutcomeCounts = "AdmOutcomeCounts";
|
||||
public const string BaiduOutcomeCounts = "BaiduOutcomeCounts";
|
||||
public const string BrowserOutcomeCounts = "BrowserOutcomeCounts";
|
||||
public const string NotificationBody = "NotificationBody";
|
||||
|
||||
public const string NotificationOutcomeCollection = "NotificationOutcomeCollection";
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -413,6 +413,20 @@ namespace Microsoft.Azure.NotificationHubs
|
|||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the browser credential.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// The browser credential.
|
||||
/// </returns>
|
||||
[DataMember(Name = ManagementStrings.BrowserCredential, IsRequired = false, EmitDefaultValue = false, Order = 1018)]
|
||||
public BrowserCredential BrowserCredential
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets/Sets any User Metadata associated with the NotificationHub.
|
||||
/// </summary>
|
||||
|
|
|
@ -57,6 +57,12 @@ namespace Microsoft.Azure.NotificationHubs
|
|||
[EnumMember(Value = "baidu")]
|
||||
Baidu=6,
|
||||
|
||||
/// <summary>
|
||||
/// Browser Installation Platform
|
||||
/// </summary>
|
||||
[EnumMember(Value = "browser")]
|
||||
Browser=8,
|
||||
|
||||
/// <summary>
|
||||
/// FCM V1 Installation Platform
|
||||
/// </summary>
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace Microsoft.Azure.NotificationHubs
|
|||
[KnownType(typeof(WnsCredential))]
|
||||
[KnownType(typeof(AdmCredential))]
|
||||
[KnownType(typeof(FcmV1Credential))]
|
||||
[KnownType(typeof(BrowserCredential))]
|
||||
public abstract class PnsCredential : EntityDescription
|
||||
{
|
||||
internal PnsCredential()
|
||||
|
|
|
@ -456,6 +456,42 @@ namespace Microsoft.Azure.NotificationHubs {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Subject, VapidPublicKey, and VapidPrivateKey are required..
|
||||
/// </summary>
|
||||
internal static string BrowserRequiredProperties {
|
||||
get {
|
||||
return ResourceManager.GetString("BrowserRequiredProperties", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Subject is either not specified or invalid..
|
||||
/// </summary>
|
||||
internal static string BrowserSubjectNotSpecified {
|
||||
get {
|
||||
return ResourceManager.GetString("BrowserSubjectNotSpecified", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to VAPID private key is either not specified or invalid..
|
||||
/// </summary>
|
||||
internal static string BrowserVapidPrivateKeyNotSpecified {
|
||||
get {
|
||||
return ResourceManager.GetString("BrowserVapidPrivateKeyNotSpecified", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to VAPID public key is either not specified or invalid..
|
||||
/// </summary>
|
||||
internal static string BrowserVapidPublicKeyNotSpecified {
|
||||
get {
|
||||
return ResourceManager.GetString("BrowserVapidPublicKeyNotSpecified", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The buffer has already been reclaimed..
|
||||
/// </summary>
|
||||
|
|
|
@ -1309,4 +1309,16 @@
|
|||
<data name="FcmV1RequiredProperties" xml:space="preserve">
|
||||
<value>PrivateKey, ProjectId, and ClientEmail are required.</value>
|
||||
</data>
|
||||
<data name="BrowserRequiredProperties" xml:space="preserve">
|
||||
<value>Subject, VapidPublicKey, and VapidPrivateKey are required.</value>
|
||||
</data>
|
||||
<data name="BrowserSubjectNotSpecified" xml:space="preserve">
|
||||
<value>Subject is either not specified or invalid.</value>
|
||||
</data>
|
||||
<data name="BrowserVapidPrivateKeyNotSpecified" xml:space="preserve">
|
||||
<value>VAPID private key is either not specified or invalid.</value>
|
||||
</data>
|
||||
<data name="BrowserVapidPublicKeyNotSpecified" xml:space="preserve">
|
||||
<value>VAPID public key is either not specified or invalid.</value>
|
||||
</data>
|
||||
</root>
|
Загрузка…
Ссылка в новой задаче