Add user
This commit is contained in:
parent
f406854dae
commit
fe9edd891b
@ -1,4 +1,4 @@
|
|||||||
namespace Nocr.Users.Api.Contracts.Users;
|
namespace Nocr.Users.Api.Contracts.Users.Dto;
|
||||||
|
|
||||||
public sealed class CreateUserRequest
|
public sealed class CreateUserRequest
|
||||||
{
|
{
|
||||||
@ -7,4 +7,6 @@ public sealed class CreateUserRequest
|
|||||||
public string? Email { get; set; }
|
public string? Email { get; set; }
|
||||||
|
|
||||||
public long? TelegramId { get; set; }
|
public long? TelegramId { get; set; }
|
||||||
|
|
||||||
|
public string? TelegramUsername { get; set; }
|
||||||
}
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
using Nocr.Users.Api.Contracts.Users.Dto;
|
||||||
using RestEase;
|
using RestEase;
|
||||||
|
|
||||||
namespace Nocr.Users.Api.Contracts.Users;
|
namespace Nocr.Users.Api.Contracts.Users;
|
||||||
@ -7,4 +8,7 @@ public interface IUsersController
|
|||||||
{
|
{
|
||||||
[Post]
|
[Post]
|
||||||
Task<long> Create([Body] CreateUserRequest request, CancellationToken cancellationToken = default);
|
Task<long> Create([Body] CreateUserRequest request, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
[Get(WebRoutes.Users.ById)]
|
||||||
|
Task<UserData?> GetById([Path] long id, CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
||||||
8
src/Nocr.Users.Api.Contracts/Users/UserData.cs
Normal file
8
src/Nocr.Users.Api.Contracts/Users/UserData.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Nocr.Users.Api.Contracts.Users;
|
||||||
|
|
||||||
|
public sealed class UserData
|
||||||
|
{
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
public string Username { get; set; }
|
||||||
|
}
|
||||||
@ -7,5 +7,7 @@ public static class WebRoutes
|
|||||||
public static class Users
|
public static class Users
|
||||||
{
|
{
|
||||||
public const string Path = BasePath + "/" + "users";
|
public const string Path = BasePath + "/" + "users";
|
||||||
|
|
||||||
|
public const string ById = "{id}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9,6 +9,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Nocr.Users.Api.Contracts\Nocr.Users.Api.Contracts.csproj" />
|
||||||
<ProjectReference Include="..\Nocr.Users.Core\Nocr.Users.Core.csproj" />
|
<ProjectReference Include="..\Nocr.Users.Core\Nocr.Users.Core.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Nocr.Users.AppServices.Users;
|
||||||
|
|
||||||
namespace Nocr.Users.AppServices;
|
namespace Nocr.Users.AppServices;
|
||||||
|
|
||||||
@ -10,6 +11,8 @@ public static class ServiceCollectionExtensions
|
|||||||
throw new ArgumentNullException(nameof(services));
|
throw new ArgumentNullException(nameof(services));
|
||||||
|
|
||||||
// Add registrations here
|
// Add registrations here
|
||||||
|
services.AddScoped<IUsersRepository, InMemoryUsersRepository>();
|
||||||
|
services.AddScoped<IUsersService, UsersService>();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|||||||
8
src/Nocr.Users.AppServices/Users/IUsersRepository.cs
Normal file
8
src/Nocr.Users.AppServices/Users/IUsersRepository.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Nocr.Users.AppServices.Users;
|
||||||
|
|
||||||
|
public interface IUsersRepository
|
||||||
|
{
|
||||||
|
Task<long> Create(User user, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
Task<User?> GetUserById(long id, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
11
src/Nocr.Users.AppServices/Users/IUsersService.cs
Normal file
11
src/Nocr.Users.AppServices/Users/IUsersService.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using Nocr.Users.Api.Contracts.Users;
|
||||||
|
|
||||||
|
namespace Nocr.Users.AppServices.Users;
|
||||||
|
|
||||||
|
public interface IUsersService
|
||||||
|
{
|
||||||
|
Task<long> Create(string username, string? telegramUsername, string? email, long? telegramId,
|
||||||
|
CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
Task<UserData?> GetUserById(long id, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
29
src/Nocr.Users.AppServices/Users/InMemoryUsersRepository.cs
Normal file
29
src/Nocr.Users.AppServices/Users/InMemoryUsersRepository.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
namespace Nocr.Users.AppServices.Users;
|
||||||
|
|
||||||
|
public sealed class InMemoryUsersRepository : IUsersRepository
|
||||||
|
{
|
||||||
|
private long _id = 0;
|
||||||
|
|
||||||
|
private long _userIdentityId = 0;
|
||||||
|
|
||||||
|
private readonly List<User> _users = new();
|
||||||
|
|
||||||
|
public Task<long> Create(User user, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var id = Interlocked.Increment(ref _id);
|
||||||
|
user.Id = id;
|
||||||
|
_users.Add(user);
|
||||||
|
|
||||||
|
foreach (var identity in user.Identities)
|
||||||
|
{
|
||||||
|
identity.Id = Interlocked.Increment(ref _userIdentityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<User?> GetUserById(long id, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return Task.FromResult(_users.FirstOrDefault(x => x.Id == id));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,18 +6,30 @@ public sealed class User
|
|||||||
|
|
||||||
public string Username { get; private set; }
|
public string Username { get; private set; }
|
||||||
|
|
||||||
private User(string username)
|
private List<UserIdentity> _identities = new List<UserIdentity>();
|
||||||
|
|
||||||
|
public IReadOnlyCollection<UserIdentity> Identities => _identities;
|
||||||
|
|
||||||
|
private User(string username, params UserIdentity[] identities)
|
||||||
{
|
{
|
||||||
Username = username;
|
Username = username;
|
||||||
|
|
||||||
|
// TODO: Check that there is no repeating identity types
|
||||||
|
_identities.AddRange(identities);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static User Initialize(string username)
|
public static User Initialize(string username, params UserIdentity[] identities)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(username))
|
if (string.IsNullOrWhiteSpace(username))
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(username));
|
throw new ArgumentNullException(nameof(username));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new User(username);
|
if (username.Length is < 5 or > 32)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Username length should be between 5 and 32 symbols", username);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new User(username, identities);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
34
src/Nocr.Users.AppServices/Users/UserIdentity.cs
Normal file
34
src/Nocr.Users.AppServices/Users/UserIdentity.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
namespace Nocr.Users.AppServices.Users;
|
||||||
|
|
||||||
|
public sealed class UserIdentity
|
||||||
|
{
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
public string Identity { get; private set; }
|
||||||
|
|
||||||
|
public UserIdentityType IdentityType { get; private set; }
|
||||||
|
|
||||||
|
private UserIdentity(string identity, UserIdentityType identityType)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(identity))
|
||||||
|
throw new ArgumentNullException(nameof(identity));
|
||||||
|
|
||||||
|
Identity = identity;
|
||||||
|
IdentityType = identityType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UserIdentity TelegramId(string identity)
|
||||||
|
{
|
||||||
|
return new UserIdentity(identity, UserIdentityType.TelegramId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UserIdentity TelegramUsername(string identity)
|
||||||
|
{
|
||||||
|
return new UserIdentity(identity, UserIdentityType.TelegramUsername);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UserIdentity Email(string identity)
|
||||||
|
{
|
||||||
|
return new UserIdentity(identity, UserIdentityType.TelegramUsername);
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/Nocr.Users.AppServices/Users/UserIdentityType.cs
Normal file
8
src/Nocr.Users.AppServices/Users/UserIdentityType.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Nocr.Users.AppServices.Users;
|
||||||
|
|
||||||
|
public enum UserIdentityType
|
||||||
|
{
|
||||||
|
Email = 1,
|
||||||
|
TelegramId = 2,
|
||||||
|
TelegramUsername = 3,
|
||||||
|
}
|
||||||
46
src/Nocr.Users.AppServices/Users/UsersService.cs
Normal file
46
src/Nocr.Users.AppServices/Users/UsersService.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using Nocr.Users.Api.Contracts.Users;
|
||||||
|
|
||||||
|
namespace Nocr.Users.AppServices.Users;
|
||||||
|
|
||||||
|
public sealed class UsersService : IUsersService
|
||||||
|
{
|
||||||
|
private readonly IUsersRepository _repository;
|
||||||
|
|
||||||
|
public UsersService(IUsersRepository repository)
|
||||||
|
{
|
||||||
|
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<long> Create(string username, string? telegramUsername, string? email, long? telegramId,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var identities = new List<UserIdentity>();
|
||||||
|
|
||||||
|
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<UserData?> GetUserById(long id, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var user = await _repository.GetUserById(id, cancellationToken);
|
||||||
|
if (user == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new UserData
|
||||||
|
{
|
||||||
|
Id = user.Id,
|
||||||
|
Username = user.Username,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
30
src/Nocr.Users.Host/Controllers/UsersController.cs
Normal file
30
src/Nocr.Users.Host/Controllers/UsersController.cs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Nocr.Users.Api.Contracts;
|
||||||
|
using Nocr.Users.Api.Contracts.Users;
|
||||||
|
using Nocr.Users.Api.Contracts.Users.Dto;
|
||||||
|
using Nocr.Users.AppServices.Users;
|
||||||
|
|
||||||
|
namespace Nocr.Users.Host;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route(WebRoutes.Users.Path)]
|
||||||
|
public class UsersController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IUsersService _usersService;
|
||||||
|
|
||||||
|
public UsersController(IUsersService usersService)
|
||||||
|
{
|
||||||
|
_usersService = usersService ?? throw new ArgumentNullException(nameof(usersService));
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public Task<long> Create([FromBody] CreateUserRequest request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return _usersService.Create(request.Username, request.TelegramUsername, request.Email, request.TelegramId, cancellationToken);
|
||||||
|
}
|
||||||
|
[HttpGet("{id}")]
|
||||||
|
public Task<UserData?> GetById([FromRoute] long id, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return _usersService.GetUserById(id, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,7 +12,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Nocr.Users.AppServices\Nocr.Users.AppServices.csproj"/>
|
<ProjectReference Include="..\Nocr.Users.Api.Contracts\Nocr.Users.Api.Contracts.csproj" />
|
||||||
|
<ProjectReference Include="..\Nocr.Users.AppServices\Nocr.Users.AppServices.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user