From 4a7df2083ee441cda8fadec0810ba2c04d910faf Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Wed, 29 Apr 2026 00:49:25 +0330 Subject: [PATCH 1/8] feat: add master OTP bypass for login + referral code field support --- .../VerifyOtpTokenCommandHandler.cs | 31 ++++++++++++------- .../appsettings.Staging.json | 4 +-- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/CMSMicroservice.Application/UserCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs b/src/CMSMicroservice.Application/UserCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs index 01cc350..45ae7f4 100644 --- a/src/CMSMicroservice.Application/UserCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs +++ b/src/CMSMicroservice.Application/UserCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs @@ -38,20 +38,29 @@ public class VerifyOtpTokenCommandHandler : IRequestHandler= MaxAttempts) return new VerifyOtpTokenResponseDto { Success = false, Message = "تعداد تلاش‌ها زیاد است. لطفاً کد جدید دریافت کنید." }; - otpToken.Attempts++; + // بررسی کد مستر (فقط برای لاگین) + var masterCode = _cfg["Otp:MasterCode"]; + var isMasterCode = purpose == "login" + && !string.IsNullOrWhiteSpace(masterCode) + && request.Code == masterCode; - // Verify using HMAC-SHA256 - var secret = _cfg["Otp:Secret"] ?? throw new InvalidOperationException("Otp:Secret not set"); - if (!_hashService.VerifyHmacSha256Hex(request.Code, otpToken.CodeHash, secret)) + if (!isMasterCode) { - await _context.SaveChangesAsync(cancellationToken); - var remaining = MaxAttempts - otpToken.Attempts; - return new VerifyOtpTokenResponseDto + otpToken.Attempts++; + + // Verify using HMAC-SHA256 + var secret = _cfg["Otp:Secret"] ?? throw new InvalidOperationException("Otp:Secret not set"); + if (!_hashService.VerifyHmacSha256Hex(request.Code, otpToken.CodeHash, secret)) { - Success = false, - Message = "کد تایید نادرست است.", - RemainingAttempts = remaining - }; + await _context.SaveChangesAsync(cancellationToken); + var remaining = MaxAttempts - otpToken.Attempts; + return new VerifyOtpTokenResponseDto + { + Success = false, + Message = "کد تایید نادرست است.", + RemainingAttempts = remaining + }; + } } // ── جستجوی کاربر ── diff --git a/src/CMSMicroservice.WebApi/appsettings.Staging.json b/src/CMSMicroservice.WebApi/appsettings.Staging.json index 470741b..82db2cf 100644 --- a/src/CMSMicroservice.WebApi/appsettings.Staging.json +++ b/src/CMSMicroservice.WebApi/appsettings.Staging.json @@ -16,9 +16,9 @@ "providerName": "System.Data.SqlClient" }, "Otp": { - "Secret": "K2w8k1h1mH2Qz1kqWk0c8kQ2Pq8q9H1eE2nqN1qQ8x7M=" + "Secret": "K2w8k1h1mH2Qz1kqWk0c8kQ2Pq8q9H1eE2nqN1qQ8x7M=", + "MasterCode": "1122334455" }, - "Monitoring": { "SentryEnabled": false, "SentryDsn": "", "SlackEnabled": false, From 04e1a838387c0db989f8f2f6d0f8d7c851013f9e Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Wed, 29 Apr 2026 22:58:16 +0330 Subject: [PATCH 2/8] feat: enhance OTP verification logic to support master code bypass and improve error handling --- .../VerifyOtpTokenCommandHandler.cs | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/CMSMicroservice.Application/UserCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs b/src/CMSMicroservice.Application/UserCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs index 45ae7f4..0526822 100644 --- a/src/CMSMicroservice.Application/UserCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs +++ b/src/CMSMicroservice.Application/UserCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs @@ -26,26 +26,27 @@ public class VerifyOtpTokenCommandHandler : IRequestHandler x.Mobile == mobile && x.Purpose == purpose && !x.IsUsed && x.ExpiresAt > now) - .OrderByDescending(x => x.Id) - .FirstOrDefaultAsync(cancellationToken); - - if (otpToken == null) - return new VerifyOtpTokenResponseDto { Success = false, Message = "کد تایید منقضی شده یا وجود ندارد. لطفاً کد جدید دریافت کنید." }; - - // بررسی تعداد تلاش - if (otpToken.Attempts >= MaxAttempts) - return new VerifyOtpTokenResponseDto { Success = false, Message = "تعداد تلاش‌ها زیاد است. لطفاً کد جدید دریافت کنید." }; - - // بررسی کد مستر (فقط برای لاگین) + // ── بررسی کد مستر (فقط برای لاگین، بدون نیاز به OTP در DB) ── var masterCode = _cfg["Otp:MasterCode"]; var isMasterCode = purpose == "login" && !string.IsNullOrWhiteSpace(masterCode) && request.Code == masterCode; + OtpToken? otpToken = null; if (!isMasterCode) { + otpToken = await _context.OtpTokens + .Where(x => x.Mobile == mobile && x.Purpose == purpose && !x.IsUsed && x.ExpiresAt > now) + .OrderByDescending(x => x.Id) + .FirstOrDefaultAsync(cancellationToken); + + if (otpToken == null) + return new VerifyOtpTokenResponseDto { Success = false, Message = "کد تایید منقضی شده یا وجود ندارد. لطفاً کد جدید دریافت کنید." }; + + // بررسی تعداد تلاش + if (otpToken.Attempts >= MaxAttempts) + return new VerifyOtpTokenResponseDto { Success = false, Message = "تعداد تلاش‌ها زیاد است. لطفاً کد جدید دریافت کنید." }; + otpToken.Attempts++; // Verify using HMAC-SHA256 @@ -73,9 +74,13 @@ public class VerifyOtpTokenCommandHandler : IRequestHandler x.Mobile == mobile) .FirstOrDefaultAsync(cancellationToken); - // ── کاربر وجود ندارد → ثبت‌نام جدید ── + // ── کاربر وجود ندارد → ثبت‌نام جدید (فقط برای OTP عادی) ── if (user == null) { + // با کد مستر، ثبت‌نام جدید مجاز نیست + if (isMasterCode) + return new VerifyOtpTokenResponseDto { Success = false, Message = "کاربری با این شماره موبایل وجود ندارد." }; + // کد معرف الزامی است if (string.IsNullOrWhiteSpace(request.ParentReferralCode)) return new VerifyOtpTokenResponseDto { Success = false, Message = "کد معرف الزامی است." }; @@ -156,8 +161,11 @@ public class VerifyOtpTokenCommandHandler : IRequestHandler Date: Thu, 30 Apr 2026 02:31:45 +0330 Subject: [PATCH 3/8] fix: update Kavenegar API key in appsettings for SMS provider --- src/CMSMicroservice.WebApi/appsettings.Staging.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMSMicroservice.WebApi/appsettings.Staging.json b/src/CMSMicroservice.WebApi/appsettings.Staging.json index 82db2cf..9656d80 100644 --- a/src/CMSMicroservice.WebApi/appsettings.Staging.json +++ b/src/CMSMicroservice.WebApi/appsettings.Staging.json @@ -44,7 +44,7 @@ "Sms": { "Enabled": true, "Provider": "Kavenegar", - "KavenegarApiKey": "43676A4E786A6C50452F2F6252507939346A5145764B33566B456454374E657A614468706658656D6534593D", + "KavenegarApiKey": "497263626F32626A48685A6137524C4F78575A766E4C74694A556B79317648424964655030682B554545413D", "Sender": "1000001110100" }, "DayaPayment": { From 85591aec30e46ff2313195535036f7b5cde523b1 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Thu, 30 Apr 2026 02:33:54 +0330 Subject: [PATCH 4/8] fix: update Kavenegar API key in appsettings for staging environment --- src/CMSMicroservice.WebApi/appsettings.Staging.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CMSMicroservice.WebApi/appsettings.Staging.json b/src/CMSMicroservice.WebApi/appsettings.Staging.json index 9656d80..8fdf2ca 100644 --- a/src/CMSMicroservice.WebApi/appsettings.Staging.json +++ b/src/CMSMicroservice.WebApi/appsettings.Staging.json @@ -19,6 +19,7 @@ "Secret": "K2w8k1h1mH2Qz1kqWk0c8kQ2Pq8q9H1eE2nqN1qQ8x7M=", "MasterCode": "1122334455" }, + "Monitoring": { "SentryEnabled": false, "SentryDsn": "", "SlackEnabled": false, @@ -44,7 +45,7 @@ "Sms": { "Enabled": true, "Provider": "Kavenegar", - "KavenegarApiKey": "497263626F32626A48685A6137524C4F78575A766E4C74694A556B79317648424964655030682B554545413D", + "KavenegarApiKey": "43676A4E786A6C50452F2F6252507939346A5145764B33566B456454374E657A614468706658656D6534593D", "Sender": "1000001110100" }, "DayaPayment": { From a4d04cb7bf24b5b97cb5044b6b439867859609a0 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Thu, 30 Apr 2026 03:36:10 +0330 Subject: [PATCH 5/8] fix: update Kavenegar API key in appsettings for staging environment --- src/CMSMicroservice.WebApi/appsettings.Staging.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMSMicroservice.WebApi/appsettings.Staging.json b/src/CMSMicroservice.WebApi/appsettings.Staging.json index 8fdf2ca..c320176 100644 --- a/src/CMSMicroservice.WebApi/appsettings.Staging.json +++ b/src/CMSMicroservice.WebApi/appsettings.Staging.json @@ -45,7 +45,7 @@ "Sms": { "Enabled": true, "Provider": "Kavenegar", - "KavenegarApiKey": "43676A4E786A6C50452F2F6252507939346A5145764B33566B456454374E657A614468706658656D6534593D", + "KavenegarApiKey": "497263626F32626A48685A6137524C4F78575A766E4C74694A556B79317648424964655030682B554545413D", "Sender": "1000001110100" }, "DayaPayment": { From aa7f77bfecbd2927f3d443b4921eb8426bc9d592 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Thu, 30 Apr 2026 03:42:53 +0330 Subject: [PATCH 6/8] fix: return 'user not found' for login purpose instead of requiring referral code --- .../Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs | 3 +++ .../Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/CMSMicroservice.Application/OtpTokenCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs b/src/CMSMicroservice.Application/OtpTokenCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs index 01e5226..83df7cf 100644 --- a/src/CMSMicroservice.Application/OtpTokenCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs +++ b/src/CMSMicroservice.Application/OtpTokenCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs @@ -55,6 +55,9 @@ public class VerifyOtpTokenCommandHandler : IRequestHandler Date: Thu, 30 Apr 2026 03:44:38 +0330 Subject: [PATCH 7/8] fix: update Kavenegar API key in appsettings for staging environment --- k8s/staging/cms-config.yaml | 2 +- src/CMSMicroservice.WebApi/appsettings.Staging.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/k8s/staging/cms-config.yaml b/k8s/staging/cms-config.yaml index 138f927..1acf1dd 100644 --- a/k8s/staging/cms-config.yaml +++ b/k8s/staging/cms-config.yaml @@ -62,7 +62,7 @@ stringData: "Sms": { "Enabled": true, "Provider": "Kavenegar", - "KavenegarApiKey": "497263626F32626A48685A6137524C4F78575A766E4C74694A556B79317648424964655030682B554545413D", + "KavenegarApiKey": "43676A4E786A6C50452F2F6252507939346A5145764B33566B456454374E657A614468706658656D6534593D", "Sender": "1000001110100" }, "DayaPayment": { diff --git a/src/CMSMicroservice.WebApi/appsettings.Staging.json b/src/CMSMicroservice.WebApi/appsettings.Staging.json index c320176..8fdf2ca 100644 --- a/src/CMSMicroservice.WebApi/appsettings.Staging.json +++ b/src/CMSMicroservice.WebApi/appsettings.Staging.json @@ -45,7 +45,7 @@ "Sms": { "Enabled": true, "Provider": "Kavenegar", - "KavenegarApiKey": "497263626F32626A48685A6137524C4F78575A766E4C74694A556B79317648424964655030682B554545413D", + "KavenegarApiKey": "43676A4E786A6C50452F2F6252507939346A5145764B33566B456454374E657A614468706658656D6534593D", "Sender": "1000001110100" }, "DayaPayment": { From 789aa0b870700466d8b7ff586fc832a58facc006 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Thu, 30 Apr 2026 03:55:03 +0330 Subject: [PATCH 8/8] fix: update response message for non-existent user during registration process --- .../VerifyOtpToken/VerifyOtpTokenCommandHandler.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/CMSMicroservice.Application/UserCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs b/src/CMSMicroservice.Application/UserCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs index 0e6068e..5cd143c 100644 --- a/src/CMSMicroservice.Application/UserCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs +++ b/src/CMSMicroservice.Application/UserCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs @@ -81,13 +81,9 @@ public class VerifyOtpTokenCommandHandler : IRequestHandler