using JobsMedical.Web.Services.Scraping; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Hosting; namespace JobsMedical.Web.Services; /// /// One-time-code issuing/verification. Codes live in memory for 5 minutes. When SMS is configured /// (admin settings) the code is sent via the gateway and NOT returned; otherwise it's returned so /// the dev login page can display it. /// public class OtpService { private readonly IMemoryCache _cache; private readonly ISmsSender _sms; private readonly SettingsService _settings; private readonly IHostEnvironment _env; public OtpService(IMemoryCache cache, ISmsSender sms, SettingsService settings, IHostEnvironment env) { _cache = cache; _sms = sms; _settings = settings; _env = env; } private static string Key(string phone) => $"otp:{Normalize(phone)}"; /// /// Generate + store a 5-digit code. If SMS is enabled, send it and return null (don't reveal); /// otherwise return the code so the dev login screen can show it. /// public async Task IssueAsync(string phone) { var code = Random.Shared.Next(10000, 100000).ToString(); _cache.Set(Key(phone), code, TimeSpan.FromMinutes(5)); var settings = await _settings.GetAsync(); // In Development (local Docker / dotnet run) never call the SMS gateway — always show the // code on the login screen. In Production, send via SMS only when it's enabled. if (settings.SmsEnabled && !_env.IsDevelopment()) { await _sms.SendOtpAsync(phone, code, settings); return null; // sent via SMS — don't reveal it } return code; // local/dev (or SMS off): surface it on screen } public bool Verify(string phone, string code) { if (_cache.TryGetValue(Key(phone), out string? stored) && stored == code?.Trim()) { _cache.Remove(Key(phone)); return true; } return false; } /// Normalize Iranian mobile numbers (Persian digits → Latin, strip spaces). public static string Normalize(string phone) { var chars = phone.Trim().ToCharArray(); for (var i = 0; i < chars.Length; i++) if (chars[i] >= '۰' && chars[i] <= '۹') chars[i] = (char)('0' + (chars[i] - '۰')); return new string(chars).Replace(" ", "").Replace("-", ""); } }