Mohammed Foud
commited on
Commit
·
9f6bef5
1
Parent(s):
0184a4d
first commit
Browse files- Dockerfile +208 -1
- src/Program.cs +1 -1
Dockerfile
CHANGED
@@ -22,4 +22,211 @@ RUN dotnet publish "Backend.csproj" -c Release -o /app/publish
|
|
22 |
FROM base AS final
|
23 |
WORKDIR /app
|
24 |
COPY --from=publish /app/publish .
|
25 |
-
ENTRYPOINT ["dotnet", "Backend.dll"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
FROM base AS final
|
23 |
WORKDIR /app
|
24 |
COPY --from=publish /app/publish .
|
25 |
+
ENTRYPOINT ["dotnet", "Backend.dll"]
|
26 |
+
|
27 |
+
|
28 |
+
using System.Text;
|
29 |
+
using System.Text.Json.Serialization;
|
30 |
+
using Backend_Teamwork.src.Database;
|
31 |
+
using Backend_Teamwork.src.Entities;
|
32 |
+
using Backend_Teamwork.src.Middleware;
|
33 |
+
using Backend_Teamwork.src.Repository;
|
34 |
+
using Backend_Teamwork.src.Services.artwork;
|
35 |
+
using Backend_Teamwork.src.Services.booking;
|
36 |
+
using Backend_Teamwork.src.Services.category;
|
37 |
+
using Backend_Teamwork.src.Services.order;
|
38 |
+
using Backend_Teamwork.src.Services.user;
|
39 |
+
using Backend_Teamwork.src.Services.workshop;
|
40 |
+
using Backend_Teamwork.src.Utils;
|
41 |
+
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
42 |
+
using Microsoft.EntityFrameworkCore;
|
43 |
+
using Microsoft.IdentityModel.Tokens;
|
44 |
+
using Npgsql;
|
45 |
+
using static Backend_Teamwork.src.Entities.User;
|
46 |
+
|
47 |
+
var builder = WebApplication.CreateBuilder(args);
|
48 |
+
|
49 |
+
//connect to database
|
50 |
+
var dataSourceBuilder = new NpgsqlDataSourceBuilder(
|
51 |
+
builder.Configuration.GetConnectionString("ConnectionStrings__Local")
|
52 |
+
);
|
53 |
+
dataSourceBuilder.MapEnum<UserRole>();
|
54 |
+
dataSourceBuilder.MapEnum<Status>();
|
55 |
+
|
56 |
+
//add database connection
|
57 |
+
builder.Services.AddDbContext<DatabaseContext>(options =>
|
58 |
+
{
|
59 |
+
options.UseNpgsql(dataSourceBuilder.Build());
|
60 |
+
});
|
61 |
+
|
62 |
+
//add auto-mapper
|
63 |
+
builder.Services.AddAutoMapper(typeof(MapperProfile).Assembly);
|
64 |
+
|
65 |
+
//add DI services
|
66 |
+
builder.Services.AddScoped<ICategoryService, CategoryService>().AddScoped<CategoryRepository>();
|
67 |
+
builder.Services.AddScoped<IArtworkService, ArtworkService>().AddScoped<ArtworkRepository>();
|
68 |
+
builder.Services.AddScoped<IUserService, UserService>().AddScoped<UserRepository>();
|
69 |
+
builder.Services.AddScoped<IOrderService, OrderService>().AddScoped<OrderRepository>();
|
70 |
+
builder.Services.AddScoped<IWorkshopService, WorkshopService>().AddScoped<WorkshopRepository>();
|
71 |
+
builder.Services.AddScoped<IBookingService, BookingService>().AddScoped<BookingRepository>();
|
72 |
+
|
73 |
+
//builder.Services.AddScoped<IPaymentService, IPaymentService>().AddScoped<PaymentRepository>();
|
74 |
+
|
75 |
+
|
76 |
+
//add logic for authentication
|
77 |
+
builder
|
78 |
+
.Services.AddAuthentication(options =>
|
79 |
+
{
|
80 |
+
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
81 |
+
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
82 |
+
})
|
83 |
+
.AddJwtBearer(Options =>
|
84 |
+
{
|
85 |
+
Options.TokenValidationParameters = new TokenValidationParameters
|
86 |
+
{
|
87 |
+
ValidateIssuer = true,
|
88 |
+
ValidateAudience = true,
|
89 |
+
ValidateLifetime = true,
|
90 |
+
ValidateIssuerSigningKey = true,
|
91 |
+
ValidIssuer = builder.Configuration["Jwt:Issuer"],
|
92 |
+
ValidAudience = builder.Configuration["Jwt:Audience"],
|
93 |
+
IssuerSigningKey = new SymmetricSecurityKey(
|
94 |
+
Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])
|
95 |
+
),
|
96 |
+
};
|
97 |
+
});
|
98 |
+
|
99 |
+
//add logic for athorization
|
100 |
+
builder.Services.AddAuthorization(options =>
|
101 |
+
{
|
102 |
+
options.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"));
|
103 |
+
options.AddPolicy("CustomerOnly", policy => policy.RequireRole("Customer"));
|
104 |
+
});
|
105 |
+
|
106 |
+
// *** add CORS settings ***
|
107 |
+
builder.Services.AddCors(options =>
|
108 |
+
{
|
109 |
+
options.AddPolicy("AllowAll",
|
110 |
+
policyBuilder => policyBuilder.AllowAnyOrigin()
|
111 |
+
.AllowAnyHeader()
|
112 |
+
.AllowAnyMethod());
|
113 |
+
});
|
114 |
+
// builder.Services.AddCors(options =>
|
115 |
+
// {
|
116 |
+
// options.AddPolicy("AllowSpecificOrigin",
|
117 |
+
// builder => builder.WithOrigins("http://localhost:5173")
|
118 |
+
// .AllowAnyHeader()
|
119 |
+
// .AllowAnyMethod());
|
120 |
+
// });
|
121 |
+
|
122 |
+
|
123 |
+
//add controllers
|
124 |
+
builder.Services.AddControllers();
|
125 |
+
builder.Services.AddEndpointsApiExplorer();
|
126 |
+
builder
|
127 |
+
.Services.AddControllers()
|
128 |
+
.AddJsonOptions(x => x.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles);
|
129 |
+
|
130 |
+
//add swagger
|
131 |
+
builder.Services.AddSwaggerGen();
|
132 |
+
|
133 |
+
var app = builder.Build();
|
134 |
+
app.UseRouting();
|
135 |
+
app.MapGet("/", () => "Server is running");
|
136 |
+
|
137 |
+
//Convert to Timestamp format
|
138 |
+
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
|
139 |
+
|
140 |
+
//
|
141 |
+
|
142 |
+
//test database connection
|
143 |
+
using (var scope = app.Services.CreateScope())
|
144 |
+
{
|
145 |
+
var services = scope.ServiceProvider;
|
146 |
+
var logger = services.GetRequiredService<ILogger<Program>>();
|
147 |
+
var dbContext = services.GetRequiredService<DatabaseContext>();
|
148 |
+
|
149 |
+
try
|
150 |
+
{
|
151 |
+
if (dbContext.Database.CanConnect())
|
152 |
+
{
|
153 |
+
logger.LogInformation("Database connection successful at {Time}", DateTimeOffset.Now);
|
154 |
+
|
155 |
+
// Check for pending migrations
|
156 |
+
var pendingMigrations = await dbContext.Database.GetPendingMigrationsAsync();
|
157 |
+
if (pendingMigrations.Any())
|
158 |
+
{
|
159 |
+
logger.LogInformation("Applying {Count} pending migrations...", pendingMigrations.Count());
|
160 |
+
foreach (var migration in pendingMigrations)
|
161 |
+
{
|
162 |
+
logger.LogInformation("Applying migration: {Migration}", migration);
|
163 |
+
}
|
164 |
+
await dbContext.Database.MigrateAsync();
|
165 |
+
logger.LogInformation("Migrations applied successfully");
|
166 |
+
}
|
167 |
+
else
|
168 |
+
{
|
169 |
+
logger.LogInformation("No pending migrations. Database is up to date");
|
170 |
+
}
|
171 |
+
|
172 |
+
// Optional: Seed data if needed
|
173 |
+
// await SeedData(dbContext, services);
|
174 |
+
}
|
175 |
+
else
|
176 |
+
{
|
177 |
+
logger.LogError("Unable to connect to the database at {Time}", DateTimeOffset.Now);
|
178 |
+
throw new ApplicationException("Database connection failed during startup");
|
179 |
+
}
|
180 |
+
}
|
181 |
+
catch (Exception ex)
|
182 |
+
{
|
183 |
+
logger.LogError(ex, "An error occurred while migrating the database at {Time}", DateTimeOffset.Now);
|
184 |
+
|
185 |
+
// In development, you might want to see the full error
|
186 |
+
if (app.Environment.IsDevelopment())
|
187 |
+
{
|
188 |
+
throw; // Re-throw in development for more details
|
189 |
+
}
|
190 |
+
|
191 |
+
// In production, throw a more generic error
|
192 |
+
throw new ApplicationException("A database error occurred during startup. Please check the logs for more details.");
|
193 |
+
}
|
194 |
+
}
|
195 |
+
|
196 |
+
// using (var scope = app.Services.CreateScope())
|
197 |
+
// {
|
198 |
+
// var dbContext = scope.ServiceProvider.GetRequiredService<DatabaseContext>();
|
199 |
+
// try
|
200 |
+
// {
|
201 |
+
// if (dbContext.Database.CanConnect())
|
202 |
+
// {
|
203 |
+
// Console.WriteLine("Database is connected");
|
204 |
+
// dbContext.Database.Migrate();
|
205 |
+
// }
|
206 |
+
// else
|
207 |
+
// {
|
208 |
+
// Console.WriteLine("Unable to connect to the database.");
|
209 |
+
// }
|
210 |
+
// }
|
211 |
+
// catch (Exception ex)
|
212 |
+
// {
|
213 |
+
// Console.WriteLine($"Database connection failed: {ex.Message}");
|
214 |
+
// }
|
215 |
+
// }
|
216 |
+
app.UseHttpsRedirection();
|
217 |
+
|
218 |
+
//use middleware
|
219 |
+
app.UseMiddleware<ErrorHandlerMiddleware>();
|
220 |
+
app.UseAuthentication();
|
221 |
+
app.UseAuthorization();
|
222 |
+
|
223 |
+
//use controllers
|
224 |
+
app.MapControllers();
|
225 |
+
|
226 |
+
//use swagger
|
227 |
+
if (app.Environment.IsDevelopment())
|
228 |
+
{
|
229 |
+
app.UseSwagger();
|
230 |
+
app.UseSwaggerUI();
|
231 |
+
}
|
232 |
+
app.Run();
|
src/Program.cs
CHANGED
@@ -21,7 +21,7 @@ var builder = WebApplication.CreateBuilder(args);
|
|
21 |
|
22 |
//connect to database
|
23 |
var dataSourceBuilder = new NpgsqlDataSourceBuilder(
|
24 |
-
builder.Configuration.GetConnectionString("
|
25 |
);
|
26 |
dataSourceBuilder.MapEnum<UserRole>();
|
27 |
dataSourceBuilder.MapEnum<Status>();
|
|
|
21 |
|
22 |
//connect to database
|
23 |
var dataSourceBuilder = new NpgsqlDataSourceBuilder(
|
24 |
+
builder.Configuration.GetConnectionString("Local")
|
25 |
);
|
26 |
dataSourceBuilder.MapEnum<UserRole>();
|
27 |
dataSourceBuilder.MapEnum<Status>();
|