Clean architecture i Identity

Clean architecture i Identity
RJ
  • Rejestracja:prawie 3 lata
  • Ostatnio:około godziny
  • Postów:436
1

Cześć.
Chciałbym napisać od zera swój pierwszy wielki fullstackowy projekt i chciałbym wykorzystać clean architecture, a jednocześnie trzymać sobie encje usera w bazie.

Niestety, chcac dziedziczyć w Core (AppUser: IdentityUser) wprowadzam dependency na pakiecie Identity od MS - co jest wbrew założeniom architektury.

Ewentualnie jak odnieść się do encji user który może mieć n czegoś tam.

Jak podchodzicie do tego problemu? Chętnie posłucham rady kogoś bardziej doświadczonego.

edytowany 2x, ostatnio: rjakubowski
SZ
  • Rejestracja:prawie 11 lat
  • Ostatnio:około godziny
  • Postów:1513
1

Korzystacie z Identity?

Możesz korzystać z identity i nie dziedziczyć z Identityuser

edytowany 1x, ostatnio: szydlak
SO
  • Rejestracja:ponad 10 lat
  • Ostatnio:około rok
2

Ja bym w Core zrobił sobie jakąś reprezentację usera, która jest całkowicie niezależna od ASP.NET Core Identity (bo domeną mojej aplikacji raczej nie jest zarządzanie hasłami użytkownika, czy tam opcjami MFA, więc domena może zupełnie o tym nie wiedzieć ;)).
Powiązanie pomiędzy encją w Core, a obiektem IdentityUser z ASP.NET Core Identity można zrobić luźno na podstawie Id/Guid.

Do Core wstrzykuję jakiś IUserContext mający w sobie identyfikator użytkownika (albo jakiś worek z propertisami jak potrzebuję czegoś więcej) i później w zależności w jakim kontekście operuję w Core, pobieram na podstawie tego identyfikatora odpowiednią encję biznesowo reprezentującą użytkownika.
UserContext wypełniany jest danymi pochodzącymi czy to z jakiejś sesji czy z JWT, w zależności czego tam akurat fizycznie używam do uwierzytelnienia, ale dzieje się to poza Core, bo nie jest to domena mojej aplikacji (ja często to robiłem po prostu w warstwie webowej, bo tam obsługiwałem sesje/JWT, ale nie wiem czy jest to zgodnie z czystą architekturą :]).

A samo zarządzanie użytkownikami też lubię wynieść do zewnętrznej usługi :) Jakieś Azure AD, Azure AD B2C, Auth0, czy IdentityServer, w zależności od przypadku.

Z czystym ASP.NET Core Identity ostatnio do czynienia miałem kilka lat temu, ale do obsługi logowania/rejestracji pewnie zrobiłbym sobie jakiś oddzielny moduł Auth poza Core.

Zobacz pozostałe 3 komentarze
KA
Można z tym dyskutować, bo Core.User może być skomponowany z kilku encji, niektóre z nich mozemy chcieć ukryć i wtedy faktycznie trzeba porobić metody publiczne które to obsługują. Ale uprawnienia nie należą raczej do encji ktore sie ukrywa wewnatrz usera.
SO
nie rozumiem po co jakieś operowanie czymkolwiek w core, Od weryfikacji czy user ma prawo cos zrobic jest serwis, nie core. Bo wtedy wciągane są zależności. trochę wchodzimy w dyskusję co autor rozumie przez Core. Ja widziałem i implementacje gdzie Core to była warstwa Application + Domain jak i implementacje gdzie Application i Domain to oddzielne warstwy (to chyba bardziej zgodne z CA). To co miałem na myśli to, że w bardziej skomplikowanych przypadkach w zależności od kontekstu biznesowego mogę mieć różne rozumienie czym jest ten User i mieć różne jego modele.
somekind
Od weryfikacji czy user ma prawo cos zrobic jest serwis, nie core. Bo wtedy wciągane są zależności. - naturalnie. Ale jeśli za core uznajemy tak jak ja domenę, to tam są głównie metody.
KA
@some_ONE Bardzo słuszna uwaga. Szkoda, że nie ma w tych kwestiach ustandaryzowanej nomenklatury opisanej w jakiejś uniwersalnej (tj. dotyczącej różnych języków, środowisk itp) książce czy encyklopedii. Czasami programiści Java widzą to i nazywają po swojemu, w .NET po swojemu, a w Androidzie to już w ogóle sieczka jest jeżeli chodzi o terminologię.
somekind
No, i książka kosztuje 8000zł, i do tego certyfikat państwowy z jej znajomości. Jak u porządnych fachowców. ;)
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Koszalin
  • Postów:10094
0
rjakubowski napisał(a):

Cześć.
Chciałbym napisać od zera swój pierwszy wielki fullstackowy projekt i chciałbym wykorzystać clean architecture, a jednocześnie trzymać sobie encje usera w bazie.

Niestety, chcac dziedziczyć w Core (AppUser: IdentityUser) wprowadzam dependency na pakiecie Identity od MS - co jest wbrew założeniom architektury.

Ewentualnie jak odnieść się do encji user który może mieć n czegoś tam.

Jak podchodzicie do tego problemu? Chętnie posłucham rady kogoś bardziej doświadczonego.

Obejrzyj:

Bez wiedzy o elementach zawartych w tych filmach nawet nie masz co marzyć o "clean architecture".

KA
  • Rejestracja:około 8 lat
  • Ostatnio:około 9 godzin
  • Postów:36
0

Musisz zrobić sobie interfejs np. IIdentityService, który będzie zależnością Twojego Core.User.

Później robisz implementację, np. AspNetCoreIdentityService i ta implementacja zależy od biblioteki MS.

Edit po dyskusji z @Riddle

Klasa Core.User nie wie nic o autentykacji, autoryzacji i nie odpowiada za to.

Autentykacja, autoryzacja powinny być w warstwie aplikacji.

Musi tak być, poza tym jeżeli planujesz w aplikacji jakieś role/uprawnienia np. UserPrivilege użytkowników to User byłby od nich zależny od nich "w bok", a to nie jest zgodne z założeniami clean architecture.

edytowany 3x, ostatnio: Kamil A
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Koszalin
  • Postów:10094
0
Kamil A napisał(a):

Musisz zrobić sobie interfejs np. IIdentityService, który będzie zależnością Twojego Core.User.

Później robisz implementację, np. AspNetCoreIdentityService i ta implementacja zależy od biblioteki MS.

No takie 3/10 rozwiązanie powiedziałbym.

Co z tego że to jest interfejs, jak i tak user musi wiedzieć że to jest identity service? Równie dobrze mógłbyś przekazać klasę service i na to samo by wyszło.

KA
  • Rejestracja:około 8 lat
  • Ostatnio:około 9 godzin
  • Postów:36
0

Nie mógł bym, bo wciągnął bym w ten sposób zależność. Interfejs nie ma zależności. Na tym właśnie to polega. Jest elementem odprzęgającym.

Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Koszalin
  • Postów:10094
0
Kamil A napisał(a):

Nie mógł bym, bo wciągnął bym w ten sposób zależność. Interfejs nie ma zależności. Na tym właśnie to polega. Jest elementem odprzęgającym.

Przekazujac interfejs IIdentityService również wciągasz.

Jestem za tym, żeby oddzielić jakoś AspNetCoreIdentityService od Core.User, ale na pewno interfejs IIdentityService to nie jest krok w dobrą stronę. Z punktu widzenia dependency inversion, to taki interfejs nie jest żadnym usprawnieniem.

edytowany 2x, ostatnio: Riddle
KA
  • Rejestracja:około 8 lat
  • Ostatnio:około 9 godzin
  • Postów:36
0
Riddle napisał(a):

Przekazujac interfejs IIdentityService również wciągasz.

Nie wciągam:

Kopiuj
namespace Blabla.Common.Interfaces;
public interface IIdentityService
{
    string GetUserName(string userId);
    bool HasRole(string userId, string role);
    bool Authorize(string userId, string policyName);
    bool CreateUser(string userName, string password);
    bool DeleteUser(string userId);
    // itd itp
}
edytowany 1x, ostatnio: Kamil A
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Koszalin
  • Postów:10094
0
Kamil A napisał(a):
Riddle napisał(a):

Przekazujac interfejs IIdentityService również wciągasz.

Nie wciągam:

Kopiuj
namespace Blabla.Common.Interfaces;

public interface IIdentityService
{
    string GetUserName(string userId);
    bool HasRole(string userId, string role);
    bool Authorize(string userId, string policyName);
    bool CreateUser(string userName, string password);
    bool DeleteUser(string userId);
    // itd itp
}

No tak, i ten interfejs wcale nie przenika szczegółów do User.Core.

Widzę że nie za bardzo rozumiesz co mam na myśli, więc może skończmy temat. Prezentujesz postawę "jeśli tylko wydzielę interfejs, to te dwie rzeczy są odseparowane", to wymagałoby pewnie paru godzin debaty żeby zaprezentować przykłady czemu to nie zawsze jest prawda. Także z mojej strony EOT.

edytowany 1x, ostatnio: Riddle
KA
Wg. mnie inaczej się nie da. Uważam, że to jest właśnie clean architecture. A jak masz lepszy pomysł to zaproponuj.
KA
  • Rejestracja:około 8 lat
  • Ostatnio:około 9 godzin
  • Postów:36
0
Riddle napisał(a):

No tak, i ten interfejs wcale nie przenika szczegółów do User.Core.

Zaraz zaraz, ja wcale nie napisałem, że ten interfejs należy wpychać do Core.User. Uwierzytelnianie, sprawdzanie jakie user ma uprawnienia itp. powinny być w warstwie aplikacji i to warstwa aplikacji ma działać na tym interfejsie. Zaraz to dopiszę w poście wyżej.

edytowany 1x, ostatnio: Kamil A
WeiXiao
  • Rejestracja:około 9 lat
  • Ostatnio:około 5 godzin
  • Postów:5144
0

Kiedyś gdzieś się spotkałem z rozdzielaniem User oraz Account

W tym podejściu User to jest ta twoja czysta, nieskalana klasa,

a gdzieś tam było Account które miało te gupotki techniczne do obsługi logowania.

Nie mam pojęcia jak to się sprawdziło w praktyce, ale może komuś się przyda.

edytowany 2x, ostatnio: WeiXiao
KA
Ja mam w jednym systemie reprezentację usera pociętą chyba na 7 części, ale podstawowy mail i hash hasła i takie tam są wewnątrz głównej klasy usera. W niektórych ORM chyba jest szybciej porobić joiny gdzie trzeba niż pisać zapytania typu "select imie, nazwisko, bla, blabla, blablabla" i robić z tego encje. Przynajmniej mi jest tak łatwiej w hibernate którego nie lubię, nie znam i nie chcę znać.
orchowskia
Teoretycznie jeśli mowa o mikroserwisach to każdy też może mieć jakąś tam swoją reprezentację jeśli jej potrzebuje, każdy z informacjami których potrzebuje, zduplikowane żeby podjąć odpowiednie dla siebie decyzje. Więc tych reprezentacji może być duużo. ad komentarz @Kamil A - @WeiXiao miał chyba na myśli coś innego niż joiny z różnych tabelek. :)
RJ
  • Rejestracja:prawie 3 lata
  • Ostatnio:około godziny
  • Postów:436
0

Podpatrzylem sobie jak MS to robi w eShopOnContainers i ApplicationUser polecial do projektu Infrastructure. Zobaczymy czy mnie to ugryzie w d*pe :)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.