API REST basata sui ruoli?

24

Sto costruendo un'API REST per la quale diversi utenti con ruoli diversi avranno accesso alle risorse che contiene.

Per mantenere l'ambito semplice, prendiamo il dominio "studente / insegnante / classe":

GET /students è la risorsa per accedere.

Gli utenti potrebbero avere ruoli come Studente e / o Insegnante

Gli studenti avranno accesso solo agli studenti delle loro classi. Gli insegnanti avranno accesso agli studenti delle classi che insegnano. Alcuni usi possono essere uno studente E insegnare anche altre classi. Devono avere accesso agli studenti delle loro classi E agli studenti delle classi che insegnano.

Idealmente voglio implementarlo come due funzioni: una per ruolo e poi "unione" se un utente ha più ruoli.

La mia domanda è: quale modello dovrei usare per implementarlo?

Esternamente

  • Devo dividere la mia API per ruolo? GET /teacher/students e GET /student/students Non mi sembra giusto.
  • Mantieni tutto sono una risorsa (preferita)

Internamente

Come dovrebbe essere implementato internamente?

  • Ogni metodo dovrebbe iniziare con un interruttore BIG / se per ruolo?
  • Devo implementare un repository per ruolo?
  • Esiste un modello di progettazione che mi aiuterà a raggiungere questo obiettivo?

Come commento a parte: sto usando API Web ASP.NET e Entity Framework 6 , ma in realtà non ha importanza per l'implementazione concettuale.

    
posta Casper Jensen 12.04.2015 - 10:00
fonte

2 risposte

11

Dovresti architettare l'API attorno alle risorse, non attorno ai ruoli, ad esempio:

/rest/students

dovrebbe essere accessibile a chiunque abbia un ruolo che permetta loro di vedere gli studenti.

Internamente, stai implementando la sicurezza basata sui ruoli. Il modo in cui procedi dipende dai dettagli della tua applicazione, ma supponiamo che tu disponga di una tabella di ruolo, che ogni persona abbia uno o più ruoli e che tali ruoli determinino a cosa ogni persona può accedere. Hai già dichiarato le regole per accedere agli studenti:

  • gli studenti possono accedere agli studenti nelle classi che prendono
  • gli insegnanti possono accedere agli studenti nelle classi che insegnano

Quindi quando una persona chiama:

/rest/students

chiami un metodo che accede agli studenti, passando nel ruolo della persona. Ecco alcuni pseudo codice:

roles = person.roles; //array
students = getStudents( roles );
return students;

e in tale metodo, potresti ottenere gli studenti per ciascun ruolo con chiamate separate, ad esempio:

factory = getFactory();
classes= [];
students = [];
for( role in roles ){
    service = factory.getService( role );
    // implementation details of how you get classes for student/teacher are hidden in the service
    classes = classes.merge( service.getClasses( person ) );
    // classes[] has class.students[]
    // loop on classes and add each student to students, or send back classes with nested students? depends on use case
  }
}

Questa è un'idea molto approssimativa per ciò che potresti fare e non è necessariamente adatta alle tue esigenze specifiche, ma dovrebbe darti un'idea dei pezzi coinvolti. Se si desidera restituire le classi con ogni studente elencato, questo è un buon approccio. Se vuoi solo gli studenti, puoi estrarli da ogni classe e unirli a una raccolta di studenti.

No, non dovresti avere un repository separato per ruolo. Tutto il ruolo consiste nel determinare in che modo ottenere i dati e forse cosa è possibile fare con i dati (ad esempio, gli insegnanti possono inserire i voti degli studenti). I dati stessi sono gli stessi.

Per quanto riguarda i pattern, questo approccio utilizza Pattern di fabbrica per astrarre il servizio che ottiene i dati in base al ruolo. Può o non può essere appropriato avere servizi separati per ruolo. Mi piace questo approccio perché riduce al minimo la quantità di codice in ogni fase del programma e lo rende più leggibile di un interruttore o di un blocco.

    
risposta data 12.04.2015 - 11:52
fonte
0

Trova una penna e un foglio e inizia a modellare il tuo sistema.

Troverete che probabilmente hai bisogno di un'entità di dominio chiamata PERSON. Poiché sia STUDENTI che INSEGNANTE "è-a" PERSON, puoi creare un'entità astratta denominata PERSON con attributi generici come nome, cognome, ecc. UN INSEGNANTE - > è-a - > Persona. Ora puoi provare a trovare le caratteristiche per un INSEGNANTE che non si applicano agli STUDENTI; per esempio. Un INSEGNANTE insegna CLASS (es) riguardo uno o più SOGGETTI.

L'applicazione della sicurezza è considerata un aspetto non funzionale della tua applicazione. È una preoccupazione trasversale che dovrebbe essere gestita al di fuori della "logica aziendale". Come @Robert Munn sottolinea, il RUOLO (i) dovrebbe essere mantenuto in un unico posto. L'uso dei ruoli per limitare l'accesso a determinate funzioni è piuttosto grossolano e il concetto è chiamato controllo degli accessi basato sui ruoli (RBAC).

Per verificare se a un insegnante dovrebbe essere permesso di vedere i voti di uno studente, deve essere espresso nel modello di dominio. Supponiamo che un insegnante abbia una lezione sull'argomento di programmazione. Probabilmente potresti esprimere nel tuo modello che gli studenti frequentano le lezioni per materie diverse. È qui che entra in gioco la logica applicativa / aziendale. Questa è la logica che puoi verificare utilizzando lo sviluppo basato su test.

dovresti dividere le tue risorse per rendere la tua applicazione testabile e modulare.

Ad ogni modo, il modo migliore per mostrare veramente cosa intendo è mostrarlo con codice :) Ecco una pagina GitHub: link

Buona fortuna:)

    
risposta data 25.04.2015 - 05:02
fonte

Leggi altre domande sui tag