Skip to content
Merged

Fix #445

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ CancellationToken cancellationToken
.ThenInclude(s => s.Model)
.Include(s => s.Car)
.ThenInclude(s => s.GPS)
.Include(s => s.Car)
.ThenInclude(s => s.Contract)
.Include(s => s.CarReport)
.Include(s => s.Technician)
.Include(s => s.Photos)
Expand Down Expand Up @@ -162,6 +164,21 @@ CancellationToken cancellationToken
? InspectionScheduleStatusEnum.Approved
: InspectionScheduleStatusEnum.Rejected;
schedule.UpdatedAt = DateTimeOffset.UtcNow;

// reset contract signature if schedule is not approved
if (!request.IsApproved && schedule.Type == InspectionScheduleType.NewCar)
{
var contract = schedule.Car?.Contract;
if (contract != null)
{
contract.OwnerSignature = null;
contract.OwnerSignatureDate = null;
contract.TechnicianSignature = null;
contract.TechnicianSignatureDate = null;
contract.Status = CarContractStatusEnum.Pending;
contract.UpdatedAt = DateTimeOffset.UtcNow;
}
}
// Set Car Status into available
if (request.IsApproved)
{
Expand Down
37 changes: 26 additions & 11 deletions src/UseCases/UC_User/Commands/CreateStaff.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,34 @@ CancellationToken cancellationToken
if (!new[] { "consultant", "technician" }.Contains(request.RoleName.ToLower()))
return Result.Error(ResponseMessages.MustBeConsultantOrTechnician);

// Check if user already exists
User? existingUser = await context.Users.FirstOrDefaultAsync(
x =>
EF.Functions.ILike(x.Email, request.Email)
|| EF.Functions.ILike(x.Phone, request.Phone),
cancellationToken
);
// Check if email or phone already exists
List<User> users = await context
.Users.AsNoTracking()
.Include(u => u.EncryptionKey)
.ToListAsync(cancellationToken);

if (existingUser is not null)
foreach (var u in users)
{
return existingUser.Email.ToLower() == request.Email.ToLower()
? Result.Error(ResponseMessages.EmailAddressIsExisted)
: Result.Error(ResponseMessages.PhoneNumberIsExisted);
string decryptedKey = keyManagementService.DecryptKey(
u.EncryptionKey.EncryptedKey,
encryptionSettings.Key
);

string decryptedPhone = await aesEncryptionService.Decrypt(
u.Phone,
decryptedKey,
u.EncryptionKey.IV
);

if (u.Email == request.Email)
{
return Result.Error(ResponseMessages.EmailAddressIsExisted);
}

if (decryptedPhone == request.Phone)
{
return Result.Error(ResponseMessages.PhoneNumberIsExisted);
}
}

// Get role
Expand Down
75 changes: 69 additions & 6 deletions test/UseCases.UnitTests/UC_User/Commands/CreateStaffTest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Ardalis.Result;
using Domain.Constants;
using Domain.Entities;
using Domain.Shared;
using Infrastructure.Encryption;
using Microsoft.EntityFrameworkCore;
Expand All @@ -9,6 +10,8 @@
using UseCases.UC_User.Commands;
using UseCases.UnitTests.TestBases;
using UseCases.UnitTests.TestBases.TestData;
using UseCases.Utils;
using UUIDNext;

namespace UseCases.UnitTests.UC_User.Commands;

Expand Down Expand Up @@ -41,7 +44,12 @@ public async Task Handle_UserNotAdmin_ReturnsForbidden()
{
// Arrange
var driverRole = await TestDataCreateUserRole.CreateTestUserRole(_dbContext, "Driver");
var user = await TestDataCreateUser.CreateTestUser(_dbContext, driverRole);
var user = await CreateUserWithEncryptedPhone(
driverRole,
"driver@test.com",
"Test Driver",
"1234567890"
);
_currentUser.SetUser(user);

var handler = new CreateStaff.Handler(
Expand Down Expand Up @@ -82,7 +90,12 @@ string name
// Arrange
var adminRole = await TestDataCreateUserRole.CreateTestUserRole(_dbContext, "Admin");
var staffRole = await TestDataCreateUserRole.CreateTestUserRole(_dbContext, roleName);
var admin = await TestDataCreateUser.CreateTestUser(_dbContext, adminRole);
var admin = await CreateUserWithEncryptedPhone(
adminRole,
"admin@test.com",
"Admin User",
"9876543210"
);
_currentUser.SetUser(admin);

var handler = new CreateStaff.Handler(
Expand Down Expand Up @@ -128,11 +141,17 @@ public async Task Handle_ExistingEmail_ReturnsError()
_dbContext,
"Consultant"
);
var admin = await TestDataCreateUser.CreateTestUser(_dbContext, adminRole);
var existingUser = await TestDataCreateUser.CreateTestUser(
_dbContext,
var admin = await CreateUserWithEncryptedPhone(
adminRole,
"admin@test.com",
"Admin User",
"9876543211"
);
var existingUser = await CreateUserWithEncryptedPhone(
consultantRole,
"existing@test.com"
"existing@test.com",
"Existing User",
"5555555555"
);
_currentUser.SetUser(admin);

Expand Down Expand Up @@ -196,4 +215,48 @@ string roleName
// Assert
Assert.False(result.IsValid);
}

private async Task<User> CreateUserWithEncryptedPhone(
UserRole userRole,
string email = "test@example.com",
string name = "Test User",
string phoneNumber = "1234567890",
string avatarUrl = "http://example.com/avatar.jpg"
)
{
// Generate encryption key and encrypt phone number
(string key, string iv) = await _keyService.GenerateKeyAsync();
string encryptedPhone = await _aesService.Encrypt(phoneNumber, key, iv);
string encryptedKey = _keyService.EncryptKey(key, _encryptionSettings.Key);

// Create encryption key record
var encryptionKey = new EncryptionKey { EncryptedKey = encryptedKey, IV = iv };
await _dbContext.EncryptionKeys.AddAsync(encryptionKey);
await _dbContext.SaveChangesAsync();

// Create user with encrypted phone
var user = new User
{
Id = Uuid.NewDatabaseFriendly(Database.PostgreSql),
EncryptionKeyId = encryptionKey.Id,
Name = name,
Email = email,
AvatarUrl = avatarUrl,
Password = "password".HashString(),
RoleId = userRole.Id,
Address = "Test Address",
DateOfBirth = DateTime.UtcNow.AddYears(-30),
Phone = encryptedPhone,
};

// Create user statistics
var userStatistic = new UserStatistic { UserId = user.Id };

// Save to database
await _dbContext.Users.AddAsync(user);
await _dbContext.UserStatistics.AddAsync(userStatistic);
await _dbContext.SaveChangesAsync();

return user;
}
}
Loading