Есть три роли: admin, area(оператор района) и school(оператор школы).
Имена area-пользователей совпадают с Id из таблицы Area базы данных.
Имена school-пользователей совпадают с Id из таблицы School базы данных.
area-пользователи должны иметь доступ только к студентам своего района, т.е. имя area-пользователя и StudentDto.AreaId должны совпадать. school-пользователи должны иметь доступ только к студентам своей школы, т.е. имя school-пользователя и StudentDto.SchoolId должны совпадать.
А теперь код:
public class Student
{
public string Surname { get; set; }
public string Name { get; set; }
public string SchoolId { get; set; }
public virtual School School { get; set; }
}
public class School
{
public int Id { get; set; }
public string Name { get; set; }
public int AreaId { get; set; }
public virtual Area Area { get; set; }
}
public class Area
{
public int Id { get; set; }
public int Name { get; set; }
}
public class StudentDto
{
public string Id { get; set; }
public string Surname { get; set; }
public string Name { get; set; }
public int SchoolId { get; set; }
public int AreaId { get; set; }
}
public interface IStudentService
{
IEnumerable<StudentDto> GetAll(int? areaId, int? schoolId);
}
[RoutePrefix("api/students")]
public class StudentsController : ApiController
{
private readonly IStudentService _studentService;
public StudentsController(IStudentService studentService)
{
_studentService = studentService;
}
[HttpGet]
public IHttpActionResult GetAll(int? areaId, int? schoolId)
{
var studentDtos = _studentService.GetAll(areaId: areaId, schoolId: schoolId);
var authorizedUser = User.Identity.Name;
if (User.IsInRole("school"))
{
if (!studentDtos.All(dto => dto.SchoolId.ToString() == authorizedUser))
{
return StatusCode(HttpStatusCode.Forbidden);
}
}
if (User.IsInRole("area"))
{
if (!studentDtos.All(dto => dto.AreaId.ToString() == authorizedUser))
{
return StatusCode(HttpStatusCode.Forbidden);
}
}
return Ok(studentDtos);
}
}
Хочется чтобы URI получения списка студентов для всех трех типов пользователей был одинаков GET: .../api/students, как я понимаю так и должно быть согласно REST (если это не так, то подправьте).
Насколько правильно все сделал я в выше описанном коде, не слишком ли нагружен метод контроллера? В частности интересует, что говорит "хорошая практика" о том как выполнена валидация?
Я также рассматривал вариант создания кастомного атрибута (фильтр) или создание отдельных URI для каждого типа пользователя, типа: api/students/admin, api/students/area, api/students/school. С кастомным атрибутом я так и не разобрался, т.к. на входе нельзя валидировать список студентов - ведь его сначала надо получить (или ничего страшного если получение организовать в самом фильтре?). А касаемо отдельных URI, то как писал выше, то это уже не REST.
GET: .../api/students
Да, это соответствует REST naming guidelines
Если быть точнее то вам надо таки писать:
GET: .../api/students?role=school
В параметрах принято указывать фильтрацию, роль коей у вас выполняют ваши роли.
Продвижение своими сайтами как стратегия роста и независимости