Skip to content

Commit 556154f

Browse files
committed
- fix code
1 parent 29da661 commit 556154f

14 files changed

+404
-140
lines changed

src/eAuthor.API/Controllers/TemplateExportController.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,23 @@ namespace eAuthor.Controllers;
77
[ApiController]
88
[Route("api/templates")]
99
[Authorize]
10-
public class TemplateExportController : ControllerBase {
10+
public class TemplateExportController : ControllerBase
11+
{
1112
private readonly TemplateService _templateService;
1213
private readonly DynamicDocxBuilderService _builder;
1314

14-
public TemplateExportController(TemplateService templateService, DynamicDocxBuilderService builder) {
15+
public TemplateExportController(TemplateService templateService, DynamicDocxBuilderService builder)
16+
{
1517
_templateService = templateService;
1618
_builder = builder;
1719
}
1820

1921
[HttpGet("{id:guid}/export-dynamic-docx")]
20-
public async Task<IActionResult> ExportDynamic(Guid id) {
22+
public async Task<IActionResult> ExportDynamic(Guid id)
23+
{
2124
var template = await _templateService.GetAsync(id);
22-
if (template == null) return NotFound();
25+
if (template == null)
26+
return NotFound();
2327
var bytes = _builder.Build(template);
2428
return File(bytes,
2529
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",

src/eAuthor.API/Program.cs

Lines changed: 228 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,230 @@
1-
// Add registrations (only the new lines shown; keep existing ones)
1+
using System.Text;
2+
using System.Text.Json;
3+
using System.Text.Json.Serialization;
24
using eAuthor.Services;
5+
using eAuthor.Services.Expressions;
6+
using Microsoft.AspNetCore.Authentication.JwtBearer;
7+
using Microsoft.AspNetCore.Http.HttpResults;
8+
using Microsoft.AspNetCore.Mvc;
9+
using Microsoft.Extensions.Options;
10+
using Microsoft.IdentityModel.Tokens;
311

4-
builder.Services.AddScoped<StyleRenderer>();
5-
builder.Services.AddScoped<DynamicDocxBuilderService>();
6-
builder.Services.AddScoped<HtmlToDynamicConverter>();
12+
// using WordTemplating.Core.Repositories; // Uncomment when repository interfaces are present
13+
// using WordTemplating.Core.Background; // Uncomment if you have a batch worker hosted service
14+
15+
// NOTE: This Program.cs is a consolidated "final" version aligned with the documented architecture.
16+
// Adjust namespaces to match your actual project structure if they differ.
17+
18+
var builder = WebApplication.CreateBuilder(args);
19+
20+
// ------------------------------------------------------------
21+
// Configuration & Constants
22+
// ------------------------------------------------------------
23+
var jwtKey = builder.Configuration["Jwt:Key"] ?? "DEV_INSECURE_KEY_CHANGE_ME";
24+
var allowAnyCors = builder.Configuration.GetValue("Cors:AllowAny", true);
25+
26+
// ------------------------------------------------------------
27+
// JSON Options
28+
// ------------------------------------------------------------
29+
builder.Services
30+
.AddControllers()
31+
.AddJsonOptions(o =>
32+
{
33+
o.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
34+
o.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
35+
o.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
36+
});
37+
38+
// Return problem details for model validation errors
39+
builder.Services.Configure<ApiBehaviorOptions>(opt =>
40+
{
41+
opt.InvalidModelStateResponseFactory = ctx =>
42+
{
43+
var problem = new ValidationProblemDetails(ctx.ModelState)
44+
{
45+
Status = StatusCodes.Status400BadRequest,
46+
Title = "Request validation failed",
47+
};
48+
return new BadRequestObjectResult(problem);
49+
};
50+
});
51+
52+
// ------------------------------------------------------------
53+
// CORS
54+
// ------------------------------------------------------------
55+
builder.Services.AddCors(opt =>
56+
{
57+
if (allowAnyCors)
58+
{
59+
opt.AddPolicy("DevOpen",
60+
p => p.AllowAnyOrigin()
61+
.AllowAnyHeader()
62+
.AllowAnyMethod());
63+
}
64+
else
65+
{
66+
opt.AddPolicy("Restricted", p =>
67+
{
68+
var origins = builder.Configuration.GetSection("Cors:Origins").Get<string[]>() ?? Array.Empty<string>();
69+
p.WithOrigins(origins)
70+
.AllowAnyHeader()
71+
.AllowAnyMethod();
72+
});
73+
}
74+
});
75+
76+
// ------------------------------------------------------------
77+
// Authentication (JWT)
78+
// ------------------------------------------------------------
79+
var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey));
80+
builder.Services
81+
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
82+
.AddJwtBearer(opt =>
83+
{
84+
opt.RequireHttpsMetadata = false;
85+
opt.TokenValidationParameters = new TokenValidationParameters
86+
{
87+
ValidateIssuer = false,
88+
ValidateAudience = false,
89+
ValidateIssuerSigningKey = true,
90+
IssuerSigningKey = signingKey,
91+
ValidateLifetime = true,
92+
ClockSkew = TimeSpan.FromMinutes(2)
93+
};
94+
});
95+
96+
// ------------------------------------------------------------
97+
// Authorization (basic – extend with policies/roles as needed)
98+
// ------------------------------------------------------------
99+
builder.Services.AddAuthorization();
100+
101+
// ------------------------------------------------------------
102+
// Swagger / OpenAPI
103+
// ------------------------------------------------------------
104+
builder.Services.AddEndpointsApiExplorer();
105+
builder.Services.AddSwaggerGen(cfg =>
106+
{
107+
cfg.SwaggerDoc("v1", new()
108+
{
109+
Title = "Word Templating API",
110+
Version = "v1",
111+
Description = "Dynamic DOCX generation & templating platform"
112+
});
113+
114+
// JWT header
115+
cfg.AddSecurityDefinition("Bearer", new()
116+
{
117+
In = Microsoft.OpenApi.Models.ParameterLocation.Header,
118+
Description = "JWT Authorization header using the Bearer scheme. Example: \"Bearer {token}\"",
119+
Name = "Authorization",
120+
Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey
121+
});
122+
cfg.AddSecurityRequirement(new()
123+
{
124+
{
125+
new() { Reference = new() { Id = "Bearer", Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme } },
126+
Array.Empty<string>()
127+
}
128+
});
129+
});
130+
131+
// ------------------------------------------------------------
132+
// Core / Domain Services Registration
133+
// ------------------------------------------------------------
134+
135+
// Expression + Conditional system
136+
builder.Services.AddSingleton<IExpressionParser, ExpressionParser>();
137+
builder.Services.AddSingleton<IExpressionEvaluator, ExpressionEvaluator>();
138+
builder.Services.AddSingleton<IConditionalBlockProcessor, ConditionalBlockProcessor>();
139+
140+
// Rendering / DOCX build
141+
builder.Services.AddSingleton<StyleRenderer>();
142+
builder.Services.AddSingleton<DynamicDocxBuilderService>();
143+
144+
// If you have repeater / conditional processors beyond the interface above, register them here.
145+
// builder.Services.AddSingleton<IRepeaterBlockProcessor, RepeaterBlockProcessor>();
146+
147+
// Repositories & Data Access: register your custom implementations (uncomment & adjust):
148+
// builder.Services.AddScoped<ITemplateRepository, TemplateRepository>();
149+
// builder.Services.AddScoped<IXsdRepository, XsdRepository>();
150+
// builder.Services.AddScoped<IDocumentJobRepository, DocumentJobRepository>();
151+
// builder.Services.AddScoped<IBaseDocxTemplateRepository, BaseDocxTemplateRepository>();
152+
153+
// Batch job queue / worker (uncomment when implemented):
154+
// builder.Services.AddSingleton<IDocumentJobQueue, InMemoryDocumentJobQueue>();
155+
// builder.Services.AddHostedService<BatchJobWorker>();
156+
157+
// ------------------------------------------------------------
158+
// Health & Monitoring
159+
// ------------------------------------------------------------
160+
builder.Services.AddHealthChecks();
161+
162+
// ------------------------------------------------------------
163+
// Build App
164+
// ------------------------------------------------------------
165+
var app = builder.Build();
166+
167+
// ------------------------------------------------------------
168+
// Middleware Pipeline
169+
// ------------------------------------------------------------
170+
if (app.Environment.IsDevelopment())
171+
{
172+
app.UseSwagger();
173+
app.UseSwaggerUI();
174+
}
175+
176+
// Security headers (basic – extend as needed)
177+
app.Use(async (ctx, next) =>
178+
{
179+
ctx.Response.Headers.TryAdd("X-Content-Type-Options", "nosniff");
180+
ctx.Response.Headers.TryAdd("X-Frame-Options", "DENY");
181+
ctx.Response.Headers.TryAdd("X-XSS-Protection", "1; mode=block");
182+
await next();
183+
});
184+
185+
// Global exception handling (lightweight)
186+
app.UseExceptionHandler(errorApp =>
187+
{
188+
errorApp.Run(async context =>
189+
{
190+
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
191+
context.Response.ContentType = "application/json";
192+
var problem = new
193+
{
194+
error = "Unhandled server error",
195+
traceId = context.TraceIdentifier
196+
};
197+
await context.Response.WriteAsJsonAsync(problem);
198+
});
199+
});
200+
201+
app.UseCors(allowAnyCors ? "DevOpen" : "Restricted");
202+
app.UseAuthentication();
203+
app.UseAuthorization();
204+
205+
// Map controllers
206+
app.MapControllers();
207+
208+
// Minimal health endpoint(s)
209+
app.MapHealthChecks("/health");
210+
app.MapGet("/ready", () => Results.Ok(new { status = "ready" }));
211+
212+
// Example minimal endpoint (can remove if all logic is via controllers)
213+
app.MapGet("/", () => Results.Ok(new
214+
{
215+
name = "Word Templating & Dynamic DOCX Platform",
216+
version = typeof(Program).Assembly.GetName().Version?.ToString() ?? "dev"
217+
}));
218+
219+
// ------------------------------------------------------------
220+
// Start
221+
// ------------------------------------------------------------
222+
app.Run();
223+
224+
/// <summary>
225+
/// Dummy Program class to satisfy certain hosting scenarios / tests.
226+
/// </summary>
227+
public partial class Program
228+
{
229+
// Intentionally left blank – used for WebApplicationFactory in integration tests.
230+
}

src/eAuthor.API/Services/DocumentGenerationService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using eAuthor.Services.Expressions;
77
using eAuthor.Models;
88

9-
namespace eAuthor.Services.Expressions;
9+
namespace eAuthor.Services;
1010

1111
public class DocumentGenerationService
1212
{

0 commit comments

Comments
 (0)