diff --git a/src/stream-net-tests/IntegrationTests.cs b/src/stream-net-tests/IntegrationTests.cs index c207d56..ecb0351 100644 --- a/src/stream-net-tests/IntegrationTests.cs +++ b/src/stream-net-tests/IntegrationTests.cs @@ -1225,11 +1225,8 @@ public async Task TestAggregate() var response = await _user1.AddActivity(newActivity1); response = await _user1.AddActivity(newActivity2); - - await _agg4.FollowFeed(this._user1); - var activities = await this._agg4.GetActivities(0); Assert.IsNotNull(activities); Assert.AreEqual(1, activities.Count()); diff --git a/src/stream-net-tests/SigningTest.cs b/src/stream-net-tests/SigningTest.cs deleted file mode 100644 index 83cac13..0000000 --- a/src/stream-net-tests/SigningTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using NUnit.Framework; -using Stream; - -namespace stream_net_tests -{ - [Parallelizable(ParallelScope.Self)] - [TestFixture] - public class SigningTest - { - [Test] - public void TokenIsValid() - { - var client = new StreamClient("key", "gthc2t9gh7pzq52f6cky8w4r4up9dr6rju9w3fjgmkv6cdvvav2ufe5fv7e2r9qy"); - - var feed = client.Feed("flat", "1"); - - Assert.AreEqual("iFX1l5f_lIUWgZFBnv5UisTTW18", feed.Token); - } - - [Test] - public void ReadOnlyTokenIsValid() - { - var client = new StreamClient("key", "gthc2t9gh7pzq52f6cky8w4r4up9dr6rju9w3fjgmkv6cdvvav2ufe5fv7e2r9qy"); - - var feed = client.Feed("flat", "1"); - var token = feed.ReadOnlyToken; - Assert.AreEqual("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyZXNvdXJjZSI6IioiLCJhY3Rpb24iOiIqIiwiZmVlZF9pZCI6ImZsYXQxIn0.7435I3bhISLU2RdVeVVMtmjhLE7LPHvDgqQ6mnfFwhU", token); - } - } -} diff --git a/src/stream-net/Activity.cs b/src/stream-net/Activity.cs index 6cb5033..9a16b90 100644 --- a/src/stream-net/Activity.cs +++ b/src/stream-net/Activity.cs @@ -132,7 +132,7 @@ internal JObject ToJObject(StreamClient client) if (To.SafeCount() > 0) { JArray toArray = new JArray(); - (from t in To select client.SignTo(t)).ForEach((st) => + To.ForEach((st) => { toArray.Add(st); }); diff --git a/src/stream-net/BatchOperations.cs b/src/stream-net/BatchOperations.cs index fe7955d..1e3cd66 100644 --- a/src/stream-net/BatchOperations.cs +++ b/src/stream-net/BatchOperations.cs @@ -76,7 +76,6 @@ public async Task AddToMany(Activity activity, IEnumerable feedIds) request.SetJsonBody( "{" + string.Format("\"activity\": {0}, \"feeds\": {1}", activity.ToJson(this._client), JsonConvert.SerializeObject(feedIds)) + "}" ); - _client.SignRequest(request); var response = await _client.MakeRequest(request); @@ -101,8 +100,6 @@ public async Task FollowMany(IEnumerable follows, int activityCopyLimit target = f.Target })); - _client.SignRequest(request); - var response = await _client.MakeRequest(request); if (response.StatusCode != System.Net.HttpStatusCode.Created) @@ -116,7 +113,7 @@ public async Task> GetActivities(IEnumerable ids = if (ids != null && foreignIDTimes != null) throw new ArgumentException("at most one of the parameters ids or foreignIdTimes must be provided", "ids, foreignIDTimes"); - var request = _client.BuildJWTAppRequest("activities/", HttpMethod.GET); + var request = _client.BuildAppRequest("activities/", HttpMethod.GET); if (ids != null) { @@ -140,7 +137,7 @@ public async Task> GetActivities(IEnumerable ids = public async Task UpdateActivities(IEnumerable activities) { - var request = _client.BuildJWTAppRequest("activities/", HttpMethod.POST); + var request = _client.BuildAppRequest("activities/", HttpMethod.POST); request.SetJsonBody(Activity.ToActivitiesJson(activities, this._client)); var response = await this._client.MakeRequest(request); @@ -151,7 +148,7 @@ public async Task UpdateActivities(IEnumerable activities) public async Task ActivitiesPartialUpdate(IEnumerable updates) { - var request = this._client.BuildJWTAppRequest("activity/", HttpMethod.POST); + var request = this._client.BuildAppRequest("activity/", HttpMethod.POST); var requestData = new Dictionary(){ {"changes", updates.Select(x => x.ToJObject())} diff --git a/src/stream-net/Collections.cs b/src/stream-net/Collections.cs index d89a1fd..553bcc7 100644 --- a/src/stream-net/Collections.cs +++ b/src/stream-net/Collections.cs @@ -129,7 +129,7 @@ public async Task UpsertMany(string collectionName, IEnumerable x.ToJObject()))))); - var request = this._client.BuildJWTAppRequest("collections/", HttpMethod.POST); + var request = this._client.BuildAppRequest("collections/", HttpMethod.POST); request.SetJsonBody(dataJson.ToString()); var response = await this._client.MakeRequest(request); @@ -148,7 +148,7 @@ public async Task> SelectMany(string collectionNam { var foreignIds = ids.Select(x => string.Format("{0}:{1}", collectionName, x)); - var request = this._client.BuildJWTAppRequest("collections/", HttpMethod.GET); + var request = this._client.BuildAppRequest("collections/", HttpMethod.GET); request.AddQueryParameter("foreign_ids", string.Join(",", foreignIds)); var response = await this._client.MakeRequest(request); @@ -161,7 +161,7 @@ public async Task> SelectMany(string collectionNam public async Task DeleteMany(string collectionName, IEnumerable ids) { - var request = this._client.BuildJWTAppRequest("collections/", HttpMethod.DELETE); + var request = this._client.BuildAppRequest("collections/", HttpMethod.DELETE); request.AddQueryParameter("collection_name", collectionName); request.AddQueryParameter("ids", string.Join(",", ids)); @@ -180,7 +180,7 @@ public async Task Add(string collectionName, GenericData data, _data = data, }; - var request = this._client.BuildJWTAppRequest($"collections/{collectionName}/", HttpMethod.POST); + var request = this._client.BuildAppRequest($"collections/{collectionName}/", HttpMethod.POST); request.SetJsonBody(collectionObject.ToJson()); var response = await this._client.MakeRequest(request); @@ -193,7 +193,7 @@ public async Task Add(string collectionName, GenericData data, public async Task Get(string collectionName, string ID) { - var request = this._client.BuildJWTAppRequest($"collections/{collectionName}/{ID}/", HttpMethod.GET); + var request = this._client.BuildAppRequest($"collections/{collectionName}/{ID}/", HttpMethod.GET); var response = await this._client.MakeRequest(request); @@ -206,7 +206,7 @@ public async Task Get(string collectionName, string ID) public async Task Update(string collectionName, string ID, GenericData data) { var dataJson = new JObject(new JProperty("data", data.ToJObject())); - var request = this._client.BuildJWTAppRequest($"collections/{collectionName}/{ID}/", HttpMethod.PUT); + var request = this._client.BuildAppRequest($"collections/{collectionName}/{ID}/", HttpMethod.PUT); request.SetJsonBody(dataJson.ToString()); var response = await this._client.MakeRequest(request); @@ -219,7 +219,7 @@ public async Task Update(string collectionName, string ID, Gen public async Task Delete(string collectionName, string ID) { - var request = this._client.BuildJWTAppRequest($"collections/{collectionName}/{ID}/", HttpMethod.DELETE); + var request = this._client.BuildAppRequest($"collections/{collectionName}/{ID}/", HttpMethod.DELETE); var response = await this._client.MakeRequest(request); diff --git a/src/stream-net/IStreamClient.cs b/src/stream-net/IStreamClient.cs index ab95e7c..0efd4d8 100644 --- a/src/stream-net/IStreamClient.cs +++ b/src/stream-net/IStreamClient.cs @@ -9,6 +9,7 @@ public interface IStreamClient Collections Collections { get; } Reactions Reactions { get; } Users Users { get; } + Personalization Personalization { get; } Task ActivityPartialUpdate(string id = null, ForeignIDTime foreignIDTime = null, GenericData set = null, IEnumerable unset = null); IStreamFeed Feed(string feedSlug, string userId); diff --git a/src/stream-net/IStreamFeed.cs b/src/stream-net/IStreamFeed.cs index 139e0f9..4137282 100644 --- a/src/stream-net/IStreamFeed.cs +++ b/src/stream-net/IStreamFeed.cs @@ -6,9 +6,8 @@ namespace Stream public interface IStreamFeed { string FeedId { get; } - string ReadOnlyToken { get; } - string Token { get; } string UrlPath { get; } + string EnrichedPath { get; } Task> AddActivities(IEnumerable activities); Task AddActivity(Activity activity); diff --git a/src/stream-net/Reactions.cs b/src/stream-net/Reactions.cs index 5a48675..c5fb025 100644 --- a/src/stream-net/Reactions.cs +++ b/src/stream-net/Reactions.cs @@ -13,7 +13,7 @@ public class ReactionsWithActivity { [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "results")] public IEnumerable Reactions { get; internal set; } - + public EnrichedActivity Activity { get; internal set; } } @@ -73,7 +73,7 @@ public ReactionFiltering WithFilter(ReactionFilter filter) } internal ReactionFiltering WithActivityData() - { + { _filter = (_filter == null) ? ReactionFilter.Where().WithActivityData() : _filter.WithActivityData(); return this; @@ -178,7 +178,7 @@ internal static EnrichedActivity GetActivity(string json) return null; } - } + } internal Reactions(StreamClient client) { @@ -217,7 +217,7 @@ public async Task AddChild(Reaction parent, string kind, string userID public async Task Get(string reactionID) { - var request = this._client.BuildJWTAppRequest($"reaction/{reactionID}/", HttpMethod.GET); + var request = this._client.BuildAppRequest($"reaction/{reactionID}/", HttpMethod.GET); var response = await this._client.MakeRequest(request); @@ -228,11 +228,11 @@ public async Task Get(string reactionID) } public async Task> Filter(ReactionFiltering filtering, ReactionPagination pagination) - { + { var response = await FilterHelper(filtering, pagination); if (response.StatusCode == System.Net.HttpStatusCode.OK) - { + { return JsonConvert.DeserializeObject(response.Content).Reactions; } @@ -240,7 +240,7 @@ public async Task> Filter(ReactionFiltering filtering, Rea } public async Task FilterWithActivityData(ReactionFiltering filtering, ReactionPagination pagination) - { + { var response = await FilterHelper(filtering.WithActivityData(), pagination); if (response.StatusCode == System.Net.HttpStatusCode.OK) @@ -261,9 +261,9 @@ public async Task FilterWithActivityData(ReactionFilterin private async Task FilterHelper(ReactionFiltering filtering, ReactionPagination pagination) { var urlPath = pagination.GetPath(); - var request = this._client.BuildJWTAppRequest($"reaction/{urlPath}", HttpMethod.GET); + var request = this._client.BuildAppRequest($"reaction/{urlPath}", HttpMethod.GET); filtering.Apply(request); - + var response = await this._client.MakeRequest(request); return response; @@ -278,7 +278,7 @@ public async Task Update(string reactionID, IDictionary Update(string reactionID, IDictionary Add(Reaction r) { - var request = this._client.BuildJWTAppRequest("reaction/", HttpMethod.POST); + var request = this._client.BuildAppRequest("reaction/", HttpMethod.POST); request.SetJsonBody(JsonConvert.SerializeObject(r)); var response = await this._client.MakeRequest(request); diff --git a/src/stream-net/StreamClient.cs b/src/stream-net/StreamClient.cs index 1f1e53b..da1ce9e 100644 --- a/src/stream-net/StreamClient.cs +++ b/src/stream-net/StreamClient.cs @@ -71,8 +71,7 @@ public IStreamFeed Feed(string feedSlug, string userId) if (string.IsNullOrWhiteSpace(userId)) throw new ArgumentNullException("userId", "Must have an userId"); - string token = Sign(feedSlug + userId); - return new StreamFeed(this, feedSlug, userId, token); + return new StreamFeed(this, feedSlug, userId); } public async Task ActivityPartialUpdate(string id = null, ForeignIDTime foreignIDTime = null, GenericData set = null, IEnumerable unset = null) @@ -200,16 +199,9 @@ internal RestRequest BuildActivitiesRequest(StreamFeed feed) return BuildRestRequest(BaseUrlPath + ActivitiesUrlPath, HttpMethod.POST); } - internal RestRequest BuildJWTAppRequest(string path, HttpMethod method) - { - return BuildRestRequest(BaseUrlPath + path, method); - } - internal RestRequest BuildAppRequest(string path, HttpMethod method) { - var request = new RestRequest(BaseUrlPath + path, method); - request.AddHeader("X-Api-Key", _apiKey); - return request; + return BuildRestRequest(BaseUrlPath + path, method); } internal RestRequest BuildPersonalizationRequest(string path, HttpMethod method) @@ -217,21 +209,6 @@ internal RestRequest BuildPersonalizationRequest(string path, HttpMethod method) return BuildRestRequest(BasePersonalizationUrlPath + path, method, "*"); } - internal void SignRequest(RestRequest request) - { - // make signature - var queryString = ""; - request.QueryParameters.ForEach((p) => - { - queryString += (queryString.Length == 0) ? "?" : "&"; - queryString += string.Format("{0}={1}", p.Key, Uri.EscapeDataString(p.Value.ToString())); - }); - var toSign = string.Format("(request-target): {0} {1}", request.Method.ToString().ToLower(), request.Resource + queryString); - - var signature = string.Format("keyId=\"{0}\",algorithm=\"hmac-sha256\",headers=\"(request-target)\",signature=\"{1}\"", this._apiKey, Sign256(toSign)); - request.AddHeader("Authorization", "Signature " + signature); - } - internal Task MakeRequest(RestRequest request) { return _client.Execute(request); @@ -245,26 +222,6 @@ private static string Base64UrlEncode(byte[] input) .Trim('='); } - internal string Sign(string feedId) - { - Encoding encoding = new ASCIIEncoding(); -#if NETCORE - var hashedSecret = SHA1.Create().ComputeHash(encoding.GetBytes(_apiSecret)); -#else - var hashedSecret = (new SHA1Managed()).ComputeHash(encoding.GetBytes(_apiSecret)); -#endif - - var hmac = new HMACSHA1(hashedSecret); - return Base64UrlEncode(hmac.ComputeHash(encoding.GetBytes(feedId))); - } - - internal string Sign256(string feedId) - { - Encoding encoding = new ASCIIEncoding(); - var hmac = new HMACSHA256(encoding.GetBytes(_apiSecret)); - return Convert.ToBase64String(hmac.ComputeHash(encoding.GetBytes(feedId))); - } - internal string JWToken(string feedId, string userID = null) { var payload = new Dictionary() @@ -300,12 +257,5 @@ internal string JWToken(object payload) } return string.Join(".", segments.ToArray()); } - - internal string SignTo(string to) - { - string[] bits = to.Split(':'); - var otherFeed = this.Feed(bits[0], bits[1]); - return to + " " + otherFeed.Token; - } } } diff --git a/src/stream-net/StreamFeed.cs b/src/stream-net/StreamFeed.cs index 3930eef..3191ff2 100644 --- a/src/stream-net/StreamFeed.cs +++ b/src/stream-net/StreamFeed.cs @@ -20,24 +20,20 @@ public class StreamFeed : IStreamFeed readonly string _feedSlug; readonly string _userId; - internal StreamFeed(StreamClient client, string feedSlug, string userId, string token) + internal StreamFeed(StreamClient client, string feedSlug, string userId) { if (!_feedRegex.IsMatch(feedSlug)) throw new ArgumentException("Feed slug can only contain alphanumeric characters or underscores"); if (!_userRegex.IsMatch(userId)) throw new ArgumentException("User id can only contain alphanumeric characters, underscores or dashes"); - Token = token; _client = client; _feedSlug = feedSlug; _userId = userId; - FeedTokenId = string.Format("{0}{1}", _feedSlug, _userId); UrlPath = string.Format("feed/{0}/{1}", _feedSlug, _userId); - EnrichedPath = string.Format("enrich/{0}", UrlPath); + EnrichedPath = "enrich/" + UrlPath; } - internal string FeedTokenId { get; private set; } - public string FeedId { get @@ -46,18 +42,7 @@ public string FeedId } } - public string Token { get; private set; } - - public string ReadOnlyToken - { - get - { - return _client.JWToken(FeedTokenId); - } - } - public string UrlPath { get; private set; } - public string EnrichedPath { get; private set; } /// @@ -197,7 +182,7 @@ public async Task UpdateActivityToTargets(ForeignIDTime payload["removed_targets"] = removed.ToList(); var endpoint = string.Format("feed_targets/{0}/{1}/activity_to_targets/", this._feedSlug, this._userId); - var request = this._client.BuildJWTAppRequest(endpoint, HttpMethod.POST); + var request = this._client.BuildAppRequest(endpoint, HttpMethod.POST); request.SetJsonBody(JsonConvert.SerializeObject(payload)); var response = await this._client.MakeRequest(request); @@ -351,7 +336,6 @@ public async Task FollowFeed(IStreamFeed feedToFollow, int activityCopyLimit = S { target = feedToFollow.FeedId, activity_copy_limit = activityCopyLimit, - target_token = feedToFollow.Token })); var response = await _client.MakeRequest(request); @@ -436,7 +420,7 @@ private void ValidateFeedFollow(IStreamFeed feed) { if (feed == null) throw new ArgumentNullException("feed", "Must have a feed to follow/unfollow"); - if (((StreamFeed)feed).FeedTokenId == this.FeedTokenId) + if (((StreamFeed)feed).FeedId == this.FeedId) throw new ArgumentException("Cannot follow/unfollow myself"); } diff --git a/src/stream-net/Users.cs b/src/stream-net/Users.cs index c148928..176a465 100644 --- a/src/stream-net/Users.cs +++ b/src/stream-net/Users.cs @@ -44,7 +44,7 @@ public async Task Add(string userID, IDictionary data = nu ID = userID, Data = data, }; - var request = this._client.BuildJWTAppRequest("user/", HttpMethod.POST); + var request = this._client.BuildAppRequest("user/", HttpMethod.POST); request.SetJsonBody(JsonConvert.SerializeObject(u)); request.AddQueryParameter("get_or_create", getOrCreate.ToString()); @@ -59,7 +59,7 @@ public async Task Add(string userID, IDictionary data = nu public async Task Get(string userID) { - var request = this._client.BuildJWTAppRequest($"user/{userID}/", HttpMethod.GET); + var request = this._client.BuildAppRequest($"user/{userID}/", HttpMethod.GET); var response = await this._client.MakeRequest(request); @@ -75,7 +75,7 @@ public async Task Update(string userID, IDictionary data) { Data = data, }; - var request = this._client.BuildJWTAppRequest($"user/{userID}/", HttpMethod.PUT); + var request = this._client.BuildAppRequest($"user/{userID}/", HttpMethod.PUT); request.SetJsonBody(JsonConvert.SerializeObject(u)); var response = await this._client.MakeRequest(request); @@ -88,7 +88,7 @@ public async Task Update(string userID, IDictionary data) public async Task Delete(string userID) { - var request = this._client.BuildJWTAppRequest($"user/{userID}/", HttpMethod.DELETE); + var request = this._client.BuildAppRequest($"user/{userID}/", HttpMethod.DELETE); var response = await this._client.MakeRequest(request);