using IdokladSdk.Enums; using Idoklad.Configuration; namespace Idoklad.Credentials; /// /// Resolves the iDoklad credentials for the current request. /// /// Mirrors get_request_settings from the sibling microsoft-365-service: each credential /// value is taken from its request header when present and otherwise falls back to the /// environment-configured default. Secrets are only ever read from headers (never query/body). /// If, after applying the fallbacks, any required value is still missing, the request is rejected. /// public sealed class RequestCredentialsProvider { private readonly IHttpContextAccessor _httpContextAccessor; private readonly IdokladSettings _settings; public RequestCredentialsProvider(IHttpContextAccessor httpContextAccessor, IdokladSettings settings) { _httpContextAccessor = httpContextAccessor; _settings = settings; } public IdokladCredentials Resolve() { var headers = _httpContextAccessor.HttpContext?.Request.Headers; var clientId = HeaderOrDefault(headers, CredentialConstants.ClientIdHeader, _settings.ClientId); var clientSecret = HeaderOrDefault(headers, CredentialConstants.ClientSecretHeader, _settings.ClientSecret); var applicationId = HeaderOrDefault(headers, CredentialConstants.ApplicationIdHeader, _settings.ApplicationId); var missing = new List(); if (string.IsNullOrWhiteSpace(clientId)) missing.Add(CredentialConstants.ClientIdHeader); if (string.IsNullOrWhiteSpace(clientSecret)) missing.Add(CredentialConstants.ClientSecretHeader); if (string.IsNullOrWhiteSpace(applicationId)) missing.Add(CredentialConstants.ApplicationIdHeader); if (missing.Count > 0) { throw new MissingCredentialsException(missing); } return new IdokladCredentials { ClientId = clientId!, ClientSecret = clientSecret!, ApplicationId = applicationId!, Language = ResolveLanguage(headers), }; } private Language ResolveLanguage(IHeaderDictionary? headers) { var raw = headers is not null && headers.TryGetValue(CredentialConstants.LanguageHeader, out var value) ? value.ToString() : null; return Enum.TryParse(raw, ignoreCase: true, out var parsed) ? parsed : _settings.Language; } private static string? HeaderOrDefault(IHeaderDictionary? headers, string name, string fallback) { if (headers is not null && headers.TryGetValue(name, out var value)) { var headerValue = value.ToString(); if (!string.IsNullOrWhiteSpace(headerValue)) { return headerValue; } } return string.IsNullOrWhiteSpace(fallback) ? null : fallback; } }