Estou criando uma API REST para a qual vários usuários com funções diferentes terão acesso aos recursos que ela contém.
Para manter o escopo simples, vamos usar o domínio "aluno / professor / turma":
GET /students
é o recurso a acessar.
Os usuários podem ter funções como Aluno e / ou Professor
Os alunos terão acesso apenas aos alunos de suas aulas. Os professores terão acesso aos alunos das aulas que ministram. Alguns usos podem ser um aluno E dar outras aulas também. Eles devem ter acesso aos alunos de suas turmas E aos alunos das turmas que ministram.
Idealmente, quero implementar isso como duas funções - uma por função e, em seguida, "união" se um usuário tiver várias funções.
Minha pergunta é: Qual padrão devo usar para implementar isso?
Externamente
- Devo dividir minha API por função?
GET /teacher/students
eGET /student/students
isso não parece certo para mim. - Mantenha tudo que eu sou um recurso (preferencial)
Internamente
Como deve ser implementado internamente?
- Todo método deve começar com um switch BIG / se por função?
- Devo implementar um repositório por função?
- Existe um padrão de design que me ajudará a conseguir isso?
Como um comentário secundário: estou usando a API Web do ASP.NET e o Entity Framework 6 , mas isso realmente não importa para a implementação conceitual.
fonte
Respostas:
Você deve arquitetar a API em torno de recursos, não de funções, por exemplo:
deve ser acessível a qualquer pessoa com uma função que permita que eles vejam os alunos.
Internamente, você está implementando segurança baseada em função. Como você faz isso depende dos detalhes do seu aplicativo, mas digamos que você tenha uma tabela de funções, cada pessoa tenha uma ou mais funções e essas funções determinam o que cada pessoa pode acessar. Você já declarou as regras para acessar os alunos:
Então, quando uma pessoa liga:
você chama um método que acessa os alunos, passando o papel da pessoa. Aqui está algum pseudo-código:
e nesse método, você pode obter os alunos para cada função com chamadas separadas, por exemplo:
Essa é uma ideia muito rudimentar para o que você poderia fazer e não necessariamente atender às suas necessidades específicas, mas deve fornecer uma ideia das peças envolvidas. Se você deseja devolver as aulas com cada aluno listado, esta é uma boa abordagem. Se você quiser apenas os alunos, poderá extraí-los de cada classe e fundi-los em uma coleção de alunos.
Não, você não deve ter um repositório separado por função. Tudo o que a função desempenha é determinar como você obtém os dados e, talvez, o que você pode fazer com os dados (por exemplo, os professores podem inserir as notas dos alunos). Os dados em si são os mesmos.
Quanto aos padrões, essa abordagem está usando o Factory Pattern para abstrair o serviço que obtém dados com base na função. Pode ou não ser apropriado ter serviços separados por função. Eu gosto dessa abordagem porque minimiza a quantidade de código em cada estágio do programa e o torna mais legível do que um switch ou um bloco if.
fonte
Encontre uma caneta e um papel e comece a modelar seu sistema.
Você descobrirá que provavelmente precisa de uma entidade de domínio chamada PERSON. Como ALUNOS e PROFESSOR "é" uma "PESSOA, você pode criar uma entidade abstrata chamada PERSON com atributos genéricos como nome, sobrenome, etc. UM PROFESSOR -> é-uma -> Pessoa. Agora você pode tentar encontrar características para um PROFESSOR que não se aplica a ALUNOS; por exemplo, UM PROFESSOR ensina CLASSE (s) em relação a um ou mais ASSUNTO (s).
A imposição da segurança é considerada um aspecto não funcional do seu aplicativo. É uma preocupação transversal que deve ser tratada fora da sua "lógica de negócios". Como aponta o @Robert Munn, todos os ROLE (s) devem ser mantidos em um só lugar. O uso de funções para limitar o acesso a determinadas funções é bastante granular e o conceito é chamado de controle de acesso baseado em função (RBAC).
Para verificar se um professor deve ou não receber as notas de um aluno, ele deve ser expresso no seu modelo de domínio. Digamos que um professor tenha uma aula sobre programação de assuntos. Você provavelmente expressaria em seu modelo que os alunos freqüentam aulas para diferentes disciplinas. É aqui que a lógica do aplicativo / negócios entra em ação. Essa é a lógica que você pode verificar usando o desenvolvimento orientado a testes.
Você deve dividir seus recursos para tornar seu aplicativo testável e modular.
De qualquer forma, a melhor maneira de realmente mostrar o que quero dizer é mostrá-lo com código :) Aqui está uma página do GitHub: https://github.com/thomasandersen77/role-based-rest-api
Boa sorte :)
fonte