Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.

Commit 6d40408

Browse files
committed
Fix email verification status parsing error (closes #212)
1 parent a86fd17 commit 6d40408

File tree

10 files changed

+168
-7
lines changed

10 files changed

+168
-7
lines changed

Stormpath.SDK.nuspec

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
33
<metadata>
44
<id>Stormpath.SDK</id>
5-
<version>0.94.1</version>
5+
<version>0.94.2</version>
66
<authors>Nate Barbettini</authors>
77
<owners>Stormpath, Inc.</owners>
88
<licenseUrl>https://github.com/stormpath/stormpath-sdk-csharp/blob/master/LICENSE</licenseUrl>
@@ -14,12 +14,12 @@
1414
<tags>Stormpath API Authentication Authorization REST</tags>
1515
<dependencies>
1616
<group targetFramework=".NETStandard1.3">
17-
<dependency id="Stormpath.SDK.Core" version="[0.94.1, )" />
17+
<dependency id="Stormpath.SDK.Core" version="[0.94.2, )" />
1818
<dependency id="Stormpath.SDK.Http.SystemNetHttpClient" version="[0.94.0, )" />
1919
<dependency id="Stormpath.SDK.JsonNetSerializer" version="[0.91.0, )" />
2020
</group>
2121
<group targetFramework=".NETFramework4.5">
22-
<dependency id="Stormpath.SDK.Core" version="[0.94.1, )" />
22+
<dependency id="Stormpath.SDK.Core" version="[0.94.2, )" />
2323
<dependency id="Stormpath.SDK.RestSharpClient" version="[0.94.0, )" />
2424
<dependency id="Stormpath.SDK.JsonNetSerializer" version="[0.91.0, )" />
2525
</group>
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// <copyright file="EmailVerificationStatus.cs" company="Stormpath, Inc.">
2+
// Copyright (c) 2016 Stormpath, Inc.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
// </copyright>
16+
17+
using System;
18+
using Stormpath.SDK.Shared;
19+
20+
namespace Stormpath.SDK.Account
21+
{
22+
/// <summary>
23+
/// Represents the various states an <see cref="IAccount">Account</see>'s email address may be in.
24+
/// </summary>
25+
public sealed class EmailVerificationStatus : StringEnumeration
26+
{
27+
/// <summary>
28+
/// The account's email has been verified.
29+
/// </summary>
30+
public static EmailVerificationStatus Verified = new EmailVerificationStatus("VERIFIED");
31+
32+
/// <summary>
33+
/// The account's email has not been verified.
34+
/// </summary>
35+
public static EmailVerificationStatus Unverified = new EmailVerificationStatus("UNVERIFIED");
36+
37+
/// <summary>
38+
/// The account's email status is not known.
39+
/// </summary>
40+
public static EmailVerificationStatus Unknown = new EmailVerificationStatus("UNKNOWN");
41+
42+
private EmailVerificationStatus(string value)
43+
: base(value)
44+
{
45+
}
46+
47+
/// <summary>
48+
/// Parses a string to an <see cref="EmailVerificationStatus"/>.
49+
/// </summary>
50+
/// <param name="status">A string containing "verified", "unverified", or "unknown" (matching is case-insensitive).</param>
51+
/// <returns>The <see cref="EmailVerificationStatus"/> with the specified name.</returns>
52+
/// <exception cref="Exception">No match is found.</exception>
53+
public static EmailVerificationStatus Parse(string status)
54+
{
55+
switch (status.ToUpper())
56+
{
57+
case "VERIFIED":
58+
return Verified;
59+
case "UNVERIFIED":
60+
return Unverified;
61+
case "UNKNOWN":
62+
return Unknown;
63+
default:
64+
throw new Exception($"Could not parse email verification status value '{status.ToUpper()}'");
65+
}
66+
}
67+
}
68+
}

src/Stormpath.SDK.Abstractions/Account/IAccount.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ public interface IAccount :
9191
/// <value>An <see cref="IEmailVerificationToken"/>, or <see langword="null"/> if this account does not need to verify its email address.</value>
9292
IEmailVerificationToken EmailVerificationToken { get; }
9393

94+
/// <summary>
95+
/// Gets the account's email verification status.
96+
/// </summary>
97+
/// <value>The account's email verification status.</value>
98+
EmailVerificationStatus EmailVerificationStatus { get; }
99+
94100
/// <summary>
95101
/// Gets the account's status.
96102
/// </summary>

src/Stormpath.SDK.Abstractions/project.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,5 @@
3636
"tooling": {
3737
"defaultNamespace": "Stormpath.SDK"
3838
},
39-
"version": "0.94.1"
39+
"version": "0.94.2"
4040
}

src/Stormpath.SDK.Core/Impl/Account/DefaultAccount.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ internal sealed partial class DefaultAccount : AbstractExtendableInstanceResourc
3131
private static readonly string DirectoryPropertyName = "directory";
3232
private static readonly string EmailPropertyName = "email";
3333
private static readonly string EmailVerificationTokenPropertyName = "emailVerificationToken";
34+
private static readonly string EmailVerificationStatusPropertyName = "emailVerificationStatus";
3435
private static readonly string FullNamePropertyName = "fullName";
3536
private static readonly string GivenNamePropertyName = "givenName";
3637
private static readonly string GroupMembershipsPropertyName = "groupMemberships";
@@ -65,6 +66,8 @@ public DefaultAccount(ResourceData data)
6566

6667
internal IEmbeddedProperty EmailVerificationToken => this.GetLinkProperty(EmailVerificationTokenPropertyName);
6768

69+
EmailVerificationStatus IAccount.EmailVerificationStatus => GetProperty<EmailVerificationStatus>(EmailVerificationStatusPropertyName);
70+
6871
IEmailVerificationToken IAccount.EmailVerificationToken
6972
{
7073
get

src/Stormpath.SDK.Core/Impl/Serialization/FieldConverters/StatusFieldConverters.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,40 @@ protected override FieldConverterResult ConvertImpl(KeyValuePair<string, object>
4141
return FieldConverterResult.Failed;
4242
}
4343

44+
// Only convert the Account.Status value
45+
if (!token.Key.Equals("status", StringComparison.OrdinalIgnoreCase))
46+
{
47+
return FieldConverterResult.Failed;
48+
}
49+
4450
return new FieldConverterResult(true, SDK.Account.AccountStatus.Parse(token.Value.ToString()));
4551
}
4652
}
4753

54+
internal sealed class AccountEmailVerificationStatusConverter : AbstractFieldConverter
55+
{
56+
public AccountEmailVerificationStatusConverter()
57+
: base(nameof(AccountEmailVerificationStatusConverter), typeof(SDK.Account.IAccount))
58+
{
59+
}
60+
61+
protected override FieldConverterResult ConvertImpl(KeyValuePair<string, object> token)
62+
{
63+
if (!IsStatusField(token))
64+
{
65+
return FieldConverterResult.Failed;
66+
}
67+
68+
// Only convert the Account.EmailVerificationStatus value
69+
if (!token.Key.Equals("emailVerificationStatus", StringComparison.OrdinalIgnoreCase))
70+
{
71+
return FieldConverterResult.Failed;
72+
}
73+
74+
return new FieldConverterResult(true, SDK.Account.EmailVerificationStatus.Parse(token.Value.ToString()));
75+
}
76+
}
77+
4878
internal sealed class ApplicationStatusConverter : AbstractFieldConverter
4979
{
5080
public ApplicationStatusConverter()
@@ -59,6 +89,12 @@ protected override FieldConverterResult ConvertImpl(KeyValuePair<string, object>
5989
return FieldConverterResult.Failed;
6090
}
6191

92+
// Only convert the Application.Status value
93+
if (!token.Key.Equals("status", StringComparison.OrdinalIgnoreCase))
94+
{
95+
return FieldConverterResult.Failed;
96+
}
97+
6298
return new FieldConverterResult(true, SDK.Application.ApplicationStatus.Parse(token.Value.ToString()));
6399
}
64100
}
@@ -77,6 +113,12 @@ protected override FieldConverterResult ConvertImpl(KeyValuePair<string, object>
77113
return FieldConverterResult.Failed;
78114
}
79115

116+
// Only convert the Directory.Status value
117+
if (!token.Key.Equals("status", StringComparison.OrdinalIgnoreCase))
118+
{
119+
return FieldConverterResult.Failed;
120+
}
121+
80122
return new FieldConverterResult(true, SDK.Directory.DirectoryStatus.Parse(token.Value.ToString()));
81123
}
82124
}
@@ -95,6 +137,12 @@ protected override FieldConverterResult ConvertImpl(KeyValuePair<string, object>
95137
return FieldConverterResult.Failed;
96138
}
97139

140+
// Only convert the Group.Status value
141+
if (!token.Key.Equals("status", StringComparison.OrdinalIgnoreCase))
142+
{
143+
return FieldConverterResult.Failed;
144+
}
145+
98146
return new FieldConverterResult(true, SDK.Group.GroupStatus.Parse(token.Value.ToString()));
99147
}
100148
}
@@ -113,6 +161,12 @@ protected override FieldConverterResult ConvertImpl(KeyValuePair<string, object>
113161
return FieldConverterResult.Failed;
114162
}
115163

164+
// Only convert the Organization.Status value
165+
if (!token.Key.Equals("status", StringComparison.OrdinalIgnoreCase))
166+
{
167+
return FieldConverterResult.Failed;
168+
}
169+
116170
return new FieldConverterResult(true, SDK.Organization.OrganizationStatus.Parse(token.Value.ToString()));
117171
}
118172
}
@@ -131,6 +185,12 @@ protected override FieldConverterResult ConvertImpl(KeyValuePair<string, object>
131185
return FieldConverterResult.Failed;
132186
}
133187

188+
// Only convert the ApiKey.Status value
189+
if (!token.Key.Equals("status", StringComparison.OrdinalIgnoreCase))
190+
{
191+
return FieldConverterResult.Failed;
192+
}
193+
134194
return new FieldConverterResult(true, SDK.Api.ApiKeyStatus.Parse(token.Value.ToString()));
135195
}
136196
}
@@ -149,6 +209,12 @@ protected override FieldConverterResult ConvertImpl(KeyValuePair<string, object>
149209
return FieldConverterResult.Failed;
150210
}
151211

212+
// Only convert the Email.Status value
213+
if (!token.Key.EndsWith("EmailStatus", StringComparison.OrdinalIgnoreCase))
214+
{
215+
return FieldConverterResult.Failed;
216+
}
217+
152218
return new FieldConverterResult(true, SDK.Mail.EmailStatus.Parse(token.Value.ToString()));
153219
}
154220
}

src/Stormpath.SDK.Core/Impl/Serialization/JsonSerializationProvider.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public JsonSerializationProvider(IJsonSerializer externalSerializer)
3636
new LinkPropertyConverter(),
3737
new ExpandedPropertyConverter(converter: this.ConvertProperties),
3838
new StatusFieldConverters.AccountStatusConverter(),
39+
new StatusFieldConverters.AccountEmailVerificationStatusConverter(),
3940
new StatusFieldConverters.ApplicationStatusConverter(),
4041
new StatusFieldConverters.DirectoryStatusConverter(),
4142
new StatusFieldConverters.GroupStatusConverter(),

src/Stormpath.SDK.Core/project.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"Stormpath.Configuration": "6.0.0",
1313
"Stormpath.SDK.Abstractions": {
1414
"target": "project",
15-
"version": "0.94.1"
15+
"version": "0.94.2"
1616
},
1717
"System.Runtime.InteropServices.RuntimeInformation": "4.0.0"
1818
},
@@ -48,5 +48,5 @@
4848
"tooling": {
4949
"defaultNamespace": "Stormpath.SDK"
5050
},
51-
"version": "0.94.1"
51+
"version": "0.94.2"
5252
}

test/Stormpath.SDK.Tests.Common/Fakes/FakeJson.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public static class FakeJson
7777
},
7878
""email"": ""[email protected]"",
7979
""emailVerificationToken"": null,
80+
""emailVerificationStatus"": ""UNKNOWN"",
8081
""fullName"": ""Han Solo"",
8182
""givenName"": ""Han"",
8283
""groupMemberships"": {

test/Stormpath.SDK.Tests/DefaultDataStore_tests.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ public async Task Supports_list_property()
273273
{
274274
var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Application).Object);
275275

276-
var application = await dataStore.GetResourceAsync<IApplication>("/account", CancellationToken.None);
276+
var application = await dataStore.GetResourceAsync<IApplication>("/application", CancellationToken.None);
277277

278278
// Verify against data from FakeJson.Application
279279
application.Name.ShouldBe("Lightsabers Galore");
@@ -283,5 +283,21 @@ public async Task Supports_list_property()
283283
application.AuthorizedCallbackUris.ShouldContain("https://foo.bar/1");
284284
application.AuthorizedCallbackUris.ShouldContain("https://foo.bar/2");
285285
}
286+
287+
/// <summary>
288+
/// Regression test for https://github.com/stormpath/stormpath-sdk-dotnet/issues/212
289+
/// </summary>
290+
/// <returns>A Task that represents the asynchronous test.</returns>
291+
[Fact]
292+
public async Task Supports_email_verification_status_unknown()
293+
{
294+
var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object);
295+
296+
var account = await dataStore.GetResourceAsync<IAccount>("/account", CancellationToken.None);
297+
298+
// Verify against data from FakeJson.Application
299+
account.EmailVerificationStatus.ShouldBe(EmailVerificationStatus.Unknown);
300+
}
301+
286302
}
287303
}

0 commit comments

Comments
 (0)