cc nasazeni
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
namespace Idoklad.Credentials;
|
||||
|
||||
/// <summary>
|
||||
/// Names of the HTTP headers that carry per-request iDoklad credentials.
|
||||
///
|
||||
/// Secrets are never accepted in the query string or request body: they are required in
|
||||
/// request headers (and documented as such in Swagger). Each header carries the credential
|
||||
/// value directly and must therefore only be sent over TLS.
|
||||
/// </summary>
|
||||
public static class CredentialConstants
|
||||
{
|
||||
public const string ClientIdHeader = "X-ClientId";
|
||||
public const string ClientSecretHeader = "X-ClientSecret";
|
||||
public const string ApplicationIdHeader = "X-ApplicationId";
|
||||
|
||||
/// <summary>Header carrying the response language override (Cz, Sk, En).</summary>
|
||||
public const string LanguageHeader = "X-Idoklad-Language";
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using IdokladSdk.Enums;
|
||||
|
||||
namespace Idoklad.Credentials;
|
||||
|
||||
/// <summary>
|
||||
/// Fully resolved set of credentials and request options used to build a <c>DokladApi</c>
|
||||
/// instance for a single request.
|
||||
/// </summary>
|
||||
public sealed record IdokladCredentials
|
||||
{
|
||||
public required string ClientId { get; init; }
|
||||
public required string ClientSecret { get; init; }
|
||||
public required string ApplicationId { get; init; }
|
||||
public required Language Language { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Idoklad.Credentials;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the request does not provide a complete set of iDoklad credentials,
|
||||
/// neither through request headers nor through the service environment defaults.
|
||||
/// </summary>
|
||||
public sealed class MissingCredentialsException : Exception
|
||||
{
|
||||
public IReadOnlyList<string> MissingHeaders { get; }
|
||||
|
||||
public MissingCredentialsException(IReadOnlyList<string> missingHeaders)
|
||||
: base("Incomplete iDoklad credentials. Provide the missing values as request headers or configure the service defaults.")
|
||||
{
|
||||
MissingHeaders = missingHeaders;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using IdokladSdk.Enums;
|
||||
using Idoklad.Configuration;
|
||||
|
||||
namespace Idoklad.Credentials;
|
||||
|
||||
/// <summary>
|
||||
/// Resolves the iDoklad credentials for the current request.
|
||||
///
|
||||
/// Mirrors <c>get_request_settings</c> 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.
|
||||
/// </summary>
|
||||
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<string>();
|
||||
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<Language>(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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user