-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
125 lines (103 loc) · 3.77 KB
/
Copy pathProgram.cs
File metadata and controls
125 lines (103 loc) · 3.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.IdentityModel.Tokens;
using SalesAPI;
using System.Text;
OfficeOpenXml.ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
// CLI: dotnet run -- verify-clients <path-to-xlsx>
if (args.Length >= 2 && args[0] == "verify-clients")
{
var workbookPath = args[1];
var tempDb = Path.Combine(Path.GetTempPath(), $"client-verify-{Guid.NewGuid():N}.db");
try
{
var report = ExcelParser.ParseClientListWithReport(workbookPath);
Console.WriteLine($"RAW={report.RawRowCount}");
Console.WriteLine($"UNIQUE={report.UniqueSoldToCodeCount}");
Console.WriteLine($"DUPLICATE_ROWS={report.DuplicateSoldToRowCount}");
Console.WriteLine($"DUPLICATE_CODES={report.DuplicateSoldToCodes.Count}");
Console.WriteLine($"INACTIVE={report.InactiveMarkedRows}");
Console.WriteLine($"ACTIVE={report.UniqueActiveSoldToCodeCount}");
Console.WriteLine($"PARSED={report.ParsedClientCount}");
var db = new DatabaseHelper(tempDb);
db.DeleteAllClients();
foreach (var client in report.Clients)
db.UpsertClient(client);
var stored = db.GetActiveClientCount();
var api = db.GetAllClients().Count;
var repPortal = api;
Console.WriteLine($"STORED={stored}");
Console.WriteLine($"API={api}");
Console.WriteLine($"REP={repPortal}");
var integrity = ClientImportIntegrity.Validate(report, stored, api, repPortal);
foreach (var w in integrity.Warnings)
Console.WriteLine($"WARN={w}");
foreach (var e in integrity.Errors)
Console.WriteLine($"ERROR={e}");
Console.WriteLine($"VALID={(integrity.IsValid ? 1 : 0)}");
if (!integrity.IsValid)
Environment.Exit(1);
return;
}
finally
{
try { if (File.Exists(tempDb)) File.Delete(tempDb); } catch { }
}
}
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseUrls("http://0.0.0.0:4010");
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Register DatabaseHelper as singleton with lazy initialization
var dbPath = "sales.db";
builder.Services.AddSingleton(_ => new DatabaseHelper(dbPath));
builder.Services.AddHostedService<BootstrapUsersHostedService>();
// Configure JWT Authentication
var jwtKey = builder.Configuration["Jwt:Key"] ?? "your-secret-key-min-32-characters-long";
var jwtIssuer = builder.Configuration["Jwt:Issuer"] ?? "SalesAPI";
var jwtAudience = builder.Configuration["Jwt:Audience"] ?? "SalesAPI";
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = jwtIssuer,
ValidAudience = jwtAudience,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey))
};
});
builder.Services.AddAuthorization();
// Configure CORS
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll", policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseSwagger();
app.UseSwaggerUI();
// Serve static files (HTML, CSS, JS)
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseCors("AllowAll");
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
// Fallback to index.html for SPA routing
app.MapFallbackToFile("index.html");
app.Run();