From 8dc12fff3ca3c43b7c2a08c6a3c03f62bda01a32 Mon Sep 17 00:00:00 2001 From: Tony Han Date: Sat, 2 Mar 2024 00:36:15 +0800 Subject: [PATCH] Add LoginInfoConverter (#15422) --------- Co-authored-by: Mike Alhayek Co-authored-by: hyzx86 --- .../UsersServiceCollectionExtensions.cs | 7 ++ .../Json/LoginInfoJsonConverter.cs | 57 ++++++++++++++ .../Serializers/JsonSerializerTests.cs | 77 +++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 src/OrchardCore/OrchardCore.Users.Core/Json/LoginInfoJsonConverter.cs create mode 100644 test/OrchardCore.Tests/Serializers/JsonSerializerTests.cs diff --git a/src/OrchardCore/OrchardCore.Users.Core/Extensions/UsersServiceCollectionExtensions.cs b/src/OrchardCore/OrchardCore.Users.Core/Extensions/UsersServiceCollectionExtensions.cs index 0bd3e4317d7..c26e3856bcb 100644 --- a/src/OrchardCore/OrchardCore.Users.Core/Extensions/UsersServiceCollectionExtensions.cs +++ b/src/OrchardCore/OrchardCore.Users.Core/Extensions/UsersServiceCollectionExtensions.cs @@ -9,6 +9,8 @@ using OrchardCore.Users.Handlers; using OrchardCore.Users.Indexes; using OrchardCore.Users.Services; +using OrchardCore.Users.Core.Json; +using System.Text.Json; namespace Microsoft.Extensions.DependencyInjection { @@ -55,6 +57,11 @@ public static IServiceCollection AddUsers(this IServiceCollection services) services.AddScoped(); services.AddScoped(); + services.Configure(options => + { + options.Converters.Add(new LoginInfoJsonConverter()); + }); + return services; } } diff --git a/src/OrchardCore/OrchardCore.Users.Core/Json/LoginInfoJsonConverter.cs b/src/OrchardCore/OrchardCore.Users.Core/Json/LoginInfoJsonConverter.cs new file mode 100644 index 00000000000..151365c279b --- /dev/null +++ b/src/OrchardCore/OrchardCore.Users.Core/Json/LoginInfoJsonConverter.cs @@ -0,0 +1,57 @@ +using System; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; +using Microsoft.AspNetCore.Identity; + +namespace OrchardCore.Users.Core.Json; + +public class LoginInfoJsonConverter : JsonConverter +{ + public static readonly LoginInfoJsonConverter Instance = new(); + + public override UserLoginInfo Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var loginInfo = new UserLoginInfo(string.Empty, string.Empty, string.Empty); + + while (reader.Read()) + { + if (reader.TokenType == JsonTokenType.EndObject) + { + break; + } + + if (reader.TokenType == JsonTokenType.PropertyName) + { + var propertyName = reader.GetString(); + reader.Read(); + + switch (propertyName) + { + case nameof(UserLoginInfo.LoginProvider): + loginInfo.LoginProvider = reader.GetString(); + break; + case nameof(UserLoginInfo.ProviderKey): + loginInfo.ProviderKey = reader.GetString(); + break; + case nameof(UserLoginInfo.ProviderDisplayName): + loginInfo.ProviderDisplayName = reader.GetString(); + break; + default: + break; + } + } + } + + return loginInfo; + } + + public override void Write(Utf8JsonWriter writer, UserLoginInfo objectToWrite, JsonSerializerOptions options) + { + writer.WriteStartObject(); + writer.WriteString(nameof(UserLoginInfo.LoginProvider), objectToWrite.LoginProvider); + writer.WriteString(nameof(UserLoginInfo.ProviderKey), objectToWrite.ProviderKey); + writer.WriteString(nameof(UserLoginInfo.ProviderDisplayName), objectToWrite.ProviderDisplayName); + writer.WriteEndObject(); + } +} diff --git a/test/OrchardCore.Tests/Serializers/JsonSerializerTests.cs b/test/OrchardCore.Tests/Serializers/JsonSerializerTests.cs new file mode 100644 index 00000000000..422d44e6d12 --- /dev/null +++ b/test/OrchardCore.Tests/Serializers/JsonSerializerTests.cs @@ -0,0 +1,77 @@ +using System.Text.Json; +using OrchardCore.Tests.Apis.Context; +using OrchardCore.Users.Core.Json; +using OrchardCore.Users.Indexes; +using OrchardCore.Users.Models; + +namespace OrchardCore.Tests.Serializers; + +public class JsonSerializerTests +{ + private const string _userLoginInfo = "{\"LoginProvider\":\"OpenIdConnect\",\"ProviderKey\":\"abc\",\"ProviderDisplayName\":\"default\"}"; + + private readonly JsonSerializerOptions _options; + + public JsonSerializerTests() + { + _options = new JsonSerializerOptions(); + _options.Converters.Add(new LoginInfoJsonConverter()); + } + + [Fact] + public void Deserialize_WhenCalled_ReturnValidUserLoginInfo() + { + var obj = JsonSerializer.Deserialize(_userLoginInfo, _options); + + Assert.Equal("OpenIdConnect", obj.LoginProvider); + Assert.Equal("abc", obj.ProviderKey); + Assert.Equal("default", obj.ProviderDisplayName); + } + + [Fact] + public void Serialize_WhenCalled_ReturnValidJson() + { + var loginInfo = new UserLoginInfo("OpenIdConnect", "abc", "default"); + var json = JsonSerializer.Serialize(loginInfo, _options); + + Assert.Equal(_userLoginInfo, json); + } + + [Fact] + public async Task DefaultContentSerializer_SerializeAndDeserialize_UserWithUserLoginInfo() + { + using var context = new SiteContext(); + await context.InitializeAsync(); + await context.UsingTenantScopeAsync(async scope => + { + var loginInfo = new UserLoginInfo("OpenIdConnect", "abc", "default"); + + var newUser = new User() + { + UserId = "abc", + UserName = "mike", + Email = "test@test.com", + LoginInfos = + [ + loginInfo + ] + }; + + var session = scope.ServiceProvider.GetRequiredService(); + + await session.SaveAsync(newUser); + await session.SaveChangesAsync(); + + var dbUser = await session.Query(x => x.UserId == "abc").FirstOrDefaultAsync(); + + Assert.NotNull(dbUser); + + var userLoginInfo = dbUser.LoginInfos.FirstOrDefault(); + + Assert.NotNull(userLoginInfo); + Assert.Equal(loginInfo.LoginProvider, userLoginInfo.LoginProvider); + Assert.Equal(loginInfo.ProviderKey, userLoginInfo.ProviderKey); + Assert.Equal(loginInfo.ProviderDisplayName, userLoginInfo.ProviderDisplayName); + }); + } +}