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