Skip to content

Commit

Permalink
add new localized strings
Browse files Browse the repository at this point in the history
  • Loading branch information
emrecoskun705 committed Sep 23, 2023
1 parent 73a3031 commit 2c8bfb7
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ namespace Unitagram.Application.Contracts.Identity;

public interface IEmailVerificationService
{
Task<Result<Unit>> GenerateAsync(Guid userId);
Task<Result<bool>> ValidateAsync(Guid userId,string token);
Task<Result<Unit>> GenerateAsync(Guid userId, string email);
Task<Result<Unit>> ValidateAsync(Guid userId,string token);
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
using FluentValidation;
using Unitagram.Application.Contracts.Localization;

namespace Unitagram.Application.Models.Identity.Jwt;

public class RefreshRequestValidator : AbstractValidator<RefreshRequest>
{
public RefreshRequestValidator()
public RefreshRequestValidator(ILocalizationService localization)
{
RuleFor(a => a.Token)
.NotEmpty().WithMessage("{PropertyName} can't be empty")
.NotEmpty().WithMessage(localization["TokenNotEmpty"])
.NotNull();

RuleFor(a => a.RefreshToken)
.NotEmpty().WithMessage("{PropertyName} can't be empty")
.NotEmpty().WithMessage(localization["TokenNotEmpty"])
.NotNull();
}
}
2 changes: 1 addition & 1 deletion Unitagram.Identity.UnitTests/AuthServiceUnitTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ public async Task Register_ValidCredentials_ReturnsRegisterResponse()
.Returns(_fixture.Build<JwtResponse>().Create());

_verificationServiceMock
.Setup(u => u.GenerateAsync(It.IsAny<Guid>()))
.Setup(u => u.GenerateAsync(It.IsAny<Guid>(), It.IsAny<string>()))
.ReturnsAsync(Result<Unit>.Bottom);


Expand Down
20 changes: 10 additions & 10 deletions Unitagram.Identity/Services/AuthService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ await _universityUserRepository.CreateAsync(new UniversityUser()
user.RefreshTokenExpirationDateTime = jwtResponse.RefreshTokenExpirationDateTime;
await _userManager.UpdateAsync(user);

await _verificationService.GenerateAsync(user.Id);
await _verificationService.GenerateAsync(user.Id, user.Email);

_diagnosticContext.Set("CreatedUser", user.UserName);
_diagnosticContext.Set("University", getUniversity.Name);
Expand All @@ -204,14 +204,14 @@ public async Task<Result<EmailVerificationResponse>> ConfirmEmail(EmailVerificat

if (username == null)
{
var exception = new UserNotFoundException();
var exception = new UserNotFoundException(_localization["UserNotFound"]);
return new Result<EmailVerificationResponse>(exception);
}

var user = await _userManager.FindByNameAsync(username);
if (user == null)
{
var exception = new UserNotFoundException();
var exception = new UserNotFoundException(_localization["UsernameNotFound"]);
return new Result<EmailVerificationResponse>(exception);
}

Expand All @@ -232,24 +232,24 @@ public async Task<Result<GenerateOtpResponse>> GenerateOtpEmail(GenerateOtpReque

if (username == null)
{
var exception = new UserNotFoundException();
var exception = new UserNotFoundException(_localization["UsernameNotFound"]);
return new Result<GenerateOtpResponse>(exception);
}

var user = await _userManager.FindByNameAsync(username);
if (user == null)
{
var exception = new UserNotFoundException();
var exception = new UserNotFoundException(_localization["UserNotFound"]);
return new Result<GenerateOtpResponse>(exception);
}

if (user.EmailConfirmed)
{
var exception = new EmailAlreadyConfirmedException();
var exception = new EmailAlreadyConfirmedException(_localization["EmailAlreadyConfirmedException"]);
return new Result<GenerateOtpResponse>(exception);
}

var generateOtpResult = await _verificationService.GenerateAsync(user.Id);
var generateOtpResult = await _verificationService.GenerateAsync(user.Id, user.Email!);

var result = generateOtpResult.Match<Result<GenerateOtpResponse>>(
_ => new GenerateOtpResponse(),
Expand All @@ -266,7 +266,7 @@ private static string GetEmailDomain(RegisterRequest request)

public async Task<Result<AuthResponse>> RefreshToken(RefreshRequest request)
{
var validator = new RefreshRequestValidator();
var validator = new RefreshRequestValidator(_localization);
var validationResult = await validator.ValidateAsync(request);
if (validationResult.Errors.Any())
{
Expand All @@ -281,15 +281,15 @@ public async Task<Result<AuthResponse>> RefreshToken(RefreshRequest request)
string? username = principal.FindFirstValue(ClaimTypes.NameIdentifier);
if (username == null)
{
var exception = new JwtTokenException();
var exception = new JwtTokenException(_localization["UserNotFound"]);
return new Result<AuthResponse>(exception);
}

ApplicationUser? user = await _userManager.FindByNameAsync(username);

if (user is null)
{
var exception = new UserNotFoundException();
var exception = new UserNotFoundException(_localization["UserNotFound"]);
return new Result<AuthResponse>(exception);
}

Expand Down
40 changes: 20 additions & 20 deletions Unitagram.Identity/Services/EmailVerificationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.Extensions.Options;
using Unitagram.Application.Contracts.Email;
using Unitagram.Application.Contracts.Identity;
using Unitagram.Application.Contracts.Localization;
using Unitagram.Application.Contracts.Persistence;
using Unitagram.Application.Exceptions.EmailVerification;
using Unitagram.Application.Models.Email;
Expand All @@ -20,36 +21,36 @@ public class EmailVerificationService : IEmailVerificationService
private readonly UserManager<ApplicationUser> _userManager;
private readonly IEmailSender _emailSender;
private readonly EmailOtpSettings _emailOtpSettings;
private readonly ILocalizationService _localization;


public EmailVerificationService(
IOtpConfirmationRepository otpConfirmationRepository,
UserManager<ApplicationUser> userManager,
IEmailSender emailSender,
IOptions<EmailOtpSettings> emailOtpSettings)
IOptions<EmailOtpSettings> emailOtpSettings,
ILocalizationService localization)
{
_otpConfirmationRepository = otpConfirmationRepository;
_userManager = userManager;
_emailSender = emailSender;
_emailOtpSettings = emailOtpSettings.Value;
_localization = localization;
}

public async Task<Result<Unit>> GenerateAsync(Guid userId)
public async Task<Result<Unit>> GenerateAsync(Guid userId, string email)
{
var purpose = _emailOtpSettings.Name;

var otpConfirmation = await _otpConfirmationRepository.GetByUserIdAndName(userId, purpose);

if (otpConfirmation is null)
{
var token = GenerateRandom6DigitCode();

await CreateOtpConfirmation(userId, purpose, token);

var user = await _userManager.FindByIdAsync(userId.ToString());

await _emailSender.SendEmail(ConfirmationEmailTemplate.ToEmailMessage(user!.Email!, token), isBodyHtml: true);

await _emailSender.SendEmail(ConfirmationEmailTemplate.ToEmailMessage(email, token), isBodyHtml: true);
return Unit.Default;
}

Expand All @@ -59,18 +60,16 @@ public async Task<Result<Unit>> GenerateAsync(Guid userId)

await UpdateOtpConfirmation(userId, purpose, token);

var user = await _userManager.FindByIdAsync(userId.ToString());

await _emailSender.SendEmail(ConfirmationEmailTemplate.ToEmailMessage(user!.Email!, token), isBodyHtml: true);
await _emailSender.SendEmail(ConfirmationEmailTemplate.ToEmailMessage(email, token), isBodyHtml: true);
return Unit.Default;
}

var minutesDifference = CalculateMinutesDifference(otpConfirmation.RetryDateTimeUtc!.Value);
var exception = new OtpCodeTryAgainLaterException();
var exception = new OtpCodeTryAgainLaterException(string.Format(_localization["OtpCodeTryAgainLaterException"], minutesDifference));
return new Result<Unit>(exception);
}

public async Task<Result<bool>> ValidateAsync(Guid userId, string token)
public async Task<Result<Unit>> ValidateAsync(Guid userId, string token)
{
var purpose = _emailOtpSettings.Name;
var maxRetryCount = _emailOtpSettings.RetryCount;
Expand All @@ -80,24 +79,25 @@ public async Task<Result<bool>> ValidateAsync(Guid userId, string token)

if (otpConfirmation is null || IsRetryTimeElapsed(otpConfirmation))
{
var exception = new EmailOtpNotFoundException();
return new Result<bool>(exception);
var exception = new EmailOtpNotFoundException(_localization["EmailOtpNotFoundException"]);
return new Result<Unit>(exception);
}

// check max retry count is passed
if (otpConfirmation.RetryCount > maxRetryCount)
if (otpConfirmation.RetryCount >= maxRetryCount)
{
var exception = new ReachedMaximumCodeUsageException();
return new Result<bool>(exception);
var exception = new ReachedMaximumCodeUsageException(_localization["ReachedMaximumCodeUsageException"]);
return new Result<Unit>(exception);
}

// if invalid token then increment maxRetryCount
if (token != otpConfirmation.Value)
{
otpConfirmation.RetryCount++;
await _otpConfirmationRepository.UpdateAsync(otpConfirmation);
var exception = new InvalidCodeException();
return new Result<bool>(exception);
var count = _emailOtpSettings.RetryCount - otpConfirmation.RetryCount;
var exception = new InvalidCodeException(string.Format(_localization["EmailInvalidCodeException"], count));
return new Result<Unit>(exception);
}

// if code reaches this part everything is ok and email can be confirmed
Expand All @@ -110,7 +110,7 @@ public async Task<Result<bool>> ValidateAsync(Guid userId, string token)
// remove otpConfirmation
await _otpConfirmationRepository.DeleteAsync(otpConfirmation);

return true;
return Unit.Default;
}

private string GenerateRandom6DigitCode()
Expand Down
21 changes: 21 additions & 0 deletions Unitagram.Infrastructure/Resources/SharedResources.en-us.resx
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,25 @@
<data name="UsernameExists" xml:space="preserve">
<value>Username already exists.</value>
</data>
<data name="UsernameNotFound" xml:space="preserve">
<value>Username not found.</value>
</data>
<data name="OtpCodeTryAgainLaterException" xml:space="preserve">
<value>Please wait for {0} minutes before attempting to create new code again.</value>
</data>
<data name="EmailOtpNotFoundException" xml:space="preserve">
<value>Code not found. Please resend code.</value>
</data>
<data name="ReachedMaximumCodeUsageException" xml:space="preserve">
<value>You've reached maximum code usage. Please resend code again.</value>
</data>
<data name="EmailInvalidCodeException" xml:space="preserve">
<value>Code is not correct. You have got {0} left.</value>
</data>
<data name="EmailAlreadyConfirmedException" xml:space="preserve">
<value>Your email has already been confirmed successfully!</value>
</data>
<data name="TokenNotEmpty" xml:space="preserve">
<value>Token can't be empty. Please log in again.</value>
</data>
</root>
21 changes: 21 additions & 0 deletions Unitagram.Infrastructure/Resources/SharedResources.tr-TR.resx
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,25 @@
<data name="UsernameExists" xml:space="preserve">
<value>Kullanıcı adı kullanılıyor.</value>
</data>
<data name="UsernameNotFound" xml:space="preserve">
<value>Kullanıcı adı bulunamadı.</value>
</data>
<data name="OtpCodeTryAgainLaterException" xml:space="preserve">
<value>Yeni kod oluşturmak için lütfen tekrar {0} dakika sonra deneyin.</value>
</data>
<data name="EmailOtpNotFoundException" xml:space="preserve">
<value>Kod bulunamadı. Lütfen kodu tekrar gönderiniz.</value>
</data>
<data name="ReachedMaximumCodeUsageException" xml:space="preserve">
<value>Maksimum tekrar sayısına ulaştınız. Lütfen kodu tekrar gönderiniz.</value>
</data>
<data name="EmailInvalidCodeException" xml:space="preserve">
<value>Kod doğru değil. {0} hakkınız kaldı.</value>
</data>
<data name="EmailAlreadyConfirmedException" xml:space="preserve">
<value>E-postanız daha önce onaylanmıştır.</value>
</data>
<data name="TokenNotEmpty" xml:space="preserve">
<value>Giriş anahtarın boş olmamalıdır. Lütfen tekrar giriş yapmayı deneyiniz.</value>
</data>
</root>

0 comments on commit 2c8bfb7

Please sign in to comment.