System logowania z podzałem na role

2

Witam serdecznie wszystkich.

Chciał bym się poradzić o poradę ludzi którzy mają jakieś doświadczenie w tego typie projektów. Załóżmy że tworzę aplikację do której się loguje i jest podział na role typu Admin , user itp. Oczywiście Admin ma więcej funkcji niż taki user. Żeby zrobić taki podział to używać takich konstrukcji jak:

//Szukanie użytkownika w bazie danych i pobranie jego danych do zmiennych
if(role=="Admin")
{
 //Wyświetlenie panelu dla Admina
}
else if(role=="User")
{
 //Wyświetlanie panelu dla User
}

I robić dwa oddzielnie panele z danymi funkcjami dla Usera i Admina ?

Pytanie jest tylko teoretyczne i dla rozwiania moich wątpliwości w tej kwestii.

Dziękuję z góry za wszelkie odpowiedzi.

0

A czy funkcje admina i użytkownika będą totalnie inne, czy czescuowo się pokrywać?

Poza tym raczej bym poszedł w stronę napisania jednego mechanizmu obsługi panelu i jedynie bym do niego wstrzykiwał różna zawartość.

Dales za mało konkretów żeby jakiś sensownie odpowiedzieć, więc rady są bardzo ogólne.

0

Załóżmy że funkcje admina i użytkownika będą się pokrywać ale też ciekawi mnie jak by wyglądała wersja gdyby były całkiem inne.

Czyli stworzyć jeden panel i potem na podstawie if wyświetlać odpowiednie funkcje dla danej roli ?

3

Tak teoretycznie, to nie da się odpowiedzieć na podstawie danych, które podałeś. Szczególnie w tym dziale będzie to trudne, bo zakładam, że chodzi o jakąś aplikację desktopową.
Zakładając, że faktycznie chcesz mieć autoryzację opartą na rolach (google RBAC), to trzeba sobie jeszcze odpowiedzieć na takie pytania ile tych ról będzie, czy bądą one jedynie wbudowane w aplikację, czy administrator będzie mógł tworzyć własne.
Tak czy inaczej, to czy użytkownikowi wyświetlić ten panel, czy inny jest drobnym szczegółem, który już zakłada błąd. To jedynie UI. Załóżmy, że robisz sobie menu, które wyświetla się tylko administratorowi i masz tam pozycję "wyczyść bazę danych". Chwilę później, ktoś stwierdza, że ten przycisk powinien być też dosępny w innym miejscu, doda go na jakiejś formatce, zapomni dodać warunki autoryzacji i wziu...

Czyli pierwsze zastrzeżenie - niezależnie od tego co i jak pokażesz użytkownikowi, samo sprawdzenie uprawnień powinno następować w funkcji odpowiedzialnej za wykonanie jakiejś tam czynności.
To oznacza, że logika tej funkcji nie powinna byc w tym samym kawałku kodu, co rysowanie UI.

Natomiast ze względów czysto estetycznych / UX faktycznie nie warto wyświetlać użytkownikowi pozycji dla niego niedostępnych i tutaj to już jak kto chce i jak wygodniej. Najprościej zrobić gdzieś tam dodatkowy panel, który zawiera te krytyczne funkcje aplikacji i jest widziany jedynie przez administratora.

2

Załóżmy że funkcje admina i użytkownika będą się pokrywać ale też ciekawi mnie jak by wyglądała wersja gdyby były całkiem inne.
Czyli stworzyć jeden panel i potem na podstawie if wyświetlać odpowiednie funkcje dla danej roli ?

Ogólnie to i tak bym podszedł do tego w ten sposób, żeby nie kodować tego na pałę, tylko stworzyć jakiś mechanizm/silnik do wyświetlania i obsługi panelu, a potem do niego przekazywać, jakie elementy mają być wyświetlone oraz co ma się dziać po ich wybraniu.

A już mając to można wybrać wariant: czy stworzyć 2 osobne panele (bazujące na tym samym szablonie) czy jeden, w którym warunkowo będą pokazywane lub ukrywane poszczególne elementy.

Ale nie jestem w stanie doradzić nic więcej mając tyle informacji, ile przekazałeś. To jest bardzo ogólne pytanie i tak samo ogólna odpowiedź.

0
pestka12 napisał(a):

I robić dwa oddzielnie panele z danymi funkcjami dla Usera i Admina ?

Użycie switcha w takiej konstrukcji rozwiąże większość twoich problemów - o ile będziesz ostrożny i wiedział gdzie należy postawić break.

0

Cześć @pestka12!

Kiedy mówisz "użytkownik" i "administrator", masz na myśli użytkownika i administratora Twojej aplikacji? Czy chodzi o systemowego administratora komputera na którym uruchomiona jest aplikacja? 🤔

2

Pomijając już jak role się nazywają. Mechanizm z systemem uprawnień. Dana rola(a może użytkownik?) ma dane uprawnienia. Na "frontach" za pomocą mechanizmu określam co mogę mu wyświetlić. User posiada dane uprawnienie, wyświetl mu przycisk, pozwól na coś. Pisanie na pałę if (coś tam) jest podejściem szybkim, które w przyszłości się zemści.
Przykład. Masz dodać nową rolę, która będzie widziała część elementów Admina. Musisz przejrzeć całą apkę i modyfikować ify, zamiast stworzyć odpowiednią rolę i podpiąć jej odpowiednie uprawnienia. Na frontach nic się nie zmienia, a masz nową rolę w systemie. Ba, w przyszłosci to możesz rozbudować na dynamiczne zarządzanie uprawnieniami per user, a dzięki systemowi uprawnień, nie będziesz musiał modyfikować frontów. To jest koncepcja, która działa bez względu na język(pewnie są jakieś skrajne przypadki jak asm(chyba))

Co do tego czy mają mieć wspólne "fronty" czy osobne apki. To zależy. Zależy od kontekstu i rozbudowania(zabezpieczeń). U mnie w projektach użytkownicy(są to randomowi ludzie z ulicy, którzy korzystają z apki). Mają własne fronty i tam już mamy podział na role). Zaś "admin" ma swoje fronty i tam znów mamy różne typy kont, w zależności co dany user może zrobić, a czego nie.

0
cerrato napisał(a):

Załóżmy że funkcje admina i użytkownika będą się pokrywać ale też ciekawi mnie jak by wyglądała wersja gdyby były całkiem inne.
Czyli stworzyć jeden panel i potem na podstawie if wyświetlać odpowiednie funkcje dla danej roli ?

Ogólnie to i tak bym podszedł do tego w ten sposób, żeby nie kodować tego na pałę, tylko stworzyć jakiś mechanizm/silnik do wyświetlania i obsługi panelu, a potem do niego przekazywać, jakie elementy mają być wyświetlone oraz co ma się dziać po ich wybraniu.

A już mając to można wybrać wariant: czy stworzyć 2 osobne panele (bazujące na tym samym szablonie) czy jeden, w którym warunkowo będą pokazywane lub ukrywane poszczególne elementy.

Ale nie jestem w stanie doradzić nic więcej mając tyle informacji, ile przekazałeś. To jest bardzo ogólne pytanie i tak samo ogólna odpowiedź.

Oczywiście ja tylko uwzględniam jakiś mechanizm / silnik który ułatwi pracę a nie pisać głupią logikę typu jeśli rola jest równa admin to generuj te kontrolki. Myślałem żeby wykorzystać tu dziedziczenie czyli mam klasę User a potem po niej dziedziczy Admin bo w końcu Admin to również użytkownik tylko z większymi prawami.

Pytanie się w ogóle zrodziło się z tego bo ostatnio tworzyłem projekt i wymagali go w C# i tam takie rzeczy jak podział na role itp było praktycznie gotowymi szablonami. A że głównie siedzę w C++ to jestem ciekaw jak tu wykonywać takie zadania na chociaż w miarę okej poziomie.

0
pestka12 napisał(a):
cerrato napisał(a):

dzić nic więcej mając tyle informacji, ile przekazałeś. To jest bardzo ogólne pytanie i tak samo ogólna odpowiedź.

Oczywiście ja tylko uwzględniam jakiś mechanizm / silnik który ułatwi pracę a nie pisać głupią logikę typu jeśli rola jest równa admin to generuj te kontrolki. Myślałem żeby wykorzystać tu dziedziczenie czyli mam klasę User a potem po niej dziedziczy Admin bo w końcu Admin to również użytkownik tylko z większymi prawami.

dziedziczenie ale nie takie
Panel
PanelUser : public Panel
PanelAdmin : public Panel

0

Mi chodziło o coś takiego w kwestii dziedziczenia. Przykład napisany w C++ WxWidget:

class AdminPanel : public wxFrame {
public:
    AdminPanel() : wxFrame(nullptr, wxID_ANY, "Admin Panel") {
        wxPanel* panel = new wxPanel(this);
        wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);

        sizer->Add(new wxStaticText(panel, wxID_ANY, "Welcome to Admin Panel"), 0, wxALL | wxCENTER, 10);
        panel->SetSizer(sizer);
    }
};

class UserPanel : public wxFrame {
public:
    UserPanel() : wxFrame(nullptr, wxID_ANY, "User  Panel") {
        wxPanel* panel = new wxPanel(this);
        wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);

        sizer->Add(new wxStaticText(panel, wxID_ANY, "Welcome to User Panel"), 0, wxALL | wxCENTER, 10);
        panel->SetSizer(sizer);
    }
};

I potem na podstawie danych z bazy wybieram odpowiednią ramkę która ma się wyświetlić. Czy idę myślą w dobrą stronę czy są jakieś lepsze sposoby na stworzenie tego systemu ?

0

Witam serdecznie wszystkich.

W ostatnim tygodniu długo szukałem ciekawego rozwiązania problemu, lecz ostatnio czytałem książkę o Wzorcach projektowych w C++ i do mojego problemu pasują nie które wzorce takie jak:

  1. Fabryka
  2. Strategia
  3. Odwiedzający

Myślicie że jest to dobra droga , a jak tak to który według was wzorzec będzie najlepszy. Zaimplementowałem Wzorzec strategia do takiego systemu logowania i wygląda według mnie w porządku.

2

NIE, nie szukaj na siłę wzorców tylko pomyśl samemu jak zrobić

2

Skoro na siłę starasz się dopasować któryś ze wzorców, o których gdzieś przeczytałeś, znaczy że wcale te wzorce nie są tutaj potrzebne. Ja wiem, że na początku, jak poznajesz cos nowego, to starasz się wszędzie korzystać z tej nowości, to jest normalne i chyba każdy przez to przechodził. Ale posłuchaj porady - jeśli musisz się zastanawiać, co tutaj wsadzić, znaczy że żadna z tych rzeczy nie jest dobrze pasująca. To trochę jakbyś poszedł na kurs obsługi młotka i po powrocie do domu szukał na siłę miejsc, gdzie można z młotka skorzystać: można nim ugniatać ziemniaki, zagarniać brud z podłogi, można ubijać ziemię w doniczce z kwiatkiem. Niby można, ale to takie siłowe i bez większego sensu. Zostaw młotek w szafce i skorzystaj z niego, kiedy serio poczujesz, że jest taka potrzeba, gdy pojawi się sytuacja, w której serio młotka się używa - typu wbicie gwoździa.

screenshot-20241103144523.png

1

@cerrato: Nie szukam na siłę wzorców które można tu zastosować. To było pytanie czy jest to dobry kierunek. Jeśli opinia bardziej doświadczonych ludzi mówi że nie warto lub jest to zły kierunek to nie będę udowadniał na siłę że jest inaczej.Chcę w życiu starać się pisać profesjonalny kod i stosować dobre praktyki (lecz czasami mnie to gubi 😅 ) . To może jakieś nakierowanie na jakiś temat lub nawet jakiś prosty przykład. Ostatnio przeszukiwałem internet i strony takie jak stack , medium i albo nie umiem szukać , albo nie ma takich artykułów , postów.

Jeśli do udzielenia odpowiedzi potrzeba więcej informacji to chętnie udzielę wszystkie potrzebne dane itp.

0
pestka12 napisał(a):

Mi chodziło o coś takiego w kwestii dziedziczenia. Przykład napisany w C++ WxWidget:

class AdminPanel : public wxFrame {
public:
    AdminPanel() : wxFrame(nullptr, wxID_ANY, "Admin Panel") {
        wxPanel* panel = new wxPanel(this);
        wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);

        sizer->Add(new wxStaticText(panel, wxID_ANY, "Welcome to Admin Panel"), 0, wxALL | wxCENTER, 10);
        panel->SetSizer(sizer);
    }
};

class UserPanel : public wxFrame {
public:
    UserPanel() : wxFrame(nullptr, wxID_ANY, "User  Panel") {
        wxPanel* panel = new wxPanel(this);
        wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);

        sizer->Add(new wxStaticText(panel, wxID_ANY, "Welcome to User Panel"), 0, wxALL | wxCENTER, 10);
        panel->SetSizer(sizer);
    }
};

I potem na podstawie danych z bazy wybieram odpowiednią ramkę która ma się wyświetlić. Czy idę myślą w dobrą stronę czy są jakieś lepsze sposoby na stworzenie tego systemu ?

Ale właściwie jakimi składowymi różnią się te panele? bo że się różnią tekstem wyświetlanym to wiemy ale czym jeszcze?

0
pestka12 napisał(a):

Mi chodziło o coś takiego w kwestii dziedziczenia. Przykład napisany w C++ WxWidget:

class AdminPanel : public wxFrame {
public:
    AdminPanel() : wxFrame(nullptr, wxID_ANY, "Admin Panel") {
        wxPanel* panel = new wxPanel(this);
        wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);

        sizer->Add(new wxStaticText(panel, wxID_ANY, "Welcome to Admin Panel"), 0, wxALL | wxCENTER, 10);
        panel->SetSizer(sizer);
    }
};

class UserPanel : public wxFrame {
public:
    UserPanel() : wxFrame(nullptr, wxID_ANY, "User  Panel") {
        wxPanel* panel = new wxPanel(this);
        wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);

        sizer->Add(new wxStaticText(panel, wxID_ANY, "Welcome to User Panel"), 0, wxALL | wxCENTER, 10);
        panel->SetSizer(sizer);
    }
};

I potem na podstawie danych z bazy wybieram odpowiednią ramkę która ma się wyświetlić. Czy idę myślą w dobrą stronę czy są jakieś lepsze sposoby na stworzenie tego systemu ?

Ale właściwie jakimi składowymi różnią się te panele? bo że się różnią tekstem wyświetlanym to wiemy ale czym jeszcze?

0

@Miang: To był taki przykład. Mi chodzi o taki podział ról i wyświetlanie interfejsu jak jest np w programach magazynowych gdzie zwykły magazynier może wykonywać podstawowe czynności natomiast główny magazynier ma wyższe uprawnienia i na pewno ma inny interfejs bo dochodzą mu np przyciski którymi może generować raport gdzie zwykły magazynier po prostu tych przycisków nie widzi w interfejsie z powodu swojej roli. W skrócie chodzi mi o zasadę RBAC i podział różnych interfejsów na każdą rolę.

2

@pestka12: No bo podałeś przykład gdzie sama definicja klasy byłaby jedna ,tylko z różnymi wartościami pola przechowującego tekst dla nagłówka
jeżeli panel dla admin będzie miał też dodatkowe przyciski no to właśnie dziedziczenie z klasy Panel i rozbudowanie jej o dodatkowe elementy
Może też być że jakiś podpanel jest umieszczony na tym panelu lub nie w zależności od usera
btw. po naciśnięciu przycisku jeszcze raz powinno być sprawdzone czy ten user miał prawo widzieć ten przycisk i wykonać daną czynność

1

@pestka12 Skupiasz się na pierdołach. Jesteś początkujący (wnioskuję po pytaniach), skup się na tym, żeby zrobić zadanie, które sobie wymyśliłeś, nie na tym jakie wzorce projektowe do tego zastosować.
Odseparuj logikę od UI, sprawdzaj rolę na poziomie logiki. Jeżeli masz gdzieś metodę deleteUser(userId: int) to wewnątrz tej metody masz sprawdzić, czy aktualny użytkownik ma przypisaną rolę administratora. Możesz sobie zrobić wrapper na logikę i na tym poziomie sprawdzać rolę, albo dodać parametr z rolą, czy całym obiektem użytkownika.
Jeżeli UI, które widzi zwykły użytkownik ma być inne od UI widzianego przez administratora, to rób 2 panele, mogą dziedziczyć po wspólnym rodzicu (i to raczej implementować wspólny interface, niż faktycznie korzystać z dziedziczenia). Z typowego dziedziczenia rzadko kiedy wynika coś dobrego, a w przypadku UI, to już chyba wcale.

Jak już chcesz zastosować jakieś wzorce, to możesz zapakować sobie pokazywanie tych paneli w jakąś metodę fabrykującą, która ci zwróci odpowiednią wersję UI w zależności od tego jaka jest rola użytkownika.

1
piotrpo napisał(a):

Odseparuj logikę od UI, sprawdzaj rolę na poziomie logiki. Jeżeli masz gdzieś metodę deleteUser(userId: int) to wewnątrz tej metody masz sprawdzić, czy aktualny użytkownik ma przypisaną rolę administratora. Możesz sobie zrobić wrapper na logikę i na tym poziomie sprawdzać rolę, albo dodać parametr z rolą, czy całym obiektem użytkownika.

wywołać funkcję , która sprawdzi czy zalogowany użyszkodnik może wykonać akcję 'delete_user'
nie zapisywać w metodzie deleteUser kto ma prawo zrobić delete (że 'admin') bo to się może zmienić

0

@piotrpo: Dziękuje za wiele cennych rad. Jestem studentem 3 roku informatyki ekonomicznej i jako student studiując dziennie ciężko mi się załapać do jakieś firmy więc na razie moje doświadczenie wynosi 0 ale nadrabiam to rozwijać swoją pasję prywatnie i ciągle czytając różne artykuły i książki (Głowna tematyka to C++ i Assembler i czasami jakaś pozycja o javie). Liczę że jak obronię magisterkę to uda mi się gdzieś załapać i rozwijać się dalej w swojej pasji.

Pozdrawiam serdecznie.

0
piotrpo napisał(a):

Jeżeli masz gdzieś metodę deleteUser(userId: int) to wewnątrz tej metody masz sprawdzić, czy aktualny użytkownik ma przypisaną rolę administratora.

Jezeli uzytkownik nie ma przypisanych jakichkolwiek przywilejow do wykonywania wybranej akcji, to do tej akcji (lub jak wolisz metody), nie ma prawa nawet sie zblizyc, tymbardziej (zakladajac, ze tworzysz SOLIDny kod) wykonywac w niej dodatkowo autoryzacje.

1

@pestka12 Zamiast stosować wzorce na siłę pomyśl o tym jak podzielić program na pojedyncze odpowiedzialności, w co je zapakować, jak tworzyć te obiekty i jak je poskładać do kupy. Odpowiedzialności jakie ja tutaj widzę:

  • uwierzytelnianie (określenie tożsamości użytkownika) logika + UI
  • autoryzacja (Określenie uprawnień użytkownika o znanej tożsamości)
  • kontrola dostępu (sprawienie, że użytkownik bez odpowiedniej roli nie wywoła funkcji, której wywoływać mu nie wolno
  • logika biznesowa, czyli realizacja funkcji wywoływanych przez użytkowników, lub innych aktorów
  • wyświetlanie UI administratora
  • wyświetlanie UI użytkownika

I w tym miejscu można zacząć myśleć o tym jak to składać do kupy. Pewnie za każdą z tych linijek powinna odpowiadać osobna klasa. Kontrola dostępu może być wrapperem na logikę biznesową. Panele user/admin mogą być zwracane przez jakąś metodę fabrykującą.

0

Dziękuję bardzo wszystkim za cenne rady oraz informacje. Według mnie temat jest do zamknięcia i może przyda się przyszłym pokoleniom 😁

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.