feat(user): add user invitation functionality and enhance OTP verification
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 9m27s

- Introduced UserInvitation entity and updated IApplicationDbContext to include UserInvitations DbSet.
- Enhanced VerifyOtpTokenCommand and its handler to support optional inviter mobile number for user registration.
- Added new Protobuf definitions for GetMyInvitees and GetInvitationsByFilter RPCs to manage user invitations.
- Updated UserService to implement methods for retrieving invitees and invitations based on filters.
- Bumped Protobuf project version to reflect the addition of new features.
This commit is contained in:
masoodafar-web
2026-09-20 23:33:03 +03:30
parent f31fb5ee39
commit 2b958bd214
17 changed files with 6019 additions and 3 deletions
@@ -9,5 +9,7 @@ public record VerifyOtpTokenCommand : IRequest<VerifyOtpTokenResponseDto>
public string Code { get; init; }
//کد معرف والد
public string? ParentReferralCode { get; init; }
//شماره موبایل دعوت‌کننده (اختیاری)
public string? InviterMobile { get; init; }
}
@@ -118,6 +118,34 @@ public class VerifyOtpTokenCommandHandler : IRequestHandler<VerifyOtpTokenComman
else
return new VerifyOtpTokenResponseDto { Success = false, Message = "ظرفیت معرف تکمیل است!!" };
// ── دعوت‌کننده (اختیاری؛ اعتبارسنجی سخت قبل از ایجاد کاربر) ──
User? inviter = null;
if (!string.IsNullOrWhiteSpace(request.InviterMobile))
{
var inviterMobile = request.InviterMobile.NormalizeIranMobile();
if (inviterMobile == mobile)
{
return new VerifyOtpTokenResponseDto
{
Success = false,
Message = "شماره موبایل دعوت‌کننده نمی‌تواند با شماره خودتان یکسان باشد."
};
}
inviter = await _context.Users
.AsNoTracking()
.FirstOrDefaultAsync(u => u.Mobile == inviterMobile, cancellationToken);
if (inviter == null)
{
return new VerifyOtpTokenResponseDto
{
Success = false,
Message = "دعوت‌کننده با این شماره موبایل یافت نشد."
};
}
}
// ایجاد کاربر جدید
user = new User
{
@@ -134,6 +162,15 @@ public class VerifyOtpTokenCommandHandler : IRequestHandler<VerifyOtpTokenComman
user.AddDomainEvent(new CreateNewUserEvent(user));
await _context.SaveChangesAsync(cancellationToken);
if (inviter != null)
{
await _context.UserInvitations.AddAsync(new UserInvitation
{
InviterUserId = inviter.Id,
InviteeUserId = user.Id
}, cancellationToken);
}
// ایجاد نقش کاربری
var userRole = new UserRole { UserId = user.Id, RoleId = 1 };
await _context.UserRoles.AddAsync(userRole, cancellationToken);