-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
158 lines (133 loc) · 4.97 KB
/
Program.cs
File metadata and controls
158 lines (133 loc) · 4.97 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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System.Text.Json.Serialization;
using ValuationBackend.Data;
using ValuationBackend.Extensions;
using ValuationBackend.Models;
using DotNetEnv;
using ValuationBackend.Services;
// Load environment variables from .env file
Env.Load();
var builder = WebApplication.CreateBuilder(args);
// Add services to the container
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
// Configure enum serialization to use string names instead of integer values
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Register AutoMapper
builder.Services.AddAutoMapper(typeof(Program).Assembly);
// Register HttpContextAccessor
builder.Services.AddHttpContextAccessor();
// Register repositories and services using extension methods
builder.Services.AddRepositories();
builder.Services.AddServices();
builder.Services.AddScoped<IEmailSender, EmailSender>();
builder.Services.AddScoped<PasswordResetService>();
// Configure PostgreSQL
var connectionString = Environment.GetEnvironmentVariable("DB_CONNECTION_STRING")
?? builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseNpgsql(connectionString));
// Configure JWT settings from environment variables or fallback to appsettings.json
var jwtSettings = new JwtSettings
{
SecretKey = Environment.GetEnvironmentVariable("JWT_SECRET_KEY")
?? builder.Configuration["JwtSettings:SecretKey"]
?? "fallback-secret-key-for-development-only-min-32-chars",
Issuer = Environment.GetEnvironmentVariable("JWT_ISSUER")
?? builder.Configuration["JwtSettings:Issuer"]
?? "ValuationBackend",
Audience = Environment.GetEnvironmentVariable("JWT_AUDIENCE")
?? builder.Configuration["JwtSettings:Audience"]
?? "ValuationUsers",
ExpiryMinutes = int.TryParse(Environment.GetEnvironmentVariable("JWT_EXPIRY_MINUTES"), out var expiry)
? expiry : (int.TryParse(builder.Configuration["JwtSettings:ExpiryMinutes"], out var configExpiry) ? configExpiry : 60)
};
// Register JWT settings
builder.Services.Configure<JwtSettings>(options =>
{
options.SecretKey = jwtSettings.SecretKey;
options.Issuer = jwtSettings.Issuer;
options.Audience = jwtSettings.Audience;
options.ExpiryMinutes = jwtSettings.ExpiryMinutes;
});
builder.Services.AddDbContext<ValuationContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
// Add Authentication
var key = Encoding.UTF8.GetBytes(jwtSettings.SecretKey);
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 = jwtSettings.Issuer,
ValidAudience = jwtSettings.Audience,
IssuerSigningKey = new SymmetricSecurityKey(key)
};
});
// CORS Policy (allow all — adjust as needed)
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll", policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
// Build the app
var app = builder.Build();
// Initialize database with error handling
using (var scope = app.Services.CreateScope())
{
try
{
var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
// Only reset database if explicitly requested (e.g., via environment variable)
var shouldResetDb = Environment.GetEnvironmentVariable("RESET_DATABASE")?.ToLower() == "true";
if (shouldResetDb)
{
Console.WriteLine("Resetting database...");
// Add database reset logic here if needed
}
DbInitializer.Initialize(dbContext);
Console.WriteLine("Database initialized successfully.");
}
catch (Exception ex)
{
Console.WriteLine($"Database initialization failed: {ex.Message}");
Console.WriteLine("Application will continue without database initialization.");
Console.WriteLine("Swagger UI will still be available for API documentation.");
}
}
// Configure middleware
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
else
{
app.UseHttpsRedirection(); // Only enable in production
}
app.UseCors("AllowAll");
app.UseAuthentication(); // Must come before Authorization
app.UseAuthorization();
app.MapControllers();
app.Run();
// Make Program class accessible to test projects
public partial class Program { }