public static void TestWebPubSubTrigger(
     [WebPubSubTrigger("chat", WebPubSubEventType.System, "connect")] ConnectEventRequest request,
     WebPubSubConnectionContext connectionContext)
 {
     // Valid case use default url for verification.
     Assert.AreEqual(TestContext, connectionContext);
 }
        public void TestWebPubSubContext_UserEventStates_CollectionsInSync()
        {
            var states =
                new Dictionary <string, object>
            {
                { "aKey", "aValue" },
                { "bKey", 123 },
                { "cKey", new StateTestClass() }
            }
            .EncodeConnectionStates()
            .DecodeConnectionStates()
            .ToDictionary(p => p.Key, p => (BinaryData)p.Value);
            var ctx = new WebPubSubConnectionContext(
                eventType: WebPubSubEventType.System,
                eventName: "connected",
                hub: null,
                connectionId: "connectionId",
                userId: "userA",
                connectionStates: states);

            CollectionAssert.AreEquivalent(ctx.ConnectionStates.Keys, ctx.States.Keys);
            Assert.AreEqual(ctx.ConnectionStates["aKey"].ToString(), ctx.States["aKey"]);
            Assert.AreEqual(ctx.ConnectionStates["bKey"].ToString(), ctx.States["bKey"]);
            Assert.AreEqual(ctx.ConnectionStates["cKey"].ToString(), ctx.States["cKey"]);
        }
        internal static bool IsValidSignature(this WebPubSubConnectionContext connectionContext, WebPubSubValidationOptions options)
        {
            // no options skip validation.
            if (options == null || !options.ContainsHost())
            {
                return(true);
            }

            if (options.TryGetKey(connectionContext.Origin, out var accessKey))
            {
                // server side disable signature checks.
                if (string.IsNullOrEmpty(accessKey))
                {
                    return(true);
                }

                var signatures = connectionContext.Signature.ToHeaderList();
                if (signatures == null)
                {
                    return(false);
                }
                using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(accessKey));
                var hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(connectionContext.ConnectionId));
                var hash      = "sha256=" + BitConverter.ToString(hashBytes).Replace("-", "");
                if (signatures.Contains(hash, StringComparer.OrdinalIgnoreCase))
                {
                    return(true);
                }
            }
            return(false);
        }
        private static bool TryParseCloudEvents(this HttpRequest request, out WebPubSubConnectionContext connectionContext)
        {
            try
            {
                var connectionId = request.Headers.GetFirstHeaderValueOrDefault(Constants.Headers.CloudEvents.ConnectionId);
                var hub          = request.Headers.GetFirstHeaderValueOrDefault(Constants.Headers.CloudEvents.Hub);
                var eventType    = GetEventType(request.Headers.GetFirstHeaderValueOrDefault(Constants.Headers.CloudEvents.Type));
                var eventName    = request.Headers.GetFirstHeaderValueOrDefault(Constants.Headers.CloudEvents.EventName);
                var signature    = request.Headers.GetFirstHeaderValueOrDefault(Constants.Headers.CloudEvents.Signature);
                var origin       = request.Headers.GetFirstHeaderValueOrDefault(Constants.Headers.WebHookRequestOrigin);
                var headers      = request.Headers.ToDictionary(x => x.Key, v => v.Value.ToArray(), StringComparer.OrdinalIgnoreCase);

                string userId = null;
                // UserId is optional, e.g. connect
                if (request.Headers.ContainsKey(Constants.Headers.CloudEvents.UserId))
                {
                    userId = request.Headers.GetFirstHeaderValueOrDefault(Constants.Headers.CloudEvents.UserId);
                }

                Dictionary <string, BinaryData> states = null;
                // connection states.
                if (request.Headers.ContainsKey(Constants.Headers.CloudEvents.State))
                {
                    states = request.Headers.GetFirstHeaderValueOrDefault(Constants.Headers.CloudEvents.State).DecodeConnectionStates();
                }

                connectionContext = new WebPubSubConnectionContext(eventType, eventName, hub, connectionId, userId, signature, origin, states, headers);
                return(true);
            }
            catch
            {
                connectionContext = null;
                return(false);
            }
        }
        internal static Dictionary <string, object> UpdateStates(this WebPubSubConnectionContext connectionContext, IReadOnlyDictionary <string, BinaryData> newStates)
        {
            // states cleared.
            if (newStates == null)
            {
                return(null);
            }

            if (connectionContext.ConnectionStates?.Count > 0 || newStates.Count > 0)
            {
                var states = new Dictionary <string, object>();
                if (connectionContext.ConnectionStates?.Count > 0)
                {
                    foreach (var state in connectionContext.ConnectionStates)
                    {
                        states.Add(state.Key, state.Value);
                    }
                }

                // response states keep empty is no change.
                if (newStates.Count == 0)
                {
                    return(states);
                }
                foreach (var item in newStates)
                {
                    states[item.Key] = item.Value;
                }
                return(states);
            }

            return(null);
        }
        public void TestUpdateConnectionState()
        {
            var exist = new Dictionary <string, BinaryData>
            {
                { "aaa", BinaryData.FromObjectAsJson("aaa") },
                { "bbb", BinaryData.FromObjectAsJson("bbb") }
            };
            var connectionContext = new WebPubSubConnectionContext(eventType: WebPubSubEventType.System, null, null, null, connectionStates: exist);

            var response = new ConnectEventResponse
            {
                UserId = "aaa"
            };

            response.SetState("test", BinaryData.FromObjectAsJson("ddd"));
            response.SetState("bbb", BinaryData.FromObjectAsJson("bbb1"));
            var updated = connectionContext.UpdateStates(response.ConnectionStates);

            // new
            Assert.AreEqual("ddd", updated["test"].ToObjectFromJson <string>());
            // no change
            Assert.AreEqual("aaa", updated["aaa"].ToObjectFromJson <string>());
            // update
            Assert.AreEqual("bbb1", updated["bbb"].ToObjectFromJson <string>());

            response.ClearStates();
            updated = connectionContext.UpdateStates(response.ConnectionStates);

            // After clear is null.
            Assert.IsNull(updated);
        }
        public void TestWebPubSubContext_UserEventStates_AllBinaryData()
        {
            var ctx = new WebPubSubConnectionContext(
                eventType: WebPubSubEventType.System,
                eventName: "connected",
                hub: null,
                connectionId: "connectionId",
                userId: "userA",
                signature: null,
                origin: null,
                states: new Dictionary <string, object>
            {
                { "aKey", "aValue" },
                { "bKey", 123 },
                { "cKey", new StateTestClass(DateTime.Now, "Test", 42) }
            },
                headers: null);

            Assert.IsInstanceOf <BinaryData>(ctx.ConnectionStates["aKey"]);
            Assert.IsInstanceOf <string>(ctx.States["aKey"]);
            Assert.AreEqual("aValue", ctx.ConnectionStates["aKey"].ToObjectFromJson <string>());
            Assert.AreEqual("\"aValue\"", ctx.States["aKey"]);

            Assert.IsInstanceOf <BinaryData>(ctx.ConnectionStates["bKey"]);
            Assert.IsInstanceOf <string>(ctx.States["bKey"]);
            Assert.AreEqual(123, ctx.ConnectionStates["bKey"].ToObjectFromJson <int>());
            Assert.AreEqual("123", ctx.States["bKey"]);

            Assert.IsInstanceOf <BinaryData>(ctx.ConnectionStates["cKey"]);
            Assert.IsInstanceOf <string>(ctx.States["cKey"]);
            Assert.AreEqual(42, ctx.ConnectionStates["cKey"].ToObjectFromJson <StateTestClass>().Version);
            StringAssert.StartsWith("{", (string)ctx.States["cKey"]);
        }
        public void TestSignatureCheck_SignatureNullFail()
        {
            var connectionContext = new WebPubSubConnectionContext(
                WebPubSubEventType.System,
                null, null, "0f9c97a2f0bf4706afe87a14e0797b11",
                origin: TestUri.Host);
            var options = new WebPubSubValidationOptions($"Endpoint={TestUri};AccessKey=7aab239577fd4f24bc919802fb629f5f;Version=1.0;");
            var result  = connectionContext.IsValidSignature(options);

            Assert.False(result);
        }
        public void TestSignatureCheck_OptionsEmptySuccess()
        {
            var connectionContext = new WebPubSubConnectionContext(
                WebPubSubEventType.System,
                null, null, "0f9c97a2f0bf4706afe87a14e0797b11",
                signature: "sha256=7767effcb3946f3e1de039df4b986ef02c110b1469d02c0a06f41b3b727ab561",
                origin: TestUri.Host);
            var result = connectionContext.IsValidSignature(null);

            Assert.True(result);
        }
        public void TestSignatureCheck(string accessKey, bool valid)
        {
            var connectionContext = new WebPubSubConnectionContext(
                WebPubSubEventType.System,
                null, null, "0f9c97a2f0bf4706afe87a14e0797b11",
                signature: "sha256=7767effcb3946f3e1de039df4b986ef02c110b1469d02c0a06f41b3b727ab561",
                origin: TestUri.Host);
            var options = new WebPubSubValidationOptions($"Endpoint={TestUri};AccessKey={accessKey};Version=1.0;");
            var result  = connectionContext.IsValidSignature(options);

            Assert.AreEqual(valid, result);
        }
        public void TestUserEventRequestSerialize()
        {
            var connectionContext = new WebPubSubConnectionContext(
                WebPubSubEventType.System,
                null, null, "0f9c97a2f0bf4706afe87a14e0797b11",
                signature: "sha256=7767effcb3946f3e1de039df4b986ef02c110b1469d02c0a06f41b3b727ab561",
                origin: TestUri.Host);

            var request = new UserEventRequest(connectionContext, BinaryData.FromString("Hello World"), WebPubSubDataType.Text);

            var serialized = JsonSerializer.Serialize(request);
        }
        public void TestWebPubSubContext_ConnectedEvent()
        {
            var context = new WebPubSubConnectionContext(connectionId: "connectionId", userId: "userA", eventName: "connected", eventType: WebPubSubEventType.System, hub: null);
            var test    = new WebPubSubContext(new ConnectedEventRequest(context));

            var serialize = JObject.FromObject(test);

            Assert.NotNull(serialize["request"]);
            Assert.NotNull(serialize["response"]);
            Assert.AreEqual("", serialize["errorMessage"].ToString());
            Assert.AreEqual("False", serialize["hasError"].ToString());
            Assert.AreEqual("False", serialize["isPreflight"].ToString());
        }
        private static HttpResponseMessage BuildResponse(string input, RequestType requestType, bool hasTestStates = false)
        {
            Dictionary <string, object> states = null;

            if (hasTestStates)
            {
                states =
                    new Dictionary <string, object>
                {
                    { "testKey", BinaryData.FromString("value") }
                };
            }
            var context = new WebPubSubConnectionContext(WebPubSubEventType.System, "connect", "testhub", "Connection-Id1", null, null, null, states, null);

            return(Utilities.BuildValidResponse(JToken.Parse(input), requestType, context));
        }
        public void TestWebPubSubContext_UserEventStates_Legacy()
        {
            var states =
                new Dictionary <string, object>
            {
                { "aKey", "aValue" },
                { "bKey", 123 },
                { "cKey", new StateTestClass() }
            };

            // Use the Dictionary<string, object> states .ctor overload
            var context = new WebPubSubConnectionContext(
                WebPubSubEventType.System,
                "connected",
                "hub",
                "connectionId",
                "userA",
                null,
                null,
                states,
                null);
            var test = new WebPubSubContext(new UserEventRequest(context, BinaryData.FromString("test"), WebPubSubDataType.Text));

            var jObj    = JObject.FromObject(test);
            var request = jObj["request"];

            Assert.NotNull(request);
            Assert.AreEqual("test", request["data"].ToString());
            Assert.NotNull(jObj["response"]);
            Assert.AreEqual("", jObj["errorMessage"].ToString());
            Assert.AreEqual("False", jObj["hasError"].ToString());
            Assert.AreEqual("False", jObj["isPreflight"].ToString());

            var context1 = request["connectionContext"];

            Assert.NotNull(context1);
            var states1 = context1["states"];

            Assert.NotNull(states1);
            Assert.AreEqual("\"aValue\"", states1["aKey"].Value <string>());
            Assert.NotNull(states1);
            Assert.AreEqual(123, states1["bKey"].Value <int>());
        }
        public void TestWebPubSubContext_UserEventStates()
        {
            var states =
                new Dictionary <string, object>
            {
                { "aKey", "aValue" },
                { "bKey", 123 },
                { "cKey", new StateTestClass() }
            }.EncodeConnectionStates().DecodeConnectionStates().ToDictionary(p => p.Key, p => (BinaryData)p.Value);

            // Use the Dictionary<string, BinaryData> connectionStates .ctor overload
            var context = new WebPubSubConnectionContext(
                eventType: WebPubSubEventType.System,
                eventName: "connected",
                hub: null,
                connectionId: "connectionId",
                userId: "userA",
                connectionStates: states);
            var test = new WebPubSubContext(new UserEventRequest(context, BinaryData.FromString("test"), WebPubSubDataType.Text));

            var jObj    = JObject.Parse(JsonConvert.SerializeObject(test));
            var request = jObj["request"];

            Assert.NotNull(request);
            Assert.AreEqual("test", request["data"].Value <string>());
            Assert.NotNull(jObj["response"]);
            Assert.AreEqual(null, jObj["errorMessage"].Value <string>());
            Assert.AreEqual("False", jObj["hasError"].Value <string>());
            Assert.AreEqual("False", jObj["isPreflight"].Value <string>());
            var context1 = request["connectionContext"];

            Assert.NotNull(context1);
            var states1 = context1["states"];

            Assert.NotNull(states1);
            Assert.AreEqual("aValue", states1["aKey"].Value <string>());
            Assert.AreEqual(123, states1["bKey"].Value <int>());
            var classStates = states1["cKey"];

            Assert.NotNull(classStates);
            Assert.AreEqual("GA", classStates["Title"].Value <string>());
        }
 private static RequestType GetRequestType(this WebPubSubConnectionContext context)
 {
     if (context.EventType == WebPubSubEventType.User)
     {
         return(RequestType.User);
     }
     if (context.EventName.Equals(Constants.Events.ConnectEvent, StringComparison.OrdinalIgnoreCase))
     {
         return(RequestType.Connect);
     }
     if (context.EventName.Equals(Constants.Events.DisconnectedEvent, StringComparison.OrdinalIgnoreCase))
     {
         return(RequestType.Disconnected);
     }
     if (context.EventName.Equals(Constants.Events.ConnectedEvent, StringComparison.OrdinalIgnoreCase))
     {
         return(RequestType.Connected);
     }
     return(RequestType.Ignored);
 }
        public void TestWebPubSubContext_ConnectEvent()
        {
            var context = new WebPubSubConnectionContext(connectionId: "connectionId", userId: "userA", eventName: "connected", eventType: WebPubSubEventType.System, hub: null);

            var claims = new Dictionary <string, string[]>
            {
                { "aa", new string[] { "aa1, aa2" } },
                { "bb", new string[] { "bb, bb2" } },
            };
            var subprotocol = new string[] { "sub1", "sub2" };
            var test        = new WebPubSubContext(new ConnectEventRequest(context, claims, null, subprotocol, null));

            var serialize = JObject.FromObject(test);
            var request   = serialize["request"];

            Assert.NotNull(request);
            Assert.AreEqual(subprotocol, request["subprotocols"].ToObject <string[]>());
            Assert.NotNull(serialize["response"]);
            Assert.AreEqual("", serialize["errorMessage"].ToString());
            Assert.AreEqual("False", serialize["hasError"].ToString());
            Assert.AreEqual("False", serialize["isPreflight"].ToString());
        }
        public void TestConnectEventRequestSerialize()
        {
            var connectionContext = new WebPubSubConnectionContext(
                WebPubSubEventType.System,
                null, null, "0f9c97a2f0bf4706afe87a14e0797b11",
                signature: "sha256=7767effcb3946f3e1de039df4b986ef02c110b1469d02c0a06f41b3b727ab561",
                origin: TestUri.Host);

            var claims = new Dictionary <string, string[]>
            {
                { "aaa", new string[] { "a1", "a2" } },
                { "bbb", new string[] { "b1", "b2" } },
                { "ccc", new string[] { "c1", "c2" } },
            };
            var query = new Dictionary <string, string[]>
            {
                { "query1", new string[] { "a1", "a2" } },
                { "query2", new string[] { "b1" } },
            };
            var certs = new List <WebPubSubClientCertificate>
            {
                new WebPubSubClientCertificate("111"),
                new WebPubSubClientCertificate("222")
            };
            var request = new ConnectEventRequest(connectionContext, claims, query, new string[] { "protocol1", "protocol2" }, certs);

            var serilized = JsonSerializer.Serialize(request);

            var converted = JsonSerializer.Deserialize <ConnectEventRequest>(serilized);

            Assert.AreEqual(3, converted.Claims.Count);
            Assert.AreEqual(2, converted.Query.Count);
            Assert.AreEqual(2, converted.Subprotocols.Count);
            Assert.AreEqual(new string[] { "protocol1", "protocol2" }, converted.Subprotocols);
            Assert.NotNull(converted.ClientCertificates);
            Assert.AreEqual(2, converted.ClientCertificates.Count);
        }
 /// <summary>
 /// The connected event request
 /// </summary>
 /// <param name="context"></param>
 public ConnectedEventRequest(WebPubSubConnectionContext context)
     : base(context)
 {
 }
Exemple #20
0
 public static void Func2([WebPubSubTrigger("testchat", WebPubSubEventType.User, "message")] WebPubSubConnectionContext connectionContext, BinaryData data, WebPubSubDataType dataType)
 {
 }
Exemple #21
0
 public static void TestFunc(
     [WebPubSubTrigger("%testhub%", WebPubSubEventType.System, "testevent")] WebPubSubConnectionContext context)
 {
 }
Exemple #22
0
 public static void Func1([WebPubSubTrigger("testchat", WebPubSubEventType.System, "connect")] WebPubSubConnectionContext connectionContext)
 {
 }