Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(Identity): Support custom User Model #192

Merged
merged 16 commits into from
Aug 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions Masa.Framework.sln
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Framework.IntegrationT
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Contrib.Data.IdGenerator.NormalGuid.Tests", "src\Contrib\Data\IdGenerator\NormalGuid\Masa.Contrib.Data.IdGenerator.NormalGuid.Tests\Masa.Contrib.Data.IdGenerator.NormalGuid.Tests.csproj", "{C488CAC3-6F06-4D29-B449-93CEF482C4D7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Serialization", "Serialization", "{F2595DAE-AEB7-4739-8578-B6635FC7C6FB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Contrib.Data.Serialization.Json", "src\Contrib\Data\Serialization\Masa.Contrib.Data.Serialization.Json\Masa.Contrib.Data.Serialization.Json.csproj", "{E14E5712-EEC4-4249-84A5-5AC930E51E28}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Contrib.Data.Serialization.Yaml", "src\Contrib\Data\Serialization\Masa.Contrib.Data.Serialization.Yaml\Masa.Contrib.Data.Serialization.Yaml.csproj", "{7E8785A6-1B4D-4A35-9DA1-F6B99FF8C740}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{6E93CADC-B6C7-4063-BEA7-56068D682C31}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Contrib.Data.Serialization.Json.Tests", "src\Contrib\Data\Serialization\Tests\Masa.Contrib.Data.Serialization.Json.Tests\Masa.Contrib.Data.Serialization.Json.Tests.csproj", "{C55B75D2-43E0-4D3D-B705-110C4255528A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Contrib.Data.Serialization.Yaml.Tests", "src\Contrib\Data\Serialization\Tests\Masa.Contrib.Data.Serialization.Yaml.Tests\Masa.Contrib.Data.Serialization.Yaml.Tests.csproj", "{A86DA6FB-58E0-4FEE-B663-C336F9B3A3A5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1853,6 +1865,38 @@ Global
{C488CAC3-6F06-4D29-B449-93CEF482C4D7}.Release|Any CPU.Build.0 = Release|Any CPU
{C488CAC3-6F06-4D29-B449-93CEF482C4D7}.Release|x64.ActiveCfg = Release|Any CPU
{C488CAC3-6F06-4D29-B449-93CEF482C4D7}.Release|x64.Build.0 = Release|Any CPU
{E14E5712-EEC4-4249-84A5-5AC930E51E28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E14E5712-EEC4-4249-84A5-5AC930E51E28}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E14E5712-EEC4-4249-84A5-5AC930E51E28}.Debug|x64.ActiveCfg = Debug|Any CPU
{E14E5712-EEC4-4249-84A5-5AC930E51E28}.Debug|x64.Build.0 = Debug|Any CPU
{E14E5712-EEC4-4249-84A5-5AC930E51E28}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E14E5712-EEC4-4249-84A5-5AC930E51E28}.Release|Any CPU.Build.0 = Release|Any CPU
{E14E5712-EEC4-4249-84A5-5AC930E51E28}.Release|x64.ActiveCfg = Release|Any CPU
{E14E5712-EEC4-4249-84A5-5AC930E51E28}.Release|x64.Build.0 = Release|Any CPU
{7E8785A6-1B4D-4A35-9DA1-F6B99FF8C740}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7E8785A6-1B4D-4A35-9DA1-F6B99FF8C740}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7E8785A6-1B4D-4A35-9DA1-F6B99FF8C740}.Debug|x64.ActiveCfg = Debug|Any CPU
{7E8785A6-1B4D-4A35-9DA1-F6B99FF8C740}.Debug|x64.Build.0 = Debug|Any CPU
{7E8785A6-1B4D-4A35-9DA1-F6B99FF8C740}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7E8785A6-1B4D-4A35-9DA1-F6B99FF8C740}.Release|Any CPU.Build.0 = Release|Any CPU
{7E8785A6-1B4D-4A35-9DA1-F6B99FF8C740}.Release|x64.ActiveCfg = Release|Any CPU
{7E8785A6-1B4D-4A35-9DA1-F6B99FF8C740}.Release|x64.Build.0 = Release|Any CPU
{C55B75D2-43E0-4D3D-B705-110C4255528A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C55B75D2-43E0-4D3D-B705-110C4255528A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C55B75D2-43E0-4D3D-B705-110C4255528A}.Debug|x64.ActiveCfg = Debug|Any CPU
{C55B75D2-43E0-4D3D-B705-110C4255528A}.Debug|x64.Build.0 = Debug|Any CPU
{C55B75D2-43E0-4D3D-B705-110C4255528A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C55B75D2-43E0-4D3D-B705-110C4255528A}.Release|Any CPU.Build.0 = Release|Any CPU
{C55B75D2-43E0-4D3D-B705-110C4255528A}.Release|x64.ActiveCfg = Release|Any CPU
{C55B75D2-43E0-4D3D-B705-110C4255528A}.Release|x64.Build.0 = Release|Any CPU
{A86DA6FB-58E0-4FEE-B663-C336F9B3A3A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A86DA6FB-58E0-4FEE-B663-C336F9B3A3A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A86DA6FB-58E0-4FEE-B663-C336F9B3A3A5}.Debug|x64.ActiveCfg = Debug|Any CPU
{A86DA6FB-58E0-4FEE-B663-C336F9B3A3A5}.Debug|x64.Build.0 = Debug|Any CPU
{A86DA6FB-58E0-4FEE-B663-C336F9B3A3A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A86DA6FB-58E0-4FEE-B663-C336F9B3A3A5}.Release|Any CPU.Build.0 = Release|Any CPU
{A86DA6FB-58E0-4FEE-B663-C336F9B3A3A5}.Release|x64.ActiveCfg = Release|Any CPU
{A86DA6FB-58E0-4FEE-B663-C336F9B3A3A5}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -2111,6 +2155,12 @@ Global
{9EA05A47-B28A-4CD1-8058-00A2098ED0C2} = {55DCA34D-48CE-4D32-8515-B6583FA548AE}
{A9EED08B-6C1E-4409-9874-AA7D34102519} = {E747043D-81E2-4A89-8B5B-1258ED45F941}
{C488CAC3-6F06-4D29-B449-93CEF482C4D7} = {4515CCA0-E8FC-4FCF-93E1-B812F5949371}
{F2595DAE-AEB7-4739-8578-B6635FC7C6FB} = {BE980C6D-3277-44C4-8203-959239F81F67}
{E14E5712-EEC4-4249-84A5-5AC930E51E28} = {F2595DAE-AEB7-4739-8578-B6635FC7C6FB}
{7E8785A6-1B4D-4A35-9DA1-F6B99FF8C740} = {F2595DAE-AEB7-4739-8578-B6635FC7C6FB}
{6E93CADC-B6C7-4063-BEA7-56068D682C31} = {F2595DAE-AEB7-4739-8578-B6635FC7C6FB}
{C55B75D2-43E0-4D3D-B705-110C4255528A} = {6E93CADC-B6C7-4063-BEA7-56068D682C31}
{A86DA6FB-58E0-4FEE-B663-C336F9B3A3A5} = {6E93CADC-B6C7-4063-BEA7-56068D682C31}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {40383055-CC50-4600-AD9A-53C14F620D03}
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public interface IUserContext

TUserId? GetUserId<TUserId>();

IdentityUser? GetUser();

TIdentityUser? GetUser<TIdentityUser>() where TIdentityUser : IIdentityUser;

IEnumerable<TRoleId> GetUserRoles<TRoleId>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\Data\Masa.BuildingBlocks.Data\Masa.BuildingBlocks.Data.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Masa.BuildingBlocks.Authentication.Identity;

public abstract class UserContext : IUserSetter, IUserContext
{
private readonly AsyncLocal<object?> _currentUser = new();
private readonly AsyncLocal<Dictionary<Type, object?>?> _currentUser = new();

public bool IsAuthenticated => GetUserSimple() != null;

Expand All @@ -15,11 +15,13 @@ public abstract class UserContext : IUserSetter, IUserContext

protected ITypeConvertProvider TypeConvertProvider { get; }

public UserContext(ITypeConvertProvider typeConvertProvider) => TypeConvertProvider = typeConvertProvider;

protected abstract object? GetUser();
protected UserContext(ITypeConvertProvider typeConvertProvider)
{
TypeConvertProvider = typeConvertProvider;
_currentUser.Value = new Dictionary<Type, object?>();
}

protected abstract IdentityUser? GetUserBasicInfo();
protected abstract object? GetUser(Type userType);

public TUserId? GetUserId<TUserId>()
{
Expand All @@ -30,23 +32,33 @@ public abstract class UserContext : IUserSetter, IUserContext
return TypeConvertProvider.ConvertTo<TUserId>(userId);
}

public IdentityUser? GetUser() => GetUser<IdentityUser>();

public TIdentityUser? GetUser<TIdentityUser>() where TIdentityUser : IIdentityUser
{
var user = _currentUser.Value ?? GetUser();
var userModelType = typeof(TIdentityUser);
if (!_currentUser.Value!.TryGetValue(userModelType, out var user) || user == null)
{
user ??= GetUser(userModelType);
_currentUser.Value.TryAdd(userModelType, user);
}
return user == null ? default : (TIdentityUser)user;
}

public IIdentityUser? GetUserSimple() => GetUser<IdentityUser>();

public IDisposable Change<TIdentityUser>(TIdentityUser identityUser) where TIdentityUser : IIdentityUser
{
var user = GetUser();
_currentUser.Value = identityUser;
return new DisposeAction(() => _currentUser.Value = user);
var userModelType = typeof(TIdentityUser);
var user = GetUser(userModelType);
_currentUser.Value![userModelType] = identityUser;
return new DisposeAction(() => _currentUser.Value[userModelType] = user);
}

public IEnumerable<TRoleId> GetUserRoles<TRoleId>()
{
return GetUserSimple()?.Roles.Select(r => TypeConvertProvider.ConvertTo<TRoleId>(r)) ?? new List<TRoleId>();
return GetUserSimple()?.Roles
.Select(r => TypeConvertProvider.ConvertTo<TRoleId>(r) ??
throw new ArgumentException($"RoleId cannot be converted to [{typeof(TRoleId).Name}]")) ?? new List<TRoleId>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

global using Masa.BuildingBlocks.Authentication.Identity.Internal;
global using System.ComponentModel;
global using Masa.BuildingBlocks.Data;
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace Masa.BuildingBlocks.Authentication.Identity;
namespace Masa.BuildingBlocks.Data;

public interface ITypeConvertProvider
public enum DataType
{
T ConvertTo<T>(string value);
Json = 1,
Xml = 2,
Yml = 3
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Microsoft.Extensions.DependencyInjection;

public static class ServiceCollectionExtensions
public static partial class ServiceCollectionExtensions
{
public static IServiceCollection AddIdGeneratorCore(this IServiceCollection services)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace Masa.BuildingBlocks.Data;

public class DefaultDeserializerFactory : IDeserializerFactory
{
private readonly IServiceProvider _serviceProvider;
private readonly IOptions<DeserializerFactoryOptions> _deserializerFactoryOptions;
private readonly DeserializerRelationOptions? _defaultDeserializerOptions;

public DefaultDeserializerFactory(IServiceProvider serviceProvider, IOptions<DeserializerFactoryOptions> deserializerFactoryOptions)
{
_serviceProvider = serviceProvider;
_deserializerFactoryOptions = deserializerFactoryOptions;
_defaultDeserializerOptions = deserializerFactoryOptions.Value.Options.FirstOrDefault(options
=> options.Name == Options.DefaultName) ??
deserializerFactoryOptions.Value.Options.FirstOrDefault();
}

public IDeserializer Create()
{
if (_defaultDeserializerOptions == null)
throw new NotImplementedException("Default deserializer not found, you need to add it, like services.AddJson()");

return _defaultDeserializerOptions.Func.Invoke(_serviceProvider);
}

public IDeserializer Create(string name)
{
var deserializerOptions =
_deserializerFactoryOptions.Value.Options.FirstOrDefault(options
=> options.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
if (deserializerOptions == null)
throw new NotImplementedException($"No deserializer found for 【{name}】");

return deserializerOptions.Func.Invoke(_serviceProvider);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace Masa.BuildingBlocks.Data;

public class DefaultSerializerFactory : ISerializerFactory
{
private readonly IServiceProvider _serviceProvider;
private readonly IOptions<SerializerFactoryOptions> _serializerFactoryOptions;
private readonly SerializerRelationOptions? _defaultSerializerOptions;

public DefaultSerializerFactory(IServiceProvider serviceProvider, IOptions<SerializerFactoryOptions> serializerFactoryOptions)
{
_serviceProvider = serviceProvider;
_serializerFactoryOptions = serializerFactoryOptions;
_defaultSerializerOptions = serializerFactoryOptions.Value.Options.FirstOrDefault(options
=> options.Name == Options.DefaultName) ??
serializerFactoryOptions.Value.Options.FirstOrDefault();
}

public ISerializer Create()
{
if (_defaultSerializerOptions == null)
throw new NotImplementedException("Default serializer not found, you need to add it, like services.AddJson()");

return _defaultSerializerOptions.Func.Invoke(_serviceProvider);
}

public ISerializer Create(string name)
{
var serializerOptions =
_serializerFactoryOptions.Value.Options.FirstOrDefault(options
=> options.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
if (serializerOptions == null)
throw new NotImplementedException($"No serializer found for 【{name}】");

return serializerOptions.Func.Invoke(_serviceProvider);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace Microsoft.Extensions.DependencyInjection;

public static partial class ServiceCollectionExtensions
{
public static IServiceCollection AddSerializationCore(this IServiceCollection services)
{
services.TryAddSingleton<IDeserializerFactory, DefaultDeserializerFactory>();
services.TryAddSingleton<ISerializerFactory, DefaultSerializerFactory>();
services.TryAddSingleton(serviceProvider => serviceProvider.GetRequiredService<ISerializerFactory>().Create());
services.TryAddSingleton(serviceProvider => serviceProvider.GetRequiredService<IDeserializerFactory>().Create());
return services;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace Masa.BuildingBlocks.Data;

public interface IDeserializer
{
TValue? Deserialize<TValue>(string value);

object? Deserialize(string value, Type valueType);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace Masa.BuildingBlocks.Data;

public interface IDeserializerFactory
{
IDeserializer Create();

IDeserializer Create(string name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace Masa.BuildingBlocks.Data;

public interface ISerializer
{
string Serialize<TValue>(TValue value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace Masa.BuildingBlocks.Data;

public interface ISerializerFactory
{
public ISerializer Create();

ISerializer Create(string name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace Masa.BuildingBlocks.Data;

public interface IJsonDeserializer : IDeserializer
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace Masa.BuildingBlocks.Data;

public interface IJsonSerializer : ISerializer
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace Masa.BuildingBlocks.Data;

public interface IYamlDeserializer : IDeserializer
{

}
Loading