Skip to content

Commit e1a36d3

Browse files
committed
[WIP] Get a start on cleaning up PR #129. There's still some stuff to do, however.
1 parent b24eeff commit e1a36d3

File tree

6 files changed

+151
-86
lines changed

6 files changed

+151
-86
lines changed

Keen.Test/AccessKeyMock.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
using Keen.AccessKey;
21
using System;
3-
using System.Collections.Generic;
4-
using System.Linq;
5-
using System.Text;
62
using System.Threading.Tasks;
7-
using Newtonsoft.Json.Linq;
3+
using Keen.AccessKey;
84
using Keen.Core;
5+
using Newtonsoft.Json.Linq;
96

107

118
namespace Keen.Test
@@ -18,17 +15,19 @@ namespace Keen.Test
1815
/// </summary>
1916
class AccessKeysMock : IAccessKeys
2017
{
18+
// TODO : Replace AccessKeysMock with Moq as per PR feedback.
19+
2120
private readonly IProjectSettings _settings;
22-
private readonly Func<AccessKey.AccessKey, IProjectSettings, JObject> _createAccessKey;
21+
private readonly Func<AccessKeyDefinition, IProjectSettings, JObject> _createAccessKey;
2322

2423
public AccessKeysMock(IProjectSettings projSettings,
25-
Func<AccessKey.AccessKey, IProjectSettings, JObject> createAccessKey = null)
24+
Func<AccessKeyDefinition, IProjectSettings, JObject> createAccessKey = null)
2625
{
2726
_settings = projSettings;
2827
_createAccessKey = createAccessKey ?? ((p, k) => new JObject());
2928
}
3029

31-
public Task<JObject> CreateAccessKey(AccessKey.AccessKey accesskey)
30+
public Task<JObject> CreateAccessKey(AccessKeyDefinition accesskey)
3231
{
3332
return Task.Run(() => _createAccessKey(accesskey, _settings));
3433
}

Keen.Test/AccessKeyTests.cs

Lines changed: 83 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,135 @@
1-
using Keen.Core;
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
24
using Keen.AccessKey;
5+
using Keen.Core;
36
using Keen.Query;
47
using Newtonsoft.Json.Linq;
58
using NUnit.Framework;
6-
using System;
7-
using System.Collections.Generic;
8-
using System.Linq;
9-
using System.Text;
10-
using System.Threading.Tasks;
9+
1110

1211
namespace Keen.Test
1312
{
1413
[TestFixture]
1514
class AccessKeyTests : TestBase
1615
{
16+
private IProjectSettings _settings = null;
17+
private KeenClient _client = null;
18+
19+
[SetUp]
20+
public void AccessKeyTestsSetup()
21+
{
22+
_settings = new ProjectSettingsProvider(projectId: "X",
23+
masterKey: SettingsEnv.MasterKey);
24+
_client = new KeenClient(_settings);
25+
}
26+
1727
[Test]
1828
public void CreateAccessKey_Success()
1929
{
20-
var settings = new ProjectSettingsProvider(projectId: "X", masterKey: SettingsEnv.MasterKey); // Replace X with respective value
21-
var client = new KeenClient(settings);
22-
30+
// TODO : Replace AccessKeysMock with Moq as per PR feedback.
2331
if (UseMocks)
24-
client.AccessKeys = new AccessKeysMock(settings,
25-
createAccessKey: new Func<AccessKey.AccessKey, IProjectSettings, JObject>((e, p) =>
32+
_client.AccessKeys = new AccessKeysMock(_settings,
33+
createAccessKey: new Func<AccessKeyDefinition, IProjectSettings, JObject>((e, p) =>
2634
{
27-
Assert.True(p == settings, "Incorrect Settings");
35+
Assert.True(p == _settings, "Incorrect Settings");
2836
Assert.NotNull(e.Name, "Expected a name for the newly created Key");
2937
Assert.NotNull(e.Permitted, "Expected a list of high level actions this key can perform");
3038
Assert.NotNull(e.Options, "Expected an object containing more details about the key’s permitted and restricted functionality");
31-
if ((p == settings) && (e.Name == "TestAccessKey") && (e.IsActive) && e.Permitted.First() == "queries" && e.Options.CachedQueries.Allowed.First() == "my_cached_query")
39+
if ((p == _settings) && (e.Name == "TestAccessKey") && (e.IsActive) && e.Permitted.First() == "queries" && e.Options.CachedQueries.Allowed.First() == "my_cached_query")
3240
return new JObject();
3341
else
3442
throw new Exception("Unexpected value");
3543
}));
3644

37-
HashSet<string> permissions = new HashSet<string>() { "queries" };
38-
List<QueryFilter> qFilters = new List<QueryFilter>() { new QueryFilter("customer.id", QueryFilter.FilterOperator.Equals(), "asdf12345z") };
39-
CachedQueries cachedQueries = new CachedQueries();
40-
cachedQueries.Allowed = new HashSet<string>() { "my_cached_query" };
41-
Options options = new Options()
45+
var permitted = new HashSet<string>() { "queries" };
46+
47+
var filters = new List<QueryFilter>()
4248
{
43-
Queries = new AccessKey.Queries { Filters = qFilters },
49+
new QueryFilter("customer.id", QueryFilter.FilterOperator.Equals(), "asdf12345z")
50+
};
51+
52+
var cachedQueries = new CachedQueries
53+
{
54+
Allowed = new HashSet<string>() { "my_cached_query" }
55+
};
56+
57+
var options = new Options()
58+
{
59+
Queries = new AccessKey.Queries { Filters = filters },
4460
CachedQueries = cachedQueries
4561
};
4662

47-
Assert.DoesNotThrow(() => client.CreateAccessKey(new AccessKey.AccessKey { Name = "TestAccessKey", IsActive = true, Options = options, Permitted = permissions }));
48-
}
63+
var accessKey = new AccessKeyDefinition
64+
{
65+
Name = "TestAccessKey",
66+
IsActive = true,
67+
Permitted = permitted,
68+
Options = options
69+
};
4970

71+
Assert.DoesNotThrow(() => _client.CreateAccessKey(accessKey));
72+
}
5073

5174
[Test]
5275
public void CreateAccessKey_With_All_Properties_Given_As_Null_Success()
5376
{
54-
var settings = new ProjectSettingsProvider(projectId: "X", masterKey: SettingsEnv.MasterKey); // Replace X with respective value
55-
var client = new KeenClient(settings);
56-
77+
// TODO : Replace AccessKeysMock with Moq as per PR feedback.
5778
if (UseMocks)
58-
client.AccessKeys = new AccessKeysMock(settings,
59-
createAccessKey: new Func<AccessKey.AccessKey, IProjectSettings, JObject>((e, p) =>
79+
_client.AccessKeys = new AccessKeysMock(_settings,
80+
createAccessKey: new Func<AccessKeyDefinition, IProjectSettings, JObject>((e, p) =>
6081
{
61-
Assert.True(p == settings, "Incorrect Settings");
82+
Assert.True(p == _settings, "Incorrect Settings");
6283
Assert.NotNull(e.Name, "Expected a name for the newly created Key");
6384
Assert.NotNull(e.Permitted, "Expected a list of high level actions this key can perform");
6485
Assert.NotNull(e.Options, "Expected an object containing more details about the key’s permitted and restricted functionality");
65-
if ((p == settings) && (e.Name == "TestAccessKey") && (e.IsActive) && e.Permitted.First() == "queries" && e.Options.CachedQueries.Allowed.First() == "my_cached_query")
86+
if ((p == _settings) && (e.Name == "TestAccessKey") && (e.IsActive) && e.Permitted.First() == "queries")
6687
return new JObject();
6788
else
6889
throw new Exception("Unexpected value");
6990
}));
7091

71-
HashSet<string> permissions = new HashSet<string>() { "queries" };
72-
List<QueryFilter> qFilters = new List<QueryFilter>() { new QueryFilter("customer.id", QueryFilter.FilterOperator.Equals(), "asdf12345z") };
73-
CachedQueries cachedQueries = new CachedQueries() { Allowed = null, Blocked = null };
74-
SavedQueries savedQuaries = new SavedQueries() { Allowed = null, Blocked = null, Filters = null };
75-
Datasets datasets = new Datasets() { Allowed = null, Blocked = null, Operations = null };
76-
Writes writes = new Writes() { Autofill = null };
77-
cachedQueries.Allowed = new HashSet<string>() { "my_cached_query" };
78-
Options options = new Options()
92+
var permitted = new HashSet<string>() { "queries" };
93+
94+
// TODO : Can't null just be the default when we construct these? We should look at
95+
// some factories or a builder mechanism to configure these correctly, or at least add
96+
// more validation code that will throw before sending with reasons for why it's
97+
// malformed. For example, why set a SavedQueries instance if "saved_queries" isn't
98+
// permitted? We could help devs consuming the SDK catch that early.
99+
100+
var cachedQueries = new CachedQueries() { Allowed = null, Blocked = null };
101+
102+
var savedQuaries = new SavedQueries()
79103
{
80-
Queries = new AccessKey.Queries { Filters = qFilters },
104+
Allowed = null,
105+
Blocked = null,
106+
Filters = null
107+
};
108+
109+
var datasets = new Datasets() { Allowed = null, Blocked = null, Operations = null };
110+
var writes = new Writes() { Autofill = null };
111+
112+
var options = new Options()
113+
{
114+
Queries = new AccessKey.Queries { Filters = null },
81115
CachedQueries = cachedQueries,
82116
SavedQueries = savedQuaries,
83117
Datasets = datasets,
84118
Writes = writes
85119
};
86120

87-
Assert.DoesNotThrow(() => client.CreateAccessKey(new AccessKey.AccessKey { Name = "TestAccessKey", IsActive = true, Options = options, Permitted = permissions }));
88-
}
121+
// TODO : We need to more carefully test out what is required and what isn't. For
122+
// example, I thought the 'options' member could be omitted.
89123

124+
var accessKey = new AccessKeyDefinition
125+
{
126+
Name = "TestAccessKey",
127+
IsActive = true,
128+
Permitted = permitted,
129+
Options = options
130+
};
131+
132+
Assert.DoesNotThrow(() => _client.CreateAccessKey(accessKey));
133+
}
90134
}
91135
}

Keen/AccessKey/AccessKey.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55

66
namespace Keen.AccessKey
77
{
8+
// TODO : We should provide some helpers/constants/factories/builders/validation to
9+
// make it a littler easier to put together this model structure. For example, we could
10+
// easily provide an enum for 'Permitted' so that it's easy to use and self-documenting.
11+
812
/// <summary>
913
/// Model for AccessKey object
1014
/// </summary>
11-
public class AccessKey
15+
public class AccessKeyDefinition
1216
{
1317
public string Name { get; set; }
1418
public bool IsActive { get; set; }
@@ -58,7 +62,7 @@ public class Datasets
5862
/// </summary>
5963
public class AllowedDatasetIndexes
6064
{
61-
public Tuple<string, string> IndexBy { get; set;}
65+
public Tuple<string, string> IndexBy { get; set; }
6266
}
6367

6468
/// <summary>

Keen/AccessKey/AccessKeys.cs

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,30 @@
99
namespace Keen.AccessKey
1010
{
1111
/// <summary>
12-
/// AccessKeys implements the IAccessKeys interface which represents the Keen.IO Access Key API methods.
12+
/// AccessKeys implements the IAccessKeys interface which represents the Keen.IO Access
13+
/// Key API methods.
1314
/// </summary>
1415
public class AccessKeys : IAccessKeys
1516
{
17+
private static readonly JsonSerializerSettings SerializerSettings =
18+
new JsonSerializerSettings
19+
{
20+
ContractResolver = new DefaultContractResolver
21+
{
22+
NamingStrategy = new SnakeCaseNamingStrategy()
23+
},
24+
DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate,
25+
Formatting = Formatting.None
26+
};
27+
1628
private readonly IKeenHttpClient _keenHttpClient;
17-
private readonly string _accesKeyRelativeUrl;
29+
private readonly string _accessKeyRelativeUrl;
1830
private readonly string _readKey;
1931
private readonly string _masterKey;
2032

33+
2134
internal AccessKeys(IProjectSettings prjSettings,
22-
IKeenHttpClientProvider keenHttpClientProvider)
35+
IKeenHttpClientProvider keenHttpClientProvider)
2336
{
2437
if (null == prjSettings)
2538
{
@@ -42,33 +55,29 @@ internal AccessKeys(IProjectSettings prjSettings,
4255

4356
var serverBaseUrl = new Uri(prjSettings.KeenUrl);
4457
_keenHttpClient = keenHttpClientProvider.GetForUrl(serverBaseUrl);
45-
_accesKeyRelativeUrl = KeenHttpClient.GetRelativeUrl(prjSettings.ProjectId,
46-
KeenConstants.AccessKeyResource);
58+
_accessKeyRelativeUrl = KeenHttpClient.GetRelativeUrl(prjSettings.ProjectId,
59+
KeenConstants.AccessKeyResource);
4760

4861
_readKey = prjSettings.ReadKey;
4962
_masterKey = prjSettings.MasterKey;
5063
}
5164

52-
public async Task<JObject> CreateAccessKey(AccessKey accesskey)
65+
public async Task<JObject> CreateAccessKey(AccessKeyDefinition accesskey)
5366
{
5467
if (string.IsNullOrWhiteSpace(_masterKey))
5568
{
5669
throw new KeenException("An API WriteKey is required to add events.");
5770
}
58-
59-
DefaultContractResolver contractResolver = new DefaultContractResolver
60-
{
61-
NamingStrategy = new SnakeCaseNamingStrategy()
62-
};
6371

64-
var content = JsonConvert.SerializeObject(accesskey, new JsonSerializerSettings
72+
if (null == accesskey)
6573
{
66-
ContractResolver = contractResolver,
67-
Formatting = Formatting.Indented
68-
}).ToSafeString();
74+
throw new KeenException("An instance of AccessKeyDefinition must be provided");
75+
}
76+
77+
var content = JsonConvert.SerializeObject(accesskey, SerializerSettings);
6978

7079
var responseMsg = await _keenHttpClient
71-
.PostAsync(_accesKeyRelativeUrl, _masterKey, content)
80+
.PostAsync(_accessKeyRelativeUrl, _masterKey, content)
7281
.ConfigureAwait(continueOnCapturedContext: false);
7382

7483
var responseString = await responseMsg
@@ -86,14 +95,16 @@ public async Task<JObject> CreateAccessKey(AccessKey accesskey)
8695
{
8796
// To avoid any flow stoppers
8897
}
98+
8999
if (!responseMsg.IsSuccessStatusCode)
90100
{
91-
throw new KeenException("AddEvents failed with status: " + responseMsg.StatusCode);
101+
throw new KeenException("Creating Access Key failed with status: " +
102+
responseMsg.StatusCode);
92103
}
93104

94105
if (null == jsonResponse)
95106
{
96-
throw new KeenException("AddEvents failed with empty response from server.");
107+
throw new KeenException("Creating Access Key failed with empty JSON response.");
97108
}
98109

99110
return jsonResponse;

Keen/AccessKey/IAccessKeys.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
using Newtonsoft.Json.Linq;
21
using System.Threading.Tasks;
2+
using Newtonsoft.Json.Linq;
3+
34

45
namespace Keen.AccessKey
56
{
@@ -8,11 +9,13 @@ namespace Keen.AccessKey
89
/// </summary>
910
public interface IAccessKeys
1011
{
12+
// TODO : Flesh out public comments as per PR feedback.
13+
1114
/// <summary>
1215
/// Creates an Access Key
1316
/// </summary>
1417
/// <param name="accesskey"></param>
1518
/// <returns></returns>
16-
Task<JObject> CreateAccessKey(AccessKey accesskey);
19+
Task<JObject> CreateAccessKey(AccessKeyDefinition accesskey);
1720
}
1821
}

0 commit comments

Comments
 (0)