Skip to content

Commit 86d8f84

Browse files
Implement user existence check and repository pattern for user management
1 parent 28264ca commit 86d8f84

File tree

8 files changed

+90
-10
lines changed

8 files changed

+90
-10
lines changed

Common/Exceptions/UserAlreadyExistsException.cs

Whitespace-only changes.

Controllers/UsersController.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,12 @@ public UsersController(IMediator mediator)
2222
[AllowAnonymous] // Cho phép tạo user mà không cần authentication
2323
public async Task<IActionResult> Create([FromBody] CreateUserCommand command)
2424
{
25-
var user = await _mediator.Send(command);
26-
return Ok(user);
25+
var result = await _mediator.Send(command);
26+
if (result == null)
27+
{
28+
return ErrorResponse("Username already exists");
29+
}
30+
return SuccessResponse(result);
2731
}
2832

2933
[HttpGet("profile")]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System.Linq.Expressions;
2+
3+
namespace PaymentCoreServiceApi.Core.Interfaces.Repositories.Read;
4+
5+
public interface IBaseReadRepository<TEntity> where TEntity : class
6+
{
7+
Task<TEntity> GetByIdAsync(int id);
8+
Task<IEnumerable<TEntity>> GetAllAsync();
9+
Task<(IEnumerable<TEntity> Items, int TotalCount)> GetPagedAsync(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> predicate);
10+
}

Core/Interfaces/Repositories/Read/IUserReadRepository.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ namespace PaymentCoreServiceApi.Core.Interfaces.Repositories.Read;
22

33
public interface IUserReadRepository
44
{
5-
5+
Task<bool> ExistsAsync(string username);
66
}

Features/Users/Commands/CreateUserCommandHandler.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
using MediatR;
22
using PaymentCoreServiceApi.Core.Entities.UserGenerated;
3+
using PaymentCoreServiceApi.Core.Interfaces.Repositories.Read;
34
using PaymentCoreServiceApi.Core.Interfaces.Repositories.Write;
45

56
namespace PaymentCoreServiceApi.Features.Users.Commands;
67

78
public class CreateUserCommandHandler : IRequestHandler<CreateUserCommand, User>
89
{
910
private readonly IUserWriteRepository _userWriteRepository;
10-
11-
public CreateUserCommandHandler(IUserWriteRepository userWriteRepository)
11+
private readonly IUserReadRepository _userReadRepository;
12+
public CreateUserCommandHandler(IUserWriteRepository userWriteRepository, IUserReadRepository userReadRepository)
1213
{
1314
_userWriteRepository = userWriteRepository;
15+
_userReadRepository = userReadRepository;
1416
}
1517

1618
public async Task<User> Handle(CreateUserCommand request, CancellationToken cancellationToken)
1719
{
20+
if (await _userReadRepository.ExistsAsync(request.UserName))
21+
{
22+
return null;
23+
}
1824
try
1925
{
2026
var user = new User
@@ -26,13 +32,12 @@ public async Task<User> Handle(CreateUserCommand request, CancellationToken canc
2632
Age = request.Age,
2733
Email = request.Email,
2834
UserName = request.UserName,
29-
Password = request.Password, // Note: In production, hash this password
35+
Password = request.Password,
3036
PhoneNumber = request.PhoneNumber,
3137
Address = request.Address,
3238
Active = true
3339
};
3440

35-
// Add the user without auto-commit
3641
var result = await _userWriteRepository.AddAsync(user);
3742
await _userWriteRepository.CommitAsync();
3843
return result;

Infrastructure/Extensions/ServiceCollectionExtensions.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
using Microsoft.Extensions.Configuration;
44
using Microsoft.Extensions.DependencyInjection;
55
using Microsoft.IdentityModel.Tokens;
6+
using PaymentCoreServiceApi.Core.Interfaces.Repositories.Read;
67
using PaymentCoreServiceApi.Core.Interfaces.Repositories.Write;
78
using PaymentCoreServiceApi.Features.Auth;
9+
using PaymentCoreServiceApi.Infrastructure.Repositories.Read;
810
using PaymentCoreServiceApi.Infrastructure.Repositories.Write;
911
using PaymentCoreServiceApi.Middlewares;
1012
using PaymentCoreServiceApi.Services;
@@ -20,7 +22,7 @@ public static IServiceCollection AddRepositories(this IServiceCollection service
2022

2123
// Register Domain Specific Repositories
2224
services.AddScoped<IUserWriteRepository, UserWriteRepository>();
23-
25+
services.AddScoped<IUserReadRepository, UserReadRepository>();
2426
return services;
2527
}
2628

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using PaymentCoreServiceApi.Core.Entities.BaseModel;
2+
using PaymentCoreServiceApi.Core.Interfaces.Repositories.Read;
3+
using PaymentCoreServiceApi.Infrastructure.DbContexts;
4+
using Microsoft.EntityFrameworkCore;
5+
using System.Linq.Expressions;
6+
7+
namespace PaymentCoreServiceApi.Infrastructure.Repositories.Read;
8+
9+
public class EfBaseReadOnlyRepository<TEntity> : IBaseReadRepository<TEntity> where TEntity : EntityBase
10+
{
11+
private readonly AppDbContext _context;
12+
private readonly DbSet<TEntity> _dbSet;
13+
14+
public EfBaseReadOnlyRepository(AppDbContext context)
15+
{
16+
_context = context;
17+
_dbSet = context.Set<TEntity>();
18+
}
19+
20+
public async Task<TEntity> GetByIdAsync(int id)
21+
{
22+
return await _dbSet.FindAsync(id);
23+
}
24+
25+
public async Task<IEnumerable<TEntity>> GetAllAsync()
26+
{
27+
return await _dbSet.ToListAsync();
28+
}
29+
30+
public async Task<(IEnumerable<TEntity> Items, int TotalCount)> GetPagedAsync(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> predicate)
31+
{
32+
var query = _dbSet.Where(predicate);
33+
var totalCount = await query.CountAsync();
34+
var items = await query
35+
.Skip((pageIndex - 1) * pageSize)
36+
.Take(pageSize)
37+
.ToListAsync();
38+
39+
return (items, totalCount);
40+
}
41+
42+
43+
44+
}
Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
1+
using Microsoft.EntityFrameworkCore;
2+
using PaymentCoreServiceApi.Core.Entities.UserGenerated;
3+
using PaymentCoreServiceApi.Core.Interfaces.Repositories.Read;
4+
using PaymentCoreServiceApi.Infrastructure.DbContexts;
5+
16
namespace PaymentCoreServiceApi.Infrastructure.Repositories.Read;
27

3-
public class UserReadRepository
8+
public class UserReadRepository : EfBaseReadOnlyRepository<User>, IUserReadRepository
49
{
5-
10+
private readonly AppDbContext _context;
11+
12+
public UserReadRepository(AppDbContext context) : base(context)
13+
{
14+
_context = context;
15+
}
16+
17+
public async Task<bool> ExistsAsync(string username)
18+
{
19+
return await _context.Users.AnyAsync(u => u.UserName == username);
20+
}
621
}

0 commit comments

Comments
 (0)