Laden...

Rückgabe verschiedener DTOs: Welche Auswirkungen auf Swagger?

Erstellt von emuuu vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.099 Views
emuuu Themenstarter:in
286 Beiträge seit 2011
vor 4 Jahren
Rückgabe verschiedener DTOs: Welche Auswirkungen auf Swagger?

Guten Tag zusammen,

der Titel umreißt meine Frage schon relativ klar. Ich habe eine Entity "Person" die mit unterschiedlicher Authorisierung abgerufen werden kann.
Sprich ein Admin kann nur iwelche technischen Daten sehen, AccountManager alles bis auf die technischen Daten usw.

Dem was ich bisher gelesen habe nach, ist der beste Ansatz hierfür verschiedene DTOs zu verwenden:
PersonForAdminDTO, PersonForAccountManagerDTO, PersonForItselfDTO, usw.

Zwei Sachen stören mich daran nur:

  1. Ich müsste den Authorization-Teil der BLL von der Service-Klasse in den Controller schieben, da ich nur hier "problemlos" unterschiedliche Klassen zurückgeben kann
  2. Wie wirkt sich das auf Swagger aus? Sollte ich hier voneinander abgeleitete Klassen oder Interfaces verwenden. Oder ist das für einen produktiven Einsatz von Swagger relativ egal wenn die selbe Route unterschiedliche DTOs zurückgibt?

Beste Grüße
emuuu

2+2=5( (für extrem große Werte von 2)

16.835 Beiträge seit 2008
vor 4 Jahren

Höre ich zum ersten Mal, dass man hier verschiedene DTOs verwenden soll. Wo steht das denn?

Üblicherweise hat man pro Action definitiv nur eine einzige DTO.
Und gewisse Eigenschaften / Felder können dann einfach null sein, wenn die Authorisierung das entsprechend nicht füllen will.

Die Authorisierung selbst kann problemlos in der Logik-Schicht bleiben.
Wenn die Action was entscheiden kann, dann über Policies.

emuuu Themenstarter:in
286 Beiträge seit 2011
vor 4 Jahren

Höre ich zum ersten Mal, dass man hier verschiedene DTOs verwenden soll. Wo steht das denn?

War auf Stackoverflow in einigen Threads die accepted answer. Ohne dass in den Kommentaren groß dagegen argumentiert wurde.

Ich bin natürlich faul und würde das gerne über Automapper lösen:
Könnte ich mir einfach für alle Authorisierungs-Szenarien ein "Zwischenmapping" erstellen?
Also abhängig vom Zugriff mappe ich die Entity erst auf z.b. auf das PersonForAdminDTO und dann auf das PersonDTO.

Könnte ich z.B. einfach in jede Serviceklasse das einfügen:


private PersonDTO FilterByAuthorization(Person person)
{
   if (_user.IsInRole("Admin"))
   {
      var personForAdminDto = _mapper.Map<PersonForAdminDTO>(person);
      return _mapper.Map<PersonDTO>(personForAdminDto);
   }
   else if 
   {
      //... other
   }
}

Ist in meiner Vorstellung der praktischste Weg alle nicht freigegebenen Felder zu nullen.

2+2=5( (für extrem große Werte von 2)

16.835 Beiträge seit 2008
vor 4 Jahren

Accepted Answer auf SO... 😁
Da enthalte ich mich einfach mal der Aussage 🙂

Automapper schenkt Dir das nicht. Das musst selbst machen.
AM erstellt statische Expression Trees, die nicht dynamisch erzeugt werden. Das wäre auch zu unperformant.
Wenn Du verschiedene Modelle hast musste halt mit den Nachteilen leben.
Rosinen-Picken ist nicht. 😉

Von Rollen-basierten Abfragen in Actions sollte man absehen. Dafür sind sie nicht gedacht.
Dafür gibt es IAuthorizationService und Policies.

Die Wege "simpel", "einfach", "richtig", "am besten" sind oft nicht die gleichen 🙂

T
2.224 Beiträge seit 2008
vor 4 Jahren

Alternativ, wie Abt schon andeutet, könnte auch eine Container Klasse sein, die dann die entsprechenden Benutzer als Properties anbietet.


public class UserResponse
{
    public PersonForAdminDTO AdminUser { get; set; }

    public PersonForAccountManagerDTO AccountManagerUser { get; set; }
}

Dann muss der Client prüfen welche Property gefüllt ist und muss dann diese entsprechend verarbeiten.
Ist kein schöner Ansatz, wäre aber eine wenn auch unschöne Lösung.
Wenn du die Daten ohne Verlust an Informationen aber auf ein einheitliches Objekt mappen kann, wie eben dein PersonDTO dann wäre der bessere Ansatz es direkt zu mappen und nur dein PersonDTO Objekt mit entsprechenden Properties zu liefern.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.835 Beiträge seit 2008
vor 4 Jahren

Alternativ, wie Abt schon andeutet, könnte auch eine Container Klasse sein, die dann die entsprechenden Benutzer als Properties anbietet.

Ne, hab ich nicht angedeutet. Halte ich auch für keine gute Idee.

Was ich sagte ist, dass die Eigenschaft einer DTO nullable sein kann basierend auf der Authorisierung - nicht die DTO selbst.

emuuu Themenstarter:in
286 Beiträge seit 2011
vor 4 Jahren

Automapper schenkt Dir das nicht. Das musst selbst machen.
AM erstellt statische Expression Trees, die nicht dynamisch erzeugt werden. Das wäre auch zu unperformant.
Wenn Du verschiedene Modelle hast musste halt mit den Nachteilen leben.

Den Vorteil den ich sehe wenn ich Zwischenmappings verwenden würde: Ich hätte für jedes Authorisierungszenario eine Klasse (eine Datei) in der übersichtlich zusammenläuft, wer was sehen kann.

Dafür gibt es IAuthorizationService und Policies.

Dazu hätte ich auch eine Frage:
Ist es legitim in einen AuthorizationHandler z.B. ein Repository zu injecten? Ich denke da vor allem an etwas komplexere Authorisierungszenarien:

Ich habe einen SimCards- und einen MobileDevices-Service. Jede SimCard ist einem MobileDevice zugeordnet, jedes MobileDevice einer Person.

Jetzt möchte Person den PIN der SimCard updaten -> das darf sie nur, wenn ihr das MobileDevice zugeordnet ist, dem die SimCard zugeordnet ist.

Der AuthorizationHandler müsste also selber die MobileDevice-Entity laden und prüfen, ob dort die PersonID mit dem aktuellen UserContext übereinstimmt.

Wäre das vom Vorgehen her legitim?

2+2=5( (für extrem große Werte von 2)

16.835 Beiträge seit 2008
vor 4 Jahren

AuthZ ist Logik: hat im DAL also nichts zu suchen.

Der AuthorizationHandler müsste also selber die MobileDevice-Entity laden und prüfen, ob dort die PersonID mit dem aktuellen UserContext übereinstimmt.

Auch das ist ja Logik.