Updates to see others' students

This commit is contained in:
ivan-pelly
2026-04-08 07:56:04 -07:00
parent 0a8d2ebb59
commit 59de3bb2e5
15 changed files with 278 additions and 53 deletions
+2 -2
View File
@@ -17,7 +17,7 @@ public class StudentController : BaseController
[HttpGet("my")]
[Authorize(Roles = $"{UserRoles.Teacher},{UserRoles.Paraeducator},{UserRoles.ProgramAdmin}")]
[ProducesResponseType(typeof(ResponseResult<IEnumerable<StudentResponse>>), StatusCodes.Status200OK)]
public async Task<ActionResult<ResponseResult<IEnumerable<StudentResponse>>>> GetMyStudents()
public async Task<ActionResult<ResponseResult<IEnumerable<StudentResponse>>>> GetMyStudents([FromQuery] string? scope = null)
{
var (userId, email, programId, role, error) = GetProgramUserFromClaims();
@@ -26,7 +26,7 @@ public class StudentController : BaseController
return error;
}
var students = await _studentRepository.GetMyStudentsAsync(userId, programId, role);
var students = await _studentRepository.GetMyStudentsAsync(userId, programId, role, scope);
return Ok(new ResponseResult<IEnumerable<StudentResponse>>
{
@@ -6,4 +6,5 @@ public class dbUserStudent
public Guid? IdUser { get; set; }
public Guid? IdStudent { get; set; }
public bool? IsPrimary { get; set; }
public string? OwnerName { get; set; }
}
@@ -10,22 +10,38 @@ public class StudentRepository
{
private IDbConnection Connection => new MySqlConnection(DatabaseManager.ConnectionString);
public async Task<IEnumerable<StudentResponse>> GetMyStudentsAsync(Guid userId, Guid programId, string role)
// *****************************************************************
// Returns students visible to the current user. When scope is
// "all", returns every student in the program enriched with the
// owning user's name. Otherwise returns only the user's own.
// *****************************************************************
public async Task<IEnumerable<StudentResponse>> GetMyStudentsAsync(Guid userId, Guid programId, string role, string? scope = null)
{
using var db = Connection;
using var multi = await db.QueryMultipleAsync(
"sp_Student_GetWithAssignments",
new { p_id_program = programId.ToString(), p_id_user = userId.ToString() },
new { p_id_program = programId.ToString(), p_id_user = userId.ToString(), p_scope = scope },
commandType: CommandType.StoredProcedure);
var students = await multi.ReadAsync<StudentResponse>();
var assignments = await multi.ReadAsync<dbUserStudent>();
var students = (await multi.ReadAsync<StudentResponse>()).ToList();
var assignments = (await multi.ReadAsync<dbUserStudent>()).ToList();
var myStudents = students.Where(s =>
PermissionService.IsAllowed(role, EntityType.Student, PermissionAction.Read, assignments.Any(a => a.IdStudent == s.StudentId && a.IdUser == userId))
);
// When scope is "all", return every student in the program.
// Otherwise, return only students assigned to the current user.
var filtered = scope == "all"
? students
: students.Where(s => assignments.Any(a => a.IdStudent == s.StudentId && a.IdUser == userId)).ToList();
return myStudents;
// Enrich each student with the primary owner's display name and ownership flag.
foreach (var student in filtered)
{
var owner = assignments.FirstOrDefault(a => a.IdStudent == student.StudentId && (a.IsPrimary == true));
owner ??= assignments.FirstOrDefault(a => a.IdStudent == student.StudentId);
student.OwnerName = owner?.OwnerName;
student.IsMine = assignments.Any(a => a.IdStudent == student.StudentId && a.IdUser == userId);
}
return filtered;
}
public async Task<StudentResponse?> GetByIdAsync(Guid idStudent)
@@ -10,4 +10,6 @@ public class StudentResponse
public int GoalCount { get; set; }
public int ProgressEventCount { get; set; }
public int BenchmarkCount { get; set; }
public string? OwnerName { get; set; }
public bool IsMine { get; set; }
}
+11 -11
View File
@@ -210,29 +210,29 @@ public static class PermissionMatrix
[EntityType.Student] = new()
{
[PermissionAction.Create] = MineOnly,
[PermissionAction.Read] = MineOnly,
[PermissionAction.Update] = MineOnly,
[PermissionAction.Read] = Allow,
[PermissionAction.Update] = Allow,
[PermissionAction.Delete] = MineOnly,
},
[EntityType.Goal] = new()
{
[PermissionAction.Create] = MineOnly,
[PermissionAction.Read] = MineOnly,
[PermissionAction.Update] = MineOnly,
[PermissionAction.Create] = Allow,
[PermissionAction.Read] = Allow,
[PermissionAction.Update] = Allow,
[PermissionAction.Delete] = MineOnly,
},
[EntityType.ProgressEvent] = new()
{
[PermissionAction.Create] = MineOnly,
[PermissionAction.Read] = MineOnly,
[PermissionAction.Update] = MineOnly,
[PermissionAction.Create] = Allow,
[PermissionAction.Read] = Allow,
[PermissionAction.Update] = Allow,
[PermissionAction.Delete] = MineOnly,
},
[EntityType.Benchmark] = new()
{
[PermissionAction.Create] = MineOnly,
[PermissionAction.Read] = MineOnly,
[PermissionAction.Update] = MineOnly,
[PermissionAction.Create] = Allow,
[PermissionAction.Read] = Allow,
[PermissionAction.Update] = Allow,
[PermissionAction.Delete] = MineOnly,
},
},