﻿# Rozwiązanie zadania 5: Name mangling i maskowanie hasła
# Używamy języka angielskiego w kodzie, polskie komentarze tłumaczą zawiłości name manglingu.

class UserAccount:
    """
    Konto Użytkownika z silnym zabezpieczeniem krytycznej informacji: hasła.
    Prezentuje pojęcie 'name mangling' (wykorzystanie '___') oraz maskowanie w getterze.
    To jedno z najbardziej bezpiecznych podejść do ukrywania danych w Pythonie.
    """

    def __init__(self, username, password):
        self.username = username
        
        # Dwa podkreślenia przed 'password' (__password) aktywują w Pythonie 
        # tzw. 'name mangling'. Nazwa tej zmiennej w pamięci zostanie automatycznie 
        # zmieniona na '_UserAccount__password', aby bardzo utrudnić modyfikację
        # atrybutu bezpośrednio z zewnątrz obiektu.
        self.__password = ""
        
        # Wywołujemy bezpieczny setter aby od samego początku hasło przeszło walidację!
        self.password = password

    @property
    def password(self):
        """
        Getter hasła. Maskuje treść powrotną. 
        Kiedy ktokolwiek użyje 'print(u.password)', nigdy nie zobaczy czystego tekstu.
        Czysty tekst zapisany jest w zmiennej '__password', ale tu zwracamy tylko gwiazdki.
        """
        return "********"

    @password.setter
    def password(self, new_password):
        """
        Setter wprowadzający rygor i walidację długości hasła.
        Ustawia nowe hasło tylko jeśli jest bezpieczne.
        """
        if len(new_password) >= 8:
            self.__password = new_password
        else:
            print("Error: Password too short! (min 8 characters)")

# Blok testowy
if __name__ == '__main__':
    print("--- Próba utworzenia konta ze zbyt krótkim hasłem ---")
    u1 = UserAccount("admin", "tajne") # Poniżej 8 znaków
    
    print("\n--- Poprawienie hasła (powyżej 8 znaków) ---")
    u1.password = "bardzotajnehaslo"
    
    print("\n--- Odczyt hasła ---")
    # Zostanie wyświetlone '********', a nie 'bardzotajnehaslo'
    print(f"Maskowane hasło zwracane przez właściwość: {u1.password}")
    
    print("\n--- Próba bezpośredniego odczytu zmiennej z zewnątrz (__password) ---")
    try:
        print(u1.__password)
    except AttributeError as e:
        print("Błąd przechwycony! Python wygenerował AttributeError:")
        print(e)
        print("Wyjaśnienie: Z powodu podwójnego podkreślenia, Python zmienił "
              "wewnętrzną nazwę atrybutu z '__password' na '_UserAccount__password' "
              "(to jest właśnie name mangling).")

    print("\n--- Dowód: Jak w Pythonie obejść zabezpieczenie (odradzane) ---")
    # Jeśli bardzo byśmy chcieli się do niego dostać, znając mechanikę języka:
    # używamy '_[NazwaKlasy]__[NazwaAtrybutu]'
    print(f"Hasło wyciągnięte dzięki znajomości Name Manglingu: {u1._UserAccount__password}")
