Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 20 additions & 9 deletions src/Learnify.Api/Controllers/CoursesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,28 @@ public async Task<IActionResult> Update(int id, [FromForm] UpdateCourseRequest r
return Unauthorized("User not authenticated");
}

// TODO: Add authorization check to ensure user owns this course
// For now, we'll let the command handler deal with authorization
// Authorization check: Ensure user is admin or course owner
var isAdmin = User.IsInRole("Admin");
var course = await _mediator.Send(new GetCourseByIdQuery(id));

if (course == null)
{
return NotFound();
}

if (!isAdmin && course.InstructorId != currentUserId)
{
return Forbid("Only course owners or administrators can update courses");
}

var command = new UpdateCourseCommand(
id,
request.Title,
request.Description,
request.Price,
request.IsPublished,
request.ThumbnailImageUrl,
request.CategoryId,
id,
request.Title,
request.Description,
request.Price,
request.IsPublished,
request.ThumbnailImageUrl,
request.CategoryId,
request.ThumbnailFile);
await _mediator.Send(command);

Expand Down
24 changes: 22 additions & 2 deletions src/Learnify.Api/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,21 @@ public static async Task Main(string[] args)
builder.Services.AddRateLimitingPolicies();

// CORS
var allowedOrigins = builder.Configuration.GetSection("AllowedOrigins").Get<string[]>()
?? new[] { "http://localhost:3000", "http://localhost:5173", "https://localhost:3000" };

builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAllOrigins", policy =>
options.AddPolicy("ProductionCors", policy =>
{
policy.WithOrigins(allowedOrigins)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});

// Keep development policy for fallback
options.AddPolicy("DevelopmentCors", policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
Expand Down Expand Up @@ -137,7 +149,15 @@ public static async Task Main(string[] args)

app.UseStaticFiles();
app.UseMiddleware<ExceptionHandlerMiddleware>();
app.UseCors("AllowAllOrigins");

// HTTPS redirection (except in development)
if (!app.Environment.IsDevelopment())
{
app.UseHttpsRedirection();
app.UseHsts();
}

app.UseCors(builder.Environment.IsDevelopment() ? "DevelopmentCors" : "ProductionCors");
app.UseRateLimiter();
app.UseAuthentication();
app.UseAuthorization();
Expand Down
6 changes: 6 additions & 0 deletions src/Learnify.Api/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@
"App": {
"BaseUrl": "http://localhost:5279"
},
"AllowedOrigins": [
"http://localhost:3000",
"http://localhost:5173",
"https://localhost:3000",
"https://yourdomain.com"
],
"PerformanceLogging": {
"SlowThresholdMs": 500,
"VerySlowThresholdMs": 2000
Expand Down
5 changes: 2 additions & 3 deletions src/Learnify.Application/Learnify.Application.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@
<PackageReference Include="FluentValidation" Version="12.0.0" />
<PackageReference Include="Google.Apis.Auth" Version="1.73.0" />
<PackageReference Include="MediatR" Version="12.5.0" />
<PackageReference Include="FluentValidation" Version="12.0.0" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="12.0.0" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="12.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.2" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.1" />

</ItemGroup>

<ItemGroup>
Expand Down
Loading