Skip to content
Merged
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
88 changes: 0 additions & 88 deletions .github/workflows/backend-deployment.yaml

This file was deleted.

30 changes: 0 additions & 30 deletions .github/workflows/firebase-hosting-pull-request.yml

This file was deleted.

16 changes: 16 additions & 0 deletions Caddyfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
# Global options
}

# Domain will be replaced by the setup script
{$SITE_ADDRESS:http://localhost} {
# Route API requests to the backend container
handle_path /api/* {
reverse_proxy backend:8080
}

# Everything else goes to the web container (Vite SPA)
handle {
reverse_proxy web:80
}
}
22 changes: 5 additions & 17 deletions backend/Api/Controllers/AnnouncementController.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
using Application.DTOs.Announcements;
using Application.DTOs.Tenant;
using Application.Services;
using Domain.Exceptions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using Api.Filters;

namespace Api.Controllers;

[Route("classes/{classId}/announcements")]
[ApiController]
[ServiceFilter(typeof(TenantFilter))]
public class AnnouncementController(AnnouncementService announcementService) : ControllerBase
{
public readonly AnnouncementService _announcementService = announcementService;
Expand All @@ -20,15 +17,12 @@ public class AnnouncementController(AnnouncementService announcementService) : C
[Authorize(Policy = "RequireStaff")]
[Authorize(Policy = "RequireEducator")]
public async Task<IActionResult> CreateAnnouncement([FromRoute] string classId, [FromBody] CreateAnnouncementDTO request)
{
var tenant = HttpContext.Items["Tenant"] as TokenTenantDTO;

if (!ModelState.IsValid)
{if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

var id = await _announcementService.CreateAnnouncement(tenant!, classId, request.Content, User.FindFirst(ClaimTypes.NameIdentifier)?.Value!, User.FindFirst("name")?.Value!);
var id = await _announcementService.CreateAnnouncement(classId, request.Content, User.FindFirst(ClaimTypes.NameIdentifier)?.Value!, User.FindFirst("name")?.Value!);

return StatusCode(StatusCodes.Status201Created, new {
id
Expand All @@ -38,10 +32,7 @@ public async Task<IActionResult> CreateAnnouncement([FromRoute] string classId,
[HttpGet]
[Authorize(Policy = "RequireStudentOrEducator")]
public async Task<IActionResult> GetAnnouncements([FromRoute] string classId)
{
var tenant = HttpContext.Items["Tenant"] as TokenTenantDTO;

var announcements = await _announcementService.GetAnnouncements(tenant!, classId, User.FindFirst(ClaimTypes.NameIdentifier)?.Value!);
{var announcements = await _announcementService.GetAnnouncements(classId, User.FindFirst(ClaimTypes.NameIdentifier)?.Value!);

return Ok(announcements);
}
Expand All @@ -50,12 +41,9 @@ public async Task<IActionResult> GetAnnouncements([FromRoute] string classId)
[Authorize(Policy = "RequireStaff")]
[Authorize(Policy = "RequireEducator")]
public async Task<IActionResult> DeleteAnnouncement([FromRoute] string classId, [FromRoute] string id)
{
var tenant = HttpContext.Items["Tenant"] as TokenTenantDTO;

try
{try
{
await _announcementService.DeleteAnnouncement(tenant!, classId, id, User.FindFirst(ClaimTypes.NameIdentifier)?.Value!);
await _announcementService.DeleteAnnouncement(classId, id, User.FindFirst(ClaimTypes.NameIdentifier)?.Value!);

return NoContent();
}
Expand Down
64 changes: 19 additions & 45 deletions backend/Api/Controllers/AssignmentController.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using Application.DTOs.Assignment;
using Application.DTOs.Tenant;
using Application.Services;
using Api.Filters;
using Domain.Exceptions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
Expand All @@ -12,32 +10,26 @@ namespace Api.Controllers;

[Route("classes/{classId}/assignments")]
[ApiController]
[ServiceFilter(typeof(TenantFilter))]
public class AssignmentController(AssignmentService assignmentService) : ControllerBase
{
public readonly AssignmentService _assignmentService = assignmentService;

[HttpGet]
[Authorize(Policy = "RequireStudentOrEducator")]
public async Task<IActionResult> GetAssignments([FromRoute] string classId)
{
var tenant = HttpContext.Items["Tenant"] as TokenTenantDTO;

var assignments = await _assignmentService.GetAssignments(tenant!, classId, Enum.Parse<UserType>(User.FindFirst("type")?.Value!), User.FindFirst(ClaimTypes.NameIdentifier)?.Value!);
{var assignments = await _assignmentService.GetAssignments(classId, Enum.Parse<UserType>(User.FindFirst("type")?.Value!), User.FindFirst(ClaimTypes.NameIdentifier)?.Value!);

return Ok(assignments);
}

[HttpGet("{id}")]
[Authorize(Policy = "RequireStudentOrEducator")]
public async Task<IActionResult> GetAssignment([FromRoute] string classId, [FromRoute] string id)
{
var tenant = HttpContext.Items["Tenant"] as TokenTenantDTO;
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value!;
{var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value!;

try
{
var assignment = await _assignmentService.GetAssignment(tenant!, classId, id, Enum.Parse<UserType>(User.FindFirst("type")?.Value!), userId);
var assignment = await _assignmentService.GetAssignment(classId, id, Enum.Parse<UserType>(User.FindFirst("type")?.Value!), userId);

return Ok(assignment);
}
Expand All @@ -50,12 +42,10 @@ public async Task<IActionResult> GetAssignment([FromRoute] string classId, [From
[HttpGet("{id}/submissions")]
[Authorize(Policy = "RequireEducator")]
public async Task<IActionResult> GetAssignmentSubmissions([FromRoute] string classId, [FromRoute] string id)
{
var tenant = HttpContext.Items["Tenant"] as TokenTenantDTO;
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value!;
{var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value!;
try
{
var submissions = await _assignmentService.GetAssignmentSubmissions(tenant!, classId, id, userId);
var submissions = await _assignmentService.GetAssignmentSubmissions(classId, id, userId);
return Ok(submissions);
}
catch (AssignmentNotFoundException)
Expand All @@ -68,16 +58,14 @@ public async Task<IActionResult> GetAssignmentSubmissions([FromRoute] string cla
[HttpPut]
[Authorize(Policy = "RequireEducator")]
public async Task<IActionResult> CreateAssignment([FromRoute] string classId, [FromBody] CreateAssignmentDTO request)
{
var tenant = HttpContext.Items["Tenant"] as TokenTenantDTO;
if (!ModelState.IsValid)
{if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var userId = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier)?.Value!;
try
{
var id = await _assignmentService.CreateAssignment(tenant!, classId, request.Title, request.Description, request.MaxGrade, request.DueDate, userId, request.IsVisible);
var id = await _assignmentService.CreateAssignment(classId, request.Title, request.Description, request.MaxGrade, request.DueDate, userId, request.IsVisible);
return StatusCode(StatusCodes.Status201Created, new { id });
}
catch (InvalidAssignmentException)
Expand All @@ -93,12 +81,10 @@ public async Task<IActionResult> UpdateAssignment([FromRoute] string classId, [F
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var tenant = HttpContext.Items["Tenant"] as TokenTenantDTO;
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value!;
}var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value!;
try
{
await _assignmentService.UpdateAssignment(tenant!, classId, id, request.Title, request.Description, request.DueDate, request.MaxGrade, request.IsVisible, userId);
await _assignmentService.UpdateAssignment(classId, id, request.Title, request.Description, request.DueDate, request.MaxGrade, request.IsVisible, userId);
return Ok();
}
catch (AssignmentNotFoundException)
Expand All @@ -113,12 +99,10 @@ public async Task<IActionResult> UpdateAssignment([FromRoute] string classId, [F
[HttpDelete("{id}")]
[Authorize(Policy = "RequireEducator")]
public async Task<IActionResult> DeleteAssignment([FromRoute] string classId, [FromRoute] string id)
{
var tenant = HttpContext.Items["Tenant"] as TokenTenantDTO;
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value!;
{var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value!;
try
{
await _assignmentService.DeleteAssignment(tenant!, classId, id, userId);
await _assignmentService.DeleteAssignment(classId, id, userId);
return NoContent();
}
catch (AssignmentNotFoundException)
Expand All @@ -131,14 +115,12 @@ public async Task<IActionResult> DeleteAssignment([FromRoute] string classId, [F
[HttpGet("{id}/submissions/{submissionId}/file")]
[Authorize(Policy = "RequireStudentOrEducator")]
public async Task<IActionResult> GetSubmissionFile([FromRoute] string classId, [FromRoute] string id, [FromRoute] string submissionId)
{
var tenant = HttpContext.Items["Tenant"] as TokenTenantDTO;
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value!;
{var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value!;
var userType = Enum.Parse<UserType>(User.FindFirst("type")?.Value!);

try
{
var response = await _assignmentService.GetSubmissionFile(tenant!, classId, id, submissionId, userId, userType);
var response = await _assignmentService.GetSubmissionFile(classId, id, submissionId, userId, userType);
return Ok(response);
}
catch (AssignmentNotFoundException)
Expand All @@ -154,12 +136,9 @@ public async Task<IActionResult> GetSubmissionFile([FromRoute] string classId, [
[HttpPut("{id}/submissions")]
[Authorize(Policy = "RequireStudent")]
public async Task<IActionResult> SubmitAssignment([FromRoute] string classId, [FromRoute] string id, [FromBody] AssignmentSubmissionRequestDTO request)
{
var tenant = HttpContext.Items["Tenant"] as TokenTenantDTO;

try
{try
{
var response = await _assignmentService.SubmitAssignment(tenant!, classId, id, User.FindFirst(ClaimTypes.NameIdentifier)?.Value!, request.Size, request.Type);
var response = await _assignmentService.SubmitAssignment(classId, id, User.FindFirst(ClaimTypes.NameIdentifier)?.Value!, request.Size, request.Type);

return StatusCode(StatusCodes.Status201Created, response);
}
Expand All @@ -179,13 +158,11 @@ public async Task<IActionResult> SubmitAssignment([FromRoute] string classId, [F
[HttpPost("{id}/submissions/{submissionId}/grade")]
[Authorize(Policy = "RequireEducator")]
public async Task<IActionResult> GradeSubmission([FromRoute] string classId, [FromRoute] string id, [FromRoute] string submissionId, [FromBody] GradeSubmissionRequestDTO request)
{
var tenant = HttpContext.Items["Tenant"] as TokenTenantDTO;
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value!;
{var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value!;

try
{
await _assignmentService.GradeSubmission(tenant!, classId, id, submissionId, request.Grade, userId);
await _assignmentService.GradeSubmission(classId, id, submissionId, request.Grade, userId);
return Ok();
}
catch (AssignmentNotFoundException)
Expand All @@ -205,12 +182,9 @@ public async Task<IActionResult> GradeSubmission([FromRoute] string classId, [Fr
[HttpPost("{id}/submissions/confirm")]
[Authorize(Policy = "RequireStudent")]
public async Task<IActionResult> ConfirmAssignment([FromRoute] string classId, [FromRoute] string id)
{
var tenant = HttpContext.Items["Tenant"] as TokenTenantDTO;

try
{try
{
await _assignmentService.ConfirmSubmission(tenant!, classId, id, User.FindFirst(ClaimTypes.NameIdentifier)?.Value!);
await _assignmentService.ConfirmSubmission(classId, id, User.FindFirst(ClaimTypes.NameIdentifier)?.Value!);

return Ok();
}
Expand Down
Loading
Loading