cc nasazeni

This commit is contained in:
JiriUhlir
2026-06-12 13:18:35 +02:00
parent bbec747bb7
commit 1801d02e5c
89 changed files with 3541 additions and 16 deletions
+79 -12
View File
@@ -1,22 +1,89 @@
using Microsoft.OpenApi.Models;
using Newtonsoft.Json;
using Idoklad.Client;
using Idoklad.Configuration;
using Idoklad.Credentials;
using Idoklad.Infrastructure;
using Idoklad.Services;
var builder = WebApplication.CreateBuilder(args);
// Configuration resolved from environment variables (single shared instance).
var settings = new IdokladSettings();
builder.Services.AddSingleton(settings);
// HttpClient for the iDoklad SDK, managed by IHttpClientFactory (recommended SDK usage).
builder.Services.AddHttpClient(DokladApiFactory.HttpClientName, client =>
{
client.Timeout = TimeSpan.FromSeconds(settings.RequestTimeoutSeconds);
});
builder.Services.AddHttpContextAccessor();
// Credential resolution + SDK client wiring.
builder.Services.AddScoped<RequestCredentialsProvider>();
builder.Services.AddScoped<DokladApiFactory>();
builder.Services.AddScoped<IdokladApiAccessor>();
// Agenda services.
builder.Services.AddScoped<ContactsService>();
builder.Services.AddScoped<IssuedInvoicesService>();
builder.Services.AddScoped<ReceivedInvoicesService>();
builder.Services.AddScoped<RegistersService>();
builder.Services.AddScoped<AccountService>();
// Use Newtonsoft.Json so request/response binding matches the iDoklad SDK model attributes.
builder.Services
.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
});
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = settings.AppName,
Version = settings.AppVersion,
Description =
"REST integration with iDoklad built on the official IdokladSdk (.NET) 5.3.0, " +
"using the OAuth2 client credentials flow.\n\n" +
"**Credentials.** Every agenda endpoint needs an iDoklad ClientId, ClientSecret and ApplicationId. " +
"Sensitive values are required in request headers and are never accepted in the query string or body:\n\n" +
"- `X-ClientId` — iDoklad OAuth2 ClientId\n" +
"- `X-ClientSecret` — iDoklad OAuth2 ClientSecret (sensitive; TLS only)\n" +
"- `X-ApplicationId` — iDoklad ApplicationId from the developer portal\n" +
"- `X-Idoklad-Language` — optional response language (Cz, Sk, En)\n\n" +
"If a header is omitted, the matching environment default " +
"(`IDOKLAD_CLIENT_ID`, `IDOKLAD_CLIENT_SECRET`, `IDOKLAD_APPLICATION_ID`) is used. " +
"If neither a header nor a default is available, the request is rejected with 401.",
});
options.OperationFilter<CredentialHeadersOperationFilter>();
var xmlPath = Path.Combine(AppContext.BaseDirectory, $"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Name}.xml");
if (File.Exists(xmlPath))
{
options.IncludeXmlComments(xmlPath, includeControllerXmlComments: true);
}
});
var app = builder.Build();
var rootPath = Environment.GetEnvironmentVariable("ROOT_PATH");
if (!string.IsNullOrWhiteSpace(rootPath))
if (!string.IsNullOrWhiteSpace(settings.RootPath))
{
app.UsePathBase(rootPath);
app.UsePathBase(settings.RootPath);
}
app.MapGet("/", () => Results.Json(new
{
name = "iDoklad",
service = "idoklad",
status = "ok"
}));
app.UseMiddleware<ExceptionHandlingMiddleware>();
app.MapGet("/health", () => Results.Json(new
app.UseSwagger();
app.UseSwaggerUI(options =>
{
status = "ok"
}));
options.SwaggerEndpoint("v1/swagger.json", $"{settings.AppName} v1");
});
app.MapControllers();
app.Run();