From f5ee811d17965467f54dbb3f0722626dd183de2c Mon Sep 17 00:00:00 2001 From: Sergey Nazarov Date: Sat, 23 Mar 2024 10:59:56 +0400 Subject: [PATCH] Add GetByIdentity method --- Nocr.Users.sln | 6 ++++ .../Nocr.Users.Api.Contracts.csproj | 4 +++ .../Dto/{ => Requests}/CreateUserRequest.cs | 2 +- .../Users/Dto/UserData.cs | 2 ++ .../Users/Dto/UserIdentityData.cs | 12 +++++++ .../Users/IUsersController.cs | 5 +++ src/Nocr.Users.Api.Contracts/WebRoutes.cs | 2 ++ .../Nocr.Users.AppServices.Contracts.csproj | 9 +++++ .../Users/UserIdentityType.cs | 2 +- .../Nocr.Users.AppServices.csproj | 1 + .../Users/Repositories/IUsersRepository.cs | 4 +++ .../Repositories/InMemoryUsersRepository.cs | 15 ++++++-- .../Users/Services/IUsersService.cs | 3 ++ .../Users/Services/UsersService.cs | 34 ++++++++++++++++--- .../Users/UserIdentity.cs | 2 ++ .../Controllers/UsersController.cs | 9 +++++ 16 files changed, 104 insertions(+), 8 deletions(-) rename src/Nocr.Users.Api.Contracts/Users/Dto/{ => Requests}/CreateUserRequest.cs (80%) create mode 100644 src/Nocr.Users.Api.Contracts/Users/Dto/UserIdentityData.cs create mode 100644 src/Nocr.Users.AppServices.Contracts/Nocr.Users.AppServices.Contracts.csproj rename src/{Nocr.Users.AppServices => Nocr.Users.AppServices.Contracts}/Users/UserIdentityType.cs (65%) diff --git a/Nocr.Users.sln b/Nocr.Users.sln index 47434f5..23ac39a 100644 --- a/Nocr.Users.sln +++ b/Nocr.Users.sln @@ -16,6 +16,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nocr.Users.Host", "src\Nocr 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}" 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 GlobalSection(SolutionConfigurationPlatforms) = preSolution 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}.Release|Any CPU.ActiveCfg = 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 EndGlobal diff --git a/src/Nocr.Users.Api.Contracts/Nocr.Users.Api.Contracts.csproj b/src/Nocr.Users.Api.Contracts/Nocr.Users.Api.Contracts.csproj index f5671d9..336343d 100644 --- a/src/Nocr.Users.Api.Contracts/Nocr.Users.Api.Contracts.csproj +++ b/src/Nocr.Users.Api.Contracts/Nocr.Users.Api.Contracts.csproj @@ -10,4 +10,8 @@ + + + + diff --git a/src/Nocr.Users.Api.Contracts/Users/Dto/CreateUserRequest.cs b/src/Nocr.Users.Api.Contracts/Users/Dto/Requests/CreateUserRequest.cs similarity index 80% rename from src/Nocr.Users.Api.Contracts/Users/Dto/CreateUserRequest.cs rename to src/Nocr.Users.Api.Contracts/Users/Dto/Requests/CreateUserRequest.cs index 3db4d0e..6cbc960 100644 --- a/src/Nocr.Users.Api.Contracts/Users/Dto/CreateUserRequest.cs +++ b/src/Nocr.Users.Api.Contracts/Users/Dto/Requests/CreateUserRequest.cs @@ -1,4 +1,4 @@ -namespace Nocr.Users.Api.Contracts.Users.Dto; +namespace Nocr.Users.Api.Contracts.Users.Dto.Requests; public sealed class CreateUserRequest { diff --git a/src/Nocr.Users.Api.Contracts/Users/Dto/UserData.cs b/src/Nocr.Users.Api.Contracts/Users/Dto/UserData.cs index d793aa5..7044876 100644 --- a/src/Nocr.Users.Api.Contracts/Users/Dto/UserData.cs +++ b/src/Nocr.Users.Api.Contracts/Users/Dto/UserData.cs @@ -5,4 +5,6 @@ public sealed class UserData public long Id { get; set; } public string Username { get; set; } + + public UserIdentityData[] Identities { get; set; } } \ No newline at end of file diff --git a/src/Nocr.Users.Api.Contracts/Users/Dto/UserIdentityData.cs b/src/Nocr.Users.Api.Contracts/Users/Dto/UserIdentityData.cs new file mode 100644 index 0000000..be84ed3 --- /dev/null +++ b/src/Nocr.Users.Api.Contracts/Users/Dto/UserIdentityData.cs @@ -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; } +} \ No newline at end of file diff --git a/src/Nocr.Users.Api.Contracts/Users/IUsersController.cs b/src/Nocr.Users.Api.Contracts/Users/IUsersController.cs index ac25179..e888cce 100644 --- a/src/Nocr.Users.Api.Contracts/Users/IUsersController.cs +++ b/src/Nocr.Users.Api.Contracts/Users/IUsersController.cs @@ -1,4 +1,6 @@ using Nocr.Users.Api.Contracts.Users.Dto; +using Nocr.Users.Api.Contracts.Users.Dto.Requests; +using Nocr.Users.AppServices.Contracts.Users; using RestEase; namespace Nocr.Users.Api.Contracts.Users; @@ -11,4 +13,7 @@ public interface IUsersController [Get(WebRoutes.Users.ById)] Task GetById([Path] long id, CancellationToken cancellationToken = default); + + [Get(WebRoutes.Users.ByIdentity)] + Task GetByIdentity([Query] UserIdentityType identityType, [Query] string identity, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/src/Nocr.Users.Api.Contracts/WebRoutes.cs b/src/Nocr.Users.Api.Contracts/WebRoutes.cs index ffbcafb..4b3b969 100644 --- a/src/Nocr.Users.Api.Contracts/WebRoutes.cs +++ b/src/Nocr.Users.Api.Contracts/WebRoutes.cs @@ -9,5 +9,7 @@ public static class WebRoutes public const string Path = BasePath + "/" + "users"; public const string ById = "{id}"; + + public const string ByIdentity = "identity"; } } \ No newline at end of file diff --git a/src/Nocr.Users.AppServices.Contracts/Nocr.Users.AppServices.Contracts.csproj b/src/Nocr.Users.AppServices.Contracts/Nocr.Users.AppServices.Contracts.csproj new file mode 100644 index 0000000..3a63532 --- /dev/null +++ b/src/Nocr.Users.AppServices.Contracts/Nocr.Users.AppServices.Contracts.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/src/Nocr.Users.AppServices/Users/UserIdentityType.cs b/src/Nocr.Users.AppServices.Contracts/Users/UserIdentityType.cs similarity index 65% rename from src/Nocr.Users.AppServices/Users/UserIdentityType.cs rename to src/Nocr.Users.AppServices.Contracts/Users/UserIdentityType.cs index 01b6fec..b312ba7 100644 --- a/src/Nocr.Users.AppServices/Users/UserIdentityType.cs +++ b/src/Nocr.Users.AppServices.Contracts/Users/UserIdentityType.cs @@ -1,4 +1,4 @@ -namespace Nocr.Users.AppServices.Users; +namespace Nocr.Users.AppServices.Contracts.Users; public enum UserIdentityType { diff --git a/src/Nocr.Users.AppServices/Nocr.Users.AppServices.csproj b/src/Nocr.Users.AppServices/Nocr.Users.AppServices.csproj index b7146b5..1bd4ec1 100644 --- a/src/Nocr.Users.AppServices/Nocr.Users.AppServices.csproj +++ b/src/Nocr.Users.AppServices/Nocr.Users.AppServices.csproj @@ -10,6 +10,7 @@ + diff --git a/src/Nocr.Users.AppServices/Users/Repositories/IUsersRepository.cs b/src/Nocr.Users.AppServices/Users/Repositories/IUsersRepository.cs index 3ecc5d5..7696646 100644 --- a/src/Nocr.Users.AppServices/Users/Repositories/IUsersRepository.cs +++ b/src/Nocr.Users.AppServices/Users/Repositories/IUsersRepository.cs @@ -1,3 +1,5 @@ +using Nocr.Users.AppServices.Contracts.Users; + namespace Nocr.Users.AppServices.Users.Repositories; public interface IUsersRepository @@ -5,4 +7,6 @@ public interface IUsersRepository Task Create(User user, CancellationToken cancellationToken = default); Task GetUserById(long id, CancellationToken cancellationToken = default); + + Task GetByIdentity(UserIdentityType identityType, string identity, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/src/Nocr.Users.AppServices/Users/Repositories/InMemoryUsersRepository.cs b/src/Nocr.Users.AppServices/Users/Repositories/InMemoryUsersRepository.cs index 4f31b5a..473c912 100644 --- a/src/Nocr.Users.AppServices/Users/Repositories/InMemoryUsersRepository.cs +++ b/src/Nocr.Users.AppServices/Users/Repositories/InMemoryUsersRepository.cs @@ -1,3 +1,5 @@ +using Nocr.Users.AppServices.Contracts.Users; + namespace Nocr.Users.AppServices.Users.Repositories; public sealed class InMemoryUsersRepository : IUsersRepository @@ -5,7 +7,7 @@ public sealed class InMemoryUsersRepository : IUsersRepository private long _id = 0; private long _userIdentityId = 0; - + private readonly List _users = new(); public Task Create(User user, CancellationToken cancellationToken = default) @@ -18,7 +20,7 @@ public sealed class InMemoryUsersRepository : IUsersRepository { identity.Id = Interlocked.Increment(ref _userIdentityId); } - + return Task.FromResult(id); } @@ -26,4 +28,13 @@ public sealed class InMemoryUsersRepository : IUsersRepository { return Task.FromResult(_users.FirstOrDefault(x => x.Id == id)); } + + public Task 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); + } } \ No newline at end of file diff --git a/src/Nocr.Users.AppServices/Users/Services/IUsersService.cs b/src/Nocr.Users.AppServices/Users/Services/IUsersService.cs index 2ce5f27..5d2e3be 100644 --- a/src/Nocr.Users.AppServices/Users/Services/IUsersService.cs +++ b/src/Nocr.Users.AppServices/Users/Services/IUsersService.cs @@ -1,4 +1,5 @@ using Nocr.Users.Api.Contracts.Users.Dto; +using Nocr.Users.AppServices.Contracts.Users; namespace Nocr.Users.AppServices.Users.Services; @@ -8,4 +9,6 @@ public interface IUsersService CancellationToken cancellationToken = default); Task GetById(long id, CancellationToken cancellationToken = default); + + Task GetByIdentity(UserIdentityType identityType, string identity, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/src/Nocr.Users.AppServices/Users/Services/UsersService.cs b/src/Nocr.Users.AppServices/Users/Services/UsersService.cs index a88a7c5..efaf0e5 100644 --- a/src/Nocr.Users.AppServices/Users/Services/UsersService.cs +++ b/src/Nocr.Users.AppServices/Users/Services/UsersService.cs @@ -1,4 +1,5 @@ using Nocr.Users.Api.Contracts.Users.Dto; +using Nocr.Users.AppServices.Contracts.Users; using Nocr.Users.AppServices.Users.Repositories; namespace Nocr.Users.AppServices.Users.Services; @@ -19,22 +20,36 @@ public sealed class UsersService : IUsersService if (!string.IsNullOrWhiteSpace(email)) identities.Add(UserIdentity.Email(email)); - + if (!string.IsNullOrWhiteSpace(telegramUsername)) identities.Add(UserIdentity.TelegramUsername(telegramUsername)); - + if (telegramId.HasValue) identities.Add(UserIdentity.TelegramId(telegramId.Value.ToString())); - + // TODO: ToArray = грубо var user = User.Initialize(username, identities.ToArray()); - + return await _repository.Create(user, cancellationToken); } public async Task GetById(long id, CancellationToken cancellationToken = default) { var user = await _repository.GetUserById(id, cancellationToken); + + return MapToUserData(user); + } + + public async Task 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) return null; @@ -42,6 +57,17 @@ public sealed class UsersService : IUsersService { Id = user.Id, 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 }; } } \ No newline at end of file diff --git a/src/Nocr.Users.AppServices/Users/UserIdentity.cs b/src/Nocr.Users.AppServices/Users/UserIdentity.cs index db281ee..0de861b 100644 --- a/src/Nocr.Users.AppServices/Users/UserIdentity.cs +++ b/src/Nocr.Users.AppServices/Users/UserIdentity.cs @@ -1,3 +1,5 @@ +using Nocr.Users.AppServices.Contracts.Users; + namespace Nocr.Users.AppServices.Users; public sealed class UserIdentity diff --git a/src/Nocr.Users.Host/Controllers/UsersController.cs b/src/Nocr.Users.Host/Controllers/UsersController.cs index d6e8cc2..9926c55 100644 --- a/src/Nocr.Users.Host/Controllers/UsersController.cs +++ b/src/Nocr.Users.Host/Controllers/UsersController.cs @@ -1,6 +1,8 @@ using Microsoft.AspNetCore.Mvc; using Nocr.Users.Api.Contracts; 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; namespace Nocr.Users.Host.Controllers; @@ -28,4 +30,11 @@ public class UsersController : ControllerBase { return _usersService.GetById(id, cancellationToken); } + + [HttpGet(WebRoutes.Users.ByIdentity)] + public Task GetByIdentity([FromQuery] UserIdentityType identityType, [FromQuery] string identity, + CancellationToken cancellationToken = default) + { + return _usersService.GetByIdentity(identityType, identity, cancellationToken); + } } \ No newline at end of file