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

Commit

Permalink
Fix email verification status parsing error (closes #212)
Browse files Browse the repository at this point in the history
  • Loading branch information
nbarbettini committed Oct 11, 2016
1 parent a86fd17 commit 6d40408
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 7 deletions.
6 changes: 3 additions & 3 deletions Stormpath.SDK.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>Stormpath.SDK</id>
<version>0.94.1</version>
<version>0.94.2</version>
<authors>Nate Barbettini</authors>
<owners>Stormpath, Inc.</owners>
<licenseUrl>https://github.com/stormpath/stormpath-sdk-csharp/blob/master/LICENSE</licenseUrl>
Expand All @@ -14,12 +14,12 @@
<tags>Stormpath API Authentication Authorization REST</tags>
<dependencies>
<group targetFramework=".NETStandard1.3">
<dependency id="Stormpath.SDK.Core" version="[0.94.1, )" />
<dependency id="Stormpath.SDK.Core" version="[0.94.2, )" />
<dependency id="Stormpath.SDK.Http.SystemNetHttpClient" version="[0.94.0, )" />
<dependency id="Stormpath.SDK.JsonNetSerializer" version="[0.91.0, )" />
</group>
<group targetFramework=".NETFramework4.5">
<dependency id="Stormpath.SDK.Core" version="[0.94.1, )" />
<dependency id="Stormpath.SDK.Core" version="[0.94.2, )" />
<dependency id="Stormpath.SDK.RestSharpClient" version="[0.94.0, )" />
<dependency id="Stormpath.SDK.JsonNetSerializer" version="[0.91.0, )" />
</group>
Expand Down
68 changes: 68 additions & 0 deletions src/Stormpath.SDK.Abstractions/Account/EmailVerificationStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// <copyright file="EmailVerificationStatus.cs" company="Stormpath, Inc.">
// Copyright (c) 2016 Stormpath, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System;
using Stormpath.SDK.Shared;

namespace Stormpath.SDK.Account
{
/// <summary>
/// Represents the various states an <see cref="IAccount">Account</see>'s email address may be in.
/// </summary>
public sealed class EmailVerificationStatus : StringEnumeration
{
/// <summary>
/// The account's email has been verified.
/// </summary>
public static EmailVerificationStatus Verified = new EmailVerificationStatus("VERIFIED");

/// <summary>
/// The account's email has not been verified.
/// </summary>
public static EmailVerificationStatus Unverified = new EmailVerificationStatus("UNVERIFIED");

/// <summary>
/// The account's email status is not known.
/// </summary>
public static EmailVerificationStatus Unknown = new EmailVerificationStatus("UNKNOWN");

private EmailVerificationStatus(string value)
: base(value)
{
}

/// <summary>
/// Parses a string to an <see cref="EmailVerificationStatus"/>.
/// </summary>
/// <param name="status">A string containing "verified", "unverified", or "unknown" (matching is case-insensitive).</param>
/// <returns>The <see cref="EmailVerificationStatus"/> with the specified name.</returns>
/// <exception cref="Exception">No match is found.</exception>
public static EmailVerificationStatus Parse(string status)
{
switch (status.ToUpper())
{
case "VERIFIED":
return Verified;
case "UNVERIFIED":
return Unverified;
case "UNKNOWN":
return Unknown;
default:
throw new Exception($"Could not parse email verification status value '{status.ToUpper()}'");
}
}
}
}
6 changes: 6 additions & 0 deletions src/Stormpath.SDK.Abstractions/Account/IAccount.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ public interface IAccount :
/// <value>An <see cref="IEmailVerificationToken"/>, or <see langword="null"/> if this account does not need to verify its email address.</value>
IEmailVerificationToken EmailVerificationToken { get; }

/// <summary>
/// Gets the account's email verification status.
/// </summary>
/// <value>The account's email verification status.</value>
EmailVerificationStatus EmailVerificationStatus { get; }

/// <summary>
/// Gets the account's status.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Stormpath.SDK.Abstractions/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@
"tooling": {
"defaultNamespace": "Stormpath.SDK"
},
"version": "0.94.1"
"version": "0.94.2"
}
3 changes: 3 additions & 0 deletions src/Stormpath.SDK.Core/Impl/Account/DefaultAccount.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ internal sealed partial class DefaultAccount : AbstractExtendableInstanceResourc
private static readonly string DirectoryPropertyName = "directory";
private static readonly string EmailPropertyName = "email";
private static readonly string EmailVerificationTokenPropertyName = "emailVerificationToken";
private static readonly string EmailVerificationStatusPropertyName = "emailVerificationStatus";
private static readonly string FullNamePropertyName = "fullName";
private static readonly string GivenNamePropertyName = "givenName";
private static readonly string GroupMembershipsPropertyName = "groupMemberships";
Expand Down Expand Up @@ -65,6 +66,8 @@ public DefaultAccount(ResourceData data)

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

EmailVerificationStatus IAccount.EmailVerificationStatus => GetProperty<EmailVerificationStatus>(EmailVerificationStatusPropertyName);

IEmailVerificationToken IAccount.EmailVerificationToken
{
get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,40 @@ protected override FieldConverterResult ConvertImpl(KeyValuePair<string, object>
return FieldConverterResult.Failed;
}

// Only convert the Account.Status value
if (!token.Key.Equals("status", StringComparison.OrdinalIgnoreCase))
{
return FieldConverterResult.Failed;
}

return new FieldConverterResult(true, SDK.Account.AccountStatus.Parse(token.Value.ToString()));
}
}

internal sealed class AccountEmailVerificationStatusConverter : AbstractFieldConverter
{
public AccountEmailVerificationStatusConverter()
: base(nameof(AccountEmailVerificationStatusConverter), typeof(SDK.Account.IAccount))
{
}

protected override FieldConverterResult ConvertImpl(KeyValuePair<string, object> token)
{
if (!IsStatusField(token))
{
return FieldConverterResult.Failed;
}

// Only convert the Account.EmailVerificationStatus value
if (!token.Key.Equals("emailVerificationStatus", StringComparison.OrdinalIgnoreCase))
{
return FieldConverterResult.Failed;
}

return new FieldConverterResult(true, SDK.Account.EmailVerificationStatus.Parse(token.Value.ToString()));
}
}

internal sealed class ApplicationStatusConverter : AbstractFieldConverter
{
public ApplicationStatusConverter()
Expand All @@ -59,6 +89,12 @@ protected override FieldConverterResult ConvertImpl(KeyValuePair<string, object>
return FieldConverterResult.Failed;
}

// Only convert the Application.Status value
if (!token.Key.Equals("status", StringComparison.OrdinalIgnoreCase))
{
return FieldConverterResult.Failed;
}

return new FieldConverterResult(true, SDK.Application.ApplicationStatus.Parse(token.Value.ToString()));
}
}
Expand All @@ -77,6 +113,12 @@ protected override FieldConverterResult ConvertImpl(KeyValuePair<string, object>
return FieldConverterResult.Failed;
}

// Only convert the Directory.Status value
if (!token.Key.Equals("status", StringComparison.OrdinalIgnoreCase))
{
return FieldConverterResult.Failed;
}

return new FieldConverterResult(true, SDK.Directory.DirectoryStatus.Parse(token.Value.ToString()));
}
}
Expand All @@ -95,6 +137,12 @@ protected override FieldConverterResult ConvertImpl(KeyValuePair<string, object>
return FieldConverterResult.Failed;
}

// Only convert the Group.Status value
if (!token.Key.Equals("status", StringComparison.OrdinalIgnoreCase))
{
return FieldConverterResult.Failed;
}

return new FieldConverterResult(true, SDK.Group.GroupStatus.Parse(token.Value.ToString()));
}
}
Expand All @@ -113,6 +161,12 @@ protected override FieldConverterResult ConvertImpl(KeyValuePair<string, object>
return FieldConverterResult.Failed;
}

// Only convert the Organization.Status value
if (!token.Key.Equals("status", StringComparison.OrdinalIgnoreCase))
{
return FieldConverterResult.Failed;
}

return new FieldConverterResult(true, SDK.Organization.OrganizationStatus.Parse(token.Value.ToString()));
}
}
Expand All @@ -131,6 +185,12 @@ protected override FieldConverterResult ConvertImpl(KeyValuePair<string, object>
return FieldConverterResult.Failed;
}

// Only convert the ApiKey.Status value
if (!token.Key.Equals("status", StringComparison.OrdinalIgnoreCase))
{
return FieldConverterResult.Failed;
}

return new FieldConverterResult(true, SDK.Api.ApiKeyStatus.Parse(token.Value.ToString()));
}
}
Expand All @@ -149,6 +209,12 @@ protected override FieldConverterResult ConvertImpl(KeyValuePair<string, object>
return FieldConverterResult.Failed;
}

// Only convert the Email.Status value
if (!token.Key.EndsWith("EmailStatus", StringComparison.OrdinalIgnoreCase))
{
return FieldConverterResult.Failed;
}

return new FieldConverterResult(true, SDK.Mail.EmailStatus.Parse(token.Value.ToString()));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public JsonSerializationProvider(IJsonSerializer externalSerializer)
new LinkPropertyConverter(),
new ExpandedPropertyConverter(converter: this.ConvertProperties),
new StatusFieldConverters.AccountStatusConverter(),
new StatusFieldConverters.AccountEmailVerificationStatusConverter(),
new StatusFieldConverters.ApplicationStatusConverter(),
new StatusFieldConverters.DirectoryStatusConverter(),
new StatusFieldConverters.GroupStatusConverter(),
Expand Down
4 changes: 2 additions & 2 deletions src/Stormpath.SDK.Core/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"Stormpath.Configuration": "6.0.0",
"Stormpath.SDK.Abstractions": {
"target": "project",
"version": "0.94.1"
"version": "0.94.2"
},
"System.Runtime.InteropServices.RuntimeInformation": "4.0.0"
},
Expand Down Expand Up @@ -48,5 +48,5 @@
"tooling": {
"defaultNamespace": "Stormpath.SDK"
},
"version": "0.94.1"
"version": "0.94.2"
}
1 change: 1 addition & 0 deletions test/Stormpath.SDK.Tests.Common/Fakes/FakeJson.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public static class FakeJson
},
""email"": ""[email protected]"",
""emailVerificationToken"": null,
""emailVerificationStatus"": ""UNKNOWN"",
""fullName"": ""Han Solo"",
""givenName"": ""Han"",
""groupMemberships"": {
Expand Down
18 changes: 17 additions & 1 deletion test/Stormpath.SDK.Tests/DefaultDataStore_tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ public async Task Supports_list_property()
{
var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Application).Object);

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

// Verify against data from FakeJson.Application
application.Name.ShouldBe("Lightsabers Galore");
Expand All @@ -283,5 +283,21 @@ public async Task Supports_list_property()
application.AuthorizedCallbackUris.ShouldContain("https://foo.bar/1");
application.AuthorizedCallbackUris.ShouldContain("https://foo.bar/2");
}

/// <summary>
/// Regression test for https://github.com/stormpath/stormpath-sdk-dotnet/issues/212
/// </summary>
/// <returns>A Task that represents the asynchronous test.</returns>
[Fact]
public async Task Supports_email_verification_status_unknown()
{
var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object);

var account = await dataStore.GetResourceAsync<IAccount>("/account", CancellationToken.None);

// Verify against data from FakeJson.Application
account.EmailVerificationStatus.ShouldBe(EmailVerificationStatus.Unknown);
}

}
}

0 comments on commit 6d40408

Please sign in to comment.