Add GetByIdentity method

This commit is contained in:
Sergey Nazarov 2024-03-23 10:59:56 +04:00
parent e7e2610da1
commit f5ee811d17
16 changed files with 104 additions and 8 deletions

View File

@ -16,6 +16,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nocr.Users.Host", "src\Nocr
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nocr.Users.Api.Contracts", "src\Nocr.Users.Api.Contracts\Nocr.Users.Api.Contracts.csproj", "{4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nocr.Users.Api.Contracts", "src\Nocr.Users.Api.Contracts\Nocr.Users.Api.Contracts.csproj", "{4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nocr.Users.AppServices.Contracts", "src\Nocr.Users.AppServices.Contracts\Nocr.Users.AppServices.Contracts.csproj", "{51DCF618-41C0-432A-8FD0-3EA3B70B375D}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -38,5 +40,9 @@ Global
{4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E}.Debug|Any CPU.Build.0 = Debug|Any CPU {4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E}.Release|Any CPU.ActiveCfg = Release|Any CPU {4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E}.Release|Any CPU.Build.0 = Release|Any CPU {4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E}.Release|Any CPU.Build.0 = Release|Any CPU
{51DCF618-41C0-432A-8FD0-3EA3B70B375D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{51DCF618-41C0-432A-8FD0-3EA3B70B375D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51DCF618-41C0-432A-8FD0-3EA3B70B375D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51DCF618-41C0-432A-8FD0-3EA3B70B375D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -10,4 +10,8 @@
<PackageReference Include="RestEase" /> <PackageReference Include="RestEase" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Nocr.Users.AppServices.Contracts\Nocr.Users.AppServices.Contracts.csproj" />
</ItemGroup>
</Project> </Project>

View File

@ -1,4 +1,4 @@
namespace Nocr.Users.Api.Contracts.Users.Dto; namespace Nocr.Users.Api.Contracts.Users.Dto.Requests;
public sealed class CreateUserRequest public sealed class CreateUserRequest
{ {

View File

@ -5,4 +5,6 @@ public sealed class UserData
public long Id { get; set; } public long Id { get; set; }
public string Username { get; set; } public string Username { get; set; }
public UserIdentityData[] Identities { get; set; }
} }

View File

@ -0,0 +1,12 @@
using Nocr.Users.AppServices.Contracts.Users;
namespace Nocr.Users.Api.Contracts.Users.Dto;
public sealed class UserIdentityData
{
public long Id { get; set; }
public UserIdentityType Type { get; set; }
public string Identity { get; set; }
}

View File

@ -1,4 +1,6 @@
using Nocr.Users.Api.Contracts.Users.Dto; using Nocr.Users.Api.Contracts.Users.Dto;
using Nocr.Users.Api.Contracts.Users.Dto.Requests;
using Nocr.Users.AppServices.Contracts.Users;
using RestEase; using RestEase;
namespace Nocr.Users.Api.Contracts.Users; namespace Nocr.Users.Api.Contracts.Users;
@ -11,4 +13,7 @@ public interface IUsersController
[Get(WebRoutes.Users.ById)] [Get(WebRoutes.Users.ById)]
Task<UserData?> GetById([Path] long id, CancellationToken cancellationToken = default); Task<UserData?> GetById([Path] long id, CancellationToken cancellationToken = default);
[Get(WebRoutes.Users.ByIdentity)]
Task<UserData?> GetByIdentity([Query] UserIdentityType identityType, [Query] string identity, CancellationToken cancellationToken = default);
} }

View File

@ -9,5 +9,7 @@ public static class WebRoutes
public const string Path = BasePath + "/" + "users"; public const string Path = BasePath + "/" + "users";
public const string ById = "{id}"; public const string ById = "{id}";
public const string ByIdentity = "identity";
} }
} }

View File

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -1,4 +1,4 @@
namespace Nocr.Users.AppServices.Users; namespace Nocr.Users.AppServices.Contracts.Users;
public enum UserIdentityType public enum UserIdentityType
{ {

View File

@ -10,6 +10,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Nocr.Users.Api.Contracts\Nocr.Users.Api.Contracts.csproj" /> <ProjectReference Include="..\Nocr.Users.Api.Contracts\Nocr.Users.Api.Contracts.csproj" />
<ProjectReference Include="..\Nocr.Users.AppServices.Contracts\Nocr.Users.AppServices.Contracts.csproj" />
<ProjectReference Include="..\Nocr.Users.Core\Nocr.Users.Core.csproj" /> <ProjectReference Include="..\Nocr.Users.Core\Nocr.Users.Core.csproj" />
</ItemGroup> </ItemGroup>

View File

@ -1,3 +1,5 @@
using Nocr.Users.AppServices.Contracts.Users;
namespace Nocr.Users.AppServices.Users.Repositories; namespace Nocr.Users.AppServices.Users.Repositories;
public interface IUsersRepository public interface IUsersRepository
@ -5,4 +7,6 @@ public interface IUsersRepository
Task<long> Create(User user, CancellationToken cancellationToken = default); Task<long> Create(User user, CancellationToken cancellationToken = default);
Task<User?> GetUserById(long id, CancellationToken cancellationToken = default); Task<User?> GetUserById(long id, CancellationToken cancellationToken = default);
Task<User?> GetByIdentity(UserIdentityType identityType, string identity, CancellationToken cancellationToken = default);
} }

View File

@ -1,3 +1,5 @@
using Nocr.Users.AppServices.Contracts.Users;
namespace Nocr.Users.AppServices.Users.Repositories; namespace Nocr.Users.AppServices.Users.Repositories;
public sealed class InMemoryUsersRepository : IUsersRepository public sealed class InMemoryUsersRepository : IUsersRepository
@ -5,7 +7,7 @@ public sealed class InMemoryUsersRepository : IUsersRepository
private long _id = 0; private long _id = 0;
private long _userIdentityId = 0; private long _userIdentityId = 0;
private readonly List<User> _users = new(); private readonly List<User> _users = new();
public Task<long> Create(User user, CancellationToken cancellationToken = default) public Task<long> Create(User user, CancellationToken cancellationToken = default)
@ -18,7 +20,7 @@ public sealed class InMemoryUsersRepository : IUsersRepository
{ {
identity.Id = Interlocked.Increment(ref _userIdentityId); identity.Id = Interlocked.Increment(ref _userIdentityId);
} }
return Task.FromResult(id); return Task.FromResult(id);
} }
@ -26,4 +28,13 @@ public sealed class InMemoryUsersRepository : IUsersRepository
{ {
return Task.FromResult(_users.FirstOrDefault(x => x.Id == id)); return Task.FromResult(_users.FirstOrDefault(x => x.Id == id));
} }
public Task<User?> GetByIdentity(UserIdentityType identityType, string identity,
CancellationToken cancellationToken = default)
{
var user = _users.SingleOrDefault(x => x.Identities.Any(i =>
i.Type == identityType && i.Identity.Equals(identity, StringComparison.OrdinalIgnoreCase)));
return Task.FromResult(user);
}
} }

View File

@ -1,4 +1,5 @@
using Nocr.Users.Api.Contracts.Users.Dto; using Nocr.Users.Api.Contracts.Users.Dto;
using Nocr.Users.AppServices.Contracts.Users;
namespace Nocr.Users.AppServices.Users.Services; namespace Nocr.Users.AppServices.Users.Services;
@ -8,4 +9,6 @@ public interface IUsersService
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
Task<UserData?> GetById(long id, CancellationToken cancellationToken = default); Task<UserData?> GetById(long id, CancellationToken cancellationToken = default);
Task<UserData?> GetByIdentity(UserIdentityType identityType, string identity, CancellationToken cancellationToken = default);
} }

View File

@ -1,4 +1,5 @@
using Nocr.Users.Api.Contracts.Users.Dto; using Nocr.Users.Api.Contracts.Users.Dto;
using Nocr.Users.AppServices.Contracts.Users;
using Nocr.Users.AppServices.Users.Repositories; using Nocr.Users.AppServices.Users.Repositories;
namespace Nocr.Users.AppServices.Users.Services; namespace Nocr.Users.AppServices.Users.Services;
@ -19,22 +20,36 @@ public sealed class UsersService : IUsersService
if (!string.IsNullOrWhiteSpace(email)) if (!string.IsNullOrWhiteSpace(email))
identities.Add(UserIdentity.Email(email)); identities.Add(UserIdentity.Email(email));
if (!string.IsNullOrWhiteSpace(telegramUsername)) if (!string.IsNullOrWhiteSpace(telegramUsername))
identities.Add(UserIdentity.TelegramUsername(telegramUsername)); identities.Add(UserIdentity.TelegramUsername(telegramUsername));
if (telegramId.HasValue) if (telegramId.HasValue)
identities.Add(UserIdentity.TelegramId(telegramId.Value.ToString())); identities.Add(UserIdentity.TelegramId(telegramId.Value.ToString()));
// TODO: ToArray = грубо // TODO: ToArray = грубо
var user = User.Initialize(username, identities.ToArray()); var user = User.Initialize(username, identities.ToArray());
return await _repository.Create(user, cancellationToken); return await _repository.Create(user, cancellationToken);
} }
public async Task<UserData?> GetById(long id, CancellationToken cancellationToken = default) public async Task<UserData?> GetById(long id, CancellationToken cancellationToken = default)
{ {
var user = await _repository.GetUserById(id, cancellationToken); var user = await _repository.GetUserById(id, cancellationToken);
return MapToUserData(user);
}
public async Task<UserData?> GetByIdentity(UserIdentityType identityType, string identity,
CancellationToken cancellationToken = default)
{
var user = await _repository.GetByIdentity(identityType, identity, cancellationToken);
return MapToUserData(user);
}
private static UserData? MapToUserData(User? user)
{
if (user == null) if (user == null)
return null; return null;
@ -42,6 +57,17 @@ public sealed class UsersService : IUsersService
{ {
Id = user.Id, Id = user.Id,
Username = user.Username, Username = user.Username,
Identities = user.Identities.Select(MapToUserIdentityData).ToArray()
};
}
private static UserIdentityData MapToUserIdentityData(UserIdentity userIdentity)
{
return new UserIdentityData
{
Id = userIdentity.Id,
Identity = userIdentity.Identity,
Type = userIdentity.Type
}; };
} }
} }

View File

@ -1,3 +1,5 @@
using Nocr.Users.AppServices.Contracts.Users;
namespace Nocr.Users.AppServices.Users; namespace Nocr.Users.AppServices.Users;
public sealed class UserIdentity public sealed class UserIdentity

View File

@ -1,6 +1,8 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Nocr.Users.Api.Contracts; using Nocr.Users.Api.Contracts;
using Nocr.Users.Api.Contracts.Users.Dto; using Nocr.Users.Api.Contracts.Users.Dto;
using Nocr.Users.Api.Contracts.Users.Dto.Requests;
using Nocr.Users.AppServices.Contracts.Users;
using Nocr.Users.AppServices.Users.Services; using Nocr.Users.AppServices.Users.Services;
namespace Nocr.Users.Host.Controllers; namespace Nocr.Users.Host.Controllers;
@ -28,4 +30,11 @@ public class UsersController : ControllerBase
{ {
return _usersService.GetById(id, cancellationToken); return _usersService.GetById(id, cancellationToken);
} }
[HttpGet(WebRoutes.Users.ByIdentity)]
public Task<UserData?> GetByIdentity([FromQuery] UserIdentityType identityType, [FromQuery] string identity,
CancellationToken cancellationToken = default)
{
return _usersService.GetByIdentity(identityType, identity, cancellationToken);
}
} }