[{"content":"Dlaczego? Od bardzo dawna fascynuje mnie kultura Japonii. Jedną z rzeczy, które zawsze zwracały moją uwagę, jest długowieczność i ogólnie dobry stan zdrowia Japończyków.\nCiekawym elementem japońskiej kultury jest to, że ludzie spędzają dużo czasu, siedząc na podłodze. Większość z was zapewne widziała w japońskich filmach sceny, w których ludzie siedzą na podłodze wokół niskiego stołu.\nZacząłem się zastanawiać, czy siedzenie na podłodze może być jednym z czynników wpływających na ich zdrowie i długowieczność oraz czy mógłbym wprowadzić ten zwyczaj do własnego życia.\nZa każdym razem, gdy siadasz na podłodze i z niej wstajesz, twoje ciało musi wykonać określony ruch. W pewnym sensie przypomina to zrobienie przysiadu, a przysiady są bardzo korzystne dla ciała. Ponadto siedzenie w pozycji podobnej do medytacyjnej zachęca nas do utrzymywania lepszej postawy.\nPonieważ od dawna praktykowałem medytację i miałem już poduszkę do medytacji, postanowiłem przeprowadzić eksperyment: zastąpiłem nią krzesło biurowe, którego używałem do pracy.\nZmodyfikowałem biurko tak, by jego wysokość nadawała się do pracy na siedząco na podłodze, i rozpocząłem eksperyment.\nPierwszy miesiąc Pierwszy miesiąc był znacznie trudniejszy, niż się spodziewałem. Już po kilku dniach byłem bliski rezygnacji. Bolały mnie kolana i plecy, a mimo doświadczenia w medytacji nie czułem się komfortowo, siedząc na podłodze przez tak długi czas.\nSzybko stało się jasne, że siedzenie na podłodze przez osiem godzin dziennie to coś zupełnie innego niż trzydziestominutowa medytacja.\nMimo początkowych trudności postanowiłem kontynuować eksperyment i dać organizmowi wystarczająco dużo czasu na przystosowanie się.\nPo pierwszym miesiącu ból kolan i pleców zniknął, a ja zacząłem czuć się znacznie wygodniej. Zauważyłem również niewielką poprawę postawy.\nDwa lata później nadal pracuję na podłodze Od rozpoczęcia tego eksperymentu minęły już dwa lata i nie zamierzam wracać do siedzenia na krześle biurowym. Czuję się znacznie lepiej niż wcześniej, moja postawa wyraźnie się poprawiła i nie potrafię już sobie wyobrazić spędzania wielu godzin na wygodnym krześle biurowym — które, o ironio, wcale nie wydaje mi się już wygodne.\nOdkryłem również, że siedzenie na podłodze pozwala przyjmować wiele różnych pozycji, co także może mieć pozytywny wpływ na ciało. Spędzanie całego dnia w jednej pozycji jest bardzo niezdrowe.\nPomocna może być tutaj joga. Wiele asan da się dostosować do siedzenia i pracy przy komputerze, dzięki czemu możemy regularnie zmieniać pozycję, w której pracujemy.\nCo sądzisz o takim miejscu pracy? Czy rozważyłbyś zastąpienie krzesła stanowiskiem na podłodze? A może masz własny nietypowy sposób pracy przy komputerze, dzięki któremu czujesz się wygodniej albo pozostajesz w ruchu?\nArtykuł pierwotnie opublikowany po angielsku na CoderLegion.\n","permalink":"https://spaceshaman.github.io/pl/posts/why-i-replaced-my-chair-with-a-meditation-cushion/","summary":"\u003ch2 id=\"dlaczego\"\u003eDlaczego?\u003c/h2\u003e\n\u003cp\u003eOd bardzo dawna fascynuje mnie kultura Japonii. Jedną z rzeczy, które zawsze zwracały moją uwagę, jest długowieczność i ogólnie dobry stan zdrowia Japończyków.\u003c/p\u003e\n\u003cp\u003eCiekawym elementem japońskiej kultury jest to, że ludzie spędzają dużo czasu, siedząc na podłodze. Większość z was zapewne widziała w japońskich filmach sceny, w których ludzie siedzą na podłodze wokół niskiego stołu.\u003c/p\u003e\n\u003cp\u003eZacząłem się zastanawiać, czy siedzenie na podłodze może być jednym z czynników wpływających na ich zdrowie i długowieczność oraz czy mógłbym wprowadzić ten zwyczaj do własnego życia.\u003c/p\u003e","title":"Dlaczego zastąpiłem krzesło poduszką do medytacji"},{"content":"Zarządzanie użytkownikami jest jednym z tych problemów, które rzadko wydają się na tyle trudne, by poświęcać im wiele uwagi.\nDopóki nie zaimplementujesz go po raz piąty.\nRejestracja, logowanie, sesje, weryfikacja adresu e-mail, resetowanie i zmiana hasła, usuwanie konta, role, uprawnienia — żadna z tych funkcji nie jest szczególnie nietypowa. Niemal każda aplikacja potrzebuje jednak jakiejś ich kombinacji, a implementacja często staje się ściśle powiązana z frameworkiem, ORM-em lub infrastrukturą, których akurat użyto w projekcie.\nWłaśnie ten problem skłonił mnie do zbudowania UserHarbor.\nUserHarbor to niezależna od frameworka biblioteka Pythona do zarządzania kontami użytkowników. Jej celem nie jest stworzenie kolejnego frameworka webowego ani kompletnej platformy tożsamości. Zamiast tego udostępnia niewielkie API na poziomie domeny dla typowych operacji na kontach, pozostawiając obsługę HTTP, baz danych i wysyłkę wiadomości e-mail osobnym integracjom.\nOdkąd po raz pierwszy napisałem o tym projekcie, coraz ciekawsza staje się dla mnie nie tylko sama warstwa uwierzytelniania, lecz przede wszystkim granica pomiędzy rdzeniem a jego integracjami.\nTen artykuł rozwija moje pierwotne wprowadzenie do UserHarbor i skupia się na tym, jak zmieniała się architektura wraz z rozwojem projektu.\nProblem, który chciałem rozwiązać Wyobraźmy sobie budowę dwóch aplikacji.\nPierwsza korzysta z:\nFastAPI SQLAlchemy PostgreSQL SMTP Druga korzysta z:\nFlaska MongoDB zewnętrznego API do wysyłania wiadomości e-mail Reguły zarządzania użytkownikami są w większości takie same.\nHasło nadal trzeba zweryfikować i zahaszować. Token weryfikacyjny nadal musi wygasnąć. Tokeny resetowania hasła nadal wymagają ochrony. Sesje trzeba tworzyć i unieważniać. Role i uprawnienia trzeba sprawdzać.\nW wielu bibliotekach reguły te są jednak wymieszane z modelami bazy danych, handlerami HTTP albo abstrakcjami właściwymi dla konkretnego frameworka.\nChciałem czegoś przeciwnego.\nRdzeń powinien wiedzieć, co powinno się wydarzyć, ale niekoniecznie w jaki sposób aplikacja przechowuje lub przesyła dane.\nProwadzi to do architektury wyglądającej mniej więcej tak:\nAplikacja / framework │ ▼ UserHarbor │ ├── UserStore │ └── baza danych / ORM / własny backend │ └── EmailSender └── SMTP / API / własny dostawca Rdzeń odpowiada za rejestrację, walidację, haszowanie haseł, generowanie i haszowanie tokenów, obsługę sesji oraz reguły autoryzacji.\nAdaptery odpowiadają za infrastrukturę.\nNiewielkie API na poziomie domeny UserHarbor obsługuje obecnie typowy cykl życia konta:\nrejestrację użytkownika weryfikację adresu e-mail logowanie sesje wylogowanie z jednej lub wszystkich sesji zmianę hasła reset hasła usunięcie konta role i uprawnienia Celowo nie udostępnia własnych endpointów HTTP.\nDzięki temu kod korzystający z rdzenia może wyglądać następująco:\nuser = harbor.register( username=\u0026#34;jane\u0026#34;, email=\u0026#34;*Emails are not allowed*\u0026#34;, password=\u0026#34;StrongPassword123!\u0026#34;, ) harbor.verify_email(verification_token) session_token = harbor.login( username=\u0026#34;jane\u0026#34;, password=\u0026#34;StrongPassword123!\u0026#34;, ) current_user = harbor.get_current_user(session_token) Tej samej instancji UserHarbor można używać w FastAPI, Flasku, Django, aplikacji CLI albo w programie, który w ogóle nie udostępnia HTTP.\nAutoryzacja działa według tej samej zasady:\nharbor.roles.create(\u0026#34;admin\u0026#34;) harbor.permissions.create(\u0026#34;users.delete\u0026#34;) harbor.roles.grant_permission( \u0026#34;admin\u0026#34;, \u0026#34;users.delete\u0026#34;, ) harbor.grant_role(\u0026#34;jane\u0026#34;, \u0026#34;admin\u0026#34;) if harbor.has_permission(session_token, \u0026#34;users.delete\u0026#34;): delete_user() Jeśli natomiast dostęp ma zostać wymuszony:\nuser = harbor.require_permission( session_token, \u0026#34;users.delete\u0026#34;, ) UserHarbor implementuje prostą kontrolę dostępu opartą na rolach, ale pozostawia politykę autoryzacji właściwą dla aplikacji poza rdzeniem. Celowo nie próbuje stać się uniwersalnym silnikiem polityk.\nNiezależność od frameworka nie oznacza nieprzyjazności wobec frameworków Chciałem uniknąć sytuacji, w której niezależność od frameworka odbywa się kosztem wygody programisty.\nDlatego istnieje między innymi oficjalna integracja userharbor-fastapi.\nZamiast ręcznie pisać trasy uwierzytelniania i zależności, aplikacja FastAPI może skonfigurować UserHarbor i dołączyć adapter:\nfrom fastapi import FastAPI from userharbor import UserHarbor from userharbor_fastapi import UserHarborFastAPI harbor = UserHarbor( secret_key=\u0026#34;your-secret-key\u0026#34;, store=store, email_sender=email_sender, ) auth = UserHarborFastAPI(harbor) app = FastAPI() app.include_router( auth.router, prefix=\u0026#34;/auth\u0026#34;, tags=[\u0026#34;auth\u0026#34;], ) Adapter dostarcza warstwę specyficzną dla frameworka: routery, schematy żądań, zależności uwierzytelniania bearer, mapowanie błędów oraz funkcje pomocnicze do wymagania określonych ról lub uprawnień.\nNajważniejsze jest to, że FastAPI nadal nie przenika do rdzenia UserHarbor.\nMożesz zmienić framework webowy bez zmiany logiki zarządzania kontami.\nTrudniejszy problem: co znaczy zaimplementować UserStore? Początkowo oddzielenie mechanizmu persystencji za interfejsem UserStore wydawało się oczywistym rozwiązaniem.\nDefiniujemy interfejs i implementujemy jego metody, dzięki czemu SQLAlchemy, MongoDB, Redis czy dowolne inne rozwiązanie może dostarczać warstwę przechowywania danych.\nIstnieje jednak subtelny problem.\nZgodność sygnatur metod nie oznacza, że dwie implementacje warstwy danych zachowują się tak samo.\nWeźmy pod uwagę token resetowania hasła.\nCzy utworzenie nowego tokenu powinno usunąć poprzedni?\nCo dzieje się po usunięciu użytkownika?\nCzy jego sesje powinny zniknąć automatycznie?\nCo powinno się stać, jeśli transakcja nie powiedzie się w połowie zmiany hasła?\nCzy próba usunięcia czegoś, co już nie istnieje, powinna zgłosić błąd?\nTe zachowania są częścią kontraktu warstwy danych, choć system typów Pythona nie potrafi ich wyrazić.\nStało się to jedną z najważniejszych zmian w UserHarbor 0.7.0.\nZamiana kontraktu adaptera w wykonywalne testy UserHarbor zawiera teraz zestaw testów kontraktowych wielokrotnego użytku dla implementacji UserStore.\nAdapter może zaimportować cały zestaw:\n# tests/test_user_store_contract.py from userharbor.testing.user_store_contract import * Musi jedynie dostarczyć czystą instancję warstwy danych:\nimport pytest @pytest.fixture def user_store(): store = create_user_store() try: yield store finally: dispose_user_store(store) Te same testy można następnie uruchamiać dla SQLAlchemy, implementacji przechowującej dane w pamięci lub zupełnie innego backendu persystencji.\nWersja 0.7.0 wprowadziła 57 testów kontraktowych wielokrotnego użytku, obejmujących użytkowników, hasze haseł, tokeny weryfikacji i resetu hasła, sesje, role, uprawnienia, relacje oraz zachowanie transakcji.\nZmienia to znaczenie adaptera.\nZgodny UserStore nie tylko deklaruje implementację interfejsu. Może wykazać, że przestrzega semantyki zachowań oczekiwanej przez rdzeń.\nKontrakt określa na przykład, że:\nnazwy użytkowników i adresy e-mail są unikalne utworzenie użytkownika i początkowego tokenu weryfikacyjnego jest atomowe nowy token weryfikacyjny zastępuje poprzedni nowy token resetowania hasła zastępuje poprzedni usunięcie użytkownika usuwa jego sesje i powiązane tokeny wielokrotne przypisanie tej samej relacji jest idempotentne usunięcie ról i uprawnień usuwa także ich przypisania pomyślne transakcje są zatwierdzane nieudane transakcje są wycofywane zagnieżdżone transakcje uczestniczą w transakcji zewnętrznej Podczas implementowania kolejnego backendu łatwo przeoczyć te szczegóły. To właśnie takie różnice mogą powodować błędy uwierzytelniania, które ujawniają się dopiero znacznie później.\nDla mnie był to ważny krok w rozwoju architektury: abstrakcję opisują teraz nie tylko protokoły Pythona i dokumentacja, lecz również wykonywalne zachowanie.\nSzablon do budowania nowych adapterów warstwy danych Aby uprościć ten proces, stworzyłem także userharbor-inmemory.\nJest to minimalna implementacja UserStore, która przechowuje dane w pamięci i przechodzi cały kontrakt warstwy danych.\nPełni dwie funkcje.\nPo pierwsze, przydaje się w testach i przykładach, które nie wymagają prawdziwej bazy danych.\nPo drugie, samo repozytorium może służyć jako szablon do tworzenia nowych integracji warstwy danych. Programista może zacząć od działającej implementacji i przechodzących testów kontraktowych, stopniowo zastępować backend in-memory, a przy tym stale sprawdzać, czy nowy adapter nadal zachowuje się poprawnie.\nChodzi o to, by tworzenie przyszłego adaptera bazy danych sprowadzało się przede wszystkim do następującego procesu:\ndziałający szablon UserStore │ ▼ zastąpienie implementacji persystencji │ ▼ uruchomienie wspólnych testów kontraktowych │ ▼ dodanie testów specyficznych dla backendu zamiast odtwarzania oczekiwanego zachowania na podstawie implementacji rdzenia.\nZachowanie związane z bezpieczeństwem pozostaje w rdzeniu Kolejną ważną granicą architektury jest to, że adaptery warstwy danych nigdy nie otrzymują surowych tokenów do zapisania.\nUserHarbor generuje surowe tokeny weryfikacyjne, resetowania hasła i sesji, ale haszuje je przed przekazaniem do UserStore.\nSurowy token trafia wyłącznie do tej części aplikacji, która go potrzebuje — na przykład do mechanizmu wysyłania e-maili albo do użytkownika po zalogowaniu.\nBaza danych przechowuje hasz.\nRdzeń odpowiada także za zachowania takie jak wygasanie tokenów i walidacja sesji.\nOperacje, które mogłyby ujawniać istnienie konta, w odpowiednich miejscach zwracają neutralne odpowiedzi. Przykładowo prośba o reset hasła dla nieznanego adresu e-mail nie zdradza, czy konto o takim adresie istnieje.\nIstnieją też powiadomienia o zdarzeniach w cyklu życia konta, takich jak:\nudana weryfikacja adresu e-mail zmiana hasła reset hasła usunięcie konta Interfejs EmailSender decyduje, w jaki sposób wiadomości zostaną dostarczone, ale nie rozstrzyga, kiedy dana operacja jest prawidłowa. Ta decyzja pozostaje w rdzeniu.\nSQLAlchemy bez przejmowania kontroli nad aplikacją Oficjalny adapter SQLAlchemy jest gotowy do użycia, lecz jednym z wymagań projektowych było to, by wdrożenie UserHarbor nie zmuszało aplikacji do przyjęcia całkowicie osobnego modelu użytkownika.\nDomyślnie adapter może zarządzać własną tabelą użytkowników.\nAplikacje, które mają już model SQLAlchemy, mogą jednak przekazać go adapterowi:\nstore = SQLAlchemyUserStore( SessionLocal, user_model=AppUser, ) Aplikacja może również mapować swój model na bogatszy publiczny obiekt użytkownika, zamiast ograniczać się do minimalnej reprezentacji UserHarbor.\nDokumentacja opisuje teraz także użycie adaptera z migracjami Alembic zamiast polegania na metadata.create_all() podczas uruchamiania aplikacji.\nTo rozróżnienie ma znaczenie: przykłady powinny być łatwe do uruchomienia, ale prawdziwe aplikacje potrzebują rozsądnego sposobu zarządzania zmianami schematu.\nInstalacja Sam rdzeń można zainstalować następująco:\npip install userharbor Można też dołączyć wybrane oficjalne integracje:\npip install \u0026#34;userharbor[sqlalchemy,smtp,fastapi]\u0026#34; Aby przetestować kompletny oficjalny zestaw:\npip install \u0026#34;userharbor[all]\u0026#34; Główne oficjalne integracje obejmują obecnie warstwę danych SQLAlchemy, wysyłkę wiadomości przez SMTP oraz obsługę FastAPI.\nCzym UserHarbor celowo nie powinien się stać Niekontrolowane rozrastanie się zakresu funkcji to łatwa pułapka w tego rodzaju projekcie.\nGdy mamy już uwierzytelnianie, kusi nas dodanie OAuth. Następnie logowania społecznościowego. Potem MFA, organizacji, zespołów, list ACL, własności zasobów, paneli administracyjnych i języka polityk.\nW końcu „mała biblioteka uwierzytelniania” staje się frameworkiem aplikacyjnym.\nWłaśnie tego staram się uniknąć.\nRdzeń powinien pozostać skoncentrowany na typowych, podstawowych operacjach zarządzania kontami.\nBardziej wyspecjalizowane funkcje mogą powstawać jako integracje lub osobne biblioteki, jeśli pojawi się na nie zapotrzebowanie. Nie powinny jednak komplikować podstawowego pakietu wszystkim jego użytkownikom.\nJedna z zasad projektowych UserHarbor jest więc celowo nudna:\nstabilność jest ważniejsza niż liczba funkcji.\nGdy publiczne API się ustabilizuje, wolę przeznaczać czas na bezpieczeństwo, niezawodność, zgodność i wydajność niż nieustannie poszerzać zakres rdzenia.\nObecny stan UserHarbor znajduje się obecnie w wersji 0.7.0.\nProjekt jest wciąż młody i nie uważam jeszcze ani jego API za stabilne, ani samej biblioteki za gotową do zastosowań produkcyjnych.\nNa tym etapie projekt służy w równym stopniu sprawdzaniu architektury, co dodawaniu funkcji.\nSzczególnie zależy mi na opinii dotyczącej:\ngranicy pomiędzy rdzeniem a integracjami kontraktu UserStore podejścia opartego na testach kontraktowych integracji z FastAPI własnych backendów warstwy danych kształtu publicznego API tego, co powinno — a co nie powinno — należeć do rdzenia W Pythonie istnieje wiele dobrych bibliotek uwierzytelniania przeznaczonych dla konkretnych frameworków.\nUserHarbor bada nieco inne pytanie:\nCzy sama domena zarządzania kontami może być wielokrotnie wykorzystywana z różnymi frameworkami i infrastrukturą, podczas gdy integracje pozostają małe, wymienne i niezależnie testowalne?\nJak dotąd uważam, że właśnie ta granica okazuje się najciekawszą częścią projektu.\nLinki Dokumentacja:\nhttps://userharbor.github.io/userharbor/\nRepozytorium:\nhttps://github.com/userharbor/userharbor\nIntegracja FastAPI:\nhttps://github.com/userharbor/userharbor-fastapi\nAdapter SQLAlchemy:\nhttps://github.com/userharbor/userharbor-sqlalchemy\nAdapter SMTP:\nhttps://github.com/userharbor/userharbor-smtp\nArtykuł pierwotnie opublikowany po angielsku na CoderLegion.\n","permalink":"https://spaceshaman.github.io/pl/posts/building-userharbor-framework-agnostic-user-management-for-python/","summary":"\u003cp\u003eZarządzanie użytkownikami jest jednym z tych problemów, które rzadko wydają się na tyle trudne, by poświęcać im wiele uwagi.\u003c/p\u003e\n\u003cp\u003eDopóki nie zaimplementujesz go po raz piąty.\u003c/p\u003e\n\u003cp\u003eRejestracja, logowanie, sesje, weryfikacja adresu e-mail, resetowanie i zmiana hasła, usuwanie konta, role, uprawnienia — żadna z tych funkcji nie jest szczególnie nietypowa. Niemal każda aplikacja potrzebuje jednak jakiejś ich kombinacji, a implementacja często staje się ściśle powiązana z frameworkiem, ORM-em lub infrastrukturą, których akurat użyto w projekcie.\u003c/p\u003e","title":"Rozwój UserHarbor: od niezależnego rdzenia do wykonywalnych kontraktów warstwy danych"},{"content":"Pracując ostatnio nad aplikacją SaaS, po raz kolejny musiałem zaimplementować ten sam zestaw funkcji związanych z kontami użytkowników:\nrejestrację logowanie sesje weryfikację adresu e-mail reset hasła zmianę hasła usuwanie konta podstawowe role i uprawnienia Żadna z tych rzeczy nie była szczególnie trudna.\nByła za to powtarzalna.\nPisałem już wcześniej podobny kod i nie chciałem w każdym nowym projekcie w Pythonie odtwarzać od podstaw tej samej warstwy zarządzania użytkownikami.\nZacząłem więc pracować nad UserHarbor.\nCzym jest UserHarbor? UserHarbor to niezależna od frameworka biblioteka Pythona służąca do zarządzania kontami użytkowników.\nZałożenie jest proste:\nrdzeń powinien pozostać mały, przewidywalny i niezależny od konkretnego frameworka webowego, bazy danych, ORM-u czy dostawcy poczty.\nRdzeń obsługuje logikę zarządzania kontami. Integracjami zajmują się osobne pakiety adapterów.\nZamiast tworzyć rozwiązanie wyłącznie dla FastAPI, Flaska, Django czy jednego konkretnego stosu technologicznego, chciałem zbudować rdzeń nadający się do użycia w różnych rodzajach aplikacji w Pythonie.\nNa przykład w:\naplikacjach FastAPI aplikacjach Flask aplikacjach Django narzędziach CLI narzędziach wewnętrznych własnych usługach w Pythonie Dlaczego nie użyć po prostu biblioteki dla konkretnego frameworka? Istnieją już dobre narzędzia przeznaczone dla konkretnych frameworków.\nMnie jednak zależało na czymś nieco innym.\nNie chciałem, aby logika zarządzania użytkownikami była ściśle powiązana z:\nframeworkiem webowym warstwą bazy danych dostawcą poczty konkretnym modelem żądań i odpowiedzi Zamiast tego UserHarbor używa niewielkich interfejsów dla takich elementów jak przechowywanie danych i wysyłanie wiadomości e-mail.\nGłówne interfejsy to:\nclass UserStore: ... class EmailSender: ... Rdzenia nie interesuje, w jaki sposób użytkownicy są przechowywani ani jak wysyłane są wiadomości e-mail.\nZa tę część odpowiadają adaptery.\nInstalacja Jeśli chcesz dostarczyć własne implementacje UserStore i EmailSender, zainstaluj tylko pakiet rdzenia:\npip install userharbor Aby zainstalować rdzeń wraz z oficjalnymi adapterami SQLAlchemy, SMTP i FastAPI:\npip install \u0026#34;userharbor[sqlalchemy,smtp,fastapi]\u0026#34; Możesz też od razu zainstalować wszystkie oficjalne integracje:\npip install \u0026#34;userharbor[all]\u0026#34; Oficjalne adaptery Obecnie dostępnych jest kilka oficjalnych pakietów adapterów:\nuserharbor-sqlalchemy — przechowywanie danych za pomocą SQLAlchemy userharbor-smtp — wysyłanie wiadomości e-mail przez SMTP userharbor-fastapi — integracja z FastAPI Dzięki temu rdzeń pozostaje mały, a jednocześnie typową konfigurację można łatwo zainstalować i uruchomić.\nSzybki przykład Oto dłuższy przykład wykorzystujący SQLAlchemy do przechowywania danych i SMTP do wysyłania wiadomości e-mail:\nfrom sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from userharbor import UserHarbor from userharbor_sqlalchemy import SQLAlchemyUserStore from userharbor_smtp import SMTPEmailSender engine = create_engine(\u0026#34;sqlite:///users.db\u0026#34;) SessionLocal = sessionmaker(bind=engine) store = SQLAlchemyUserStore(SessionLocal) store.metadata.create_all(engine) email_sender = SMTPEmailSender( host=\u0026#34;smtp.example.com\u0026#34;, port=587, username=\u0026#34;smtp-user\u0026#34;, password=\u0026#34;smtp-password\u0026#34;, from_email=\u0026#34;noreply@example.com\u0026#34;, ) harbor = UserHarbor( secret_key=\u0026#34;your-secret-key\u0026#34;, store=store, email_sender=email_sender, ) # Rejestracja użytkownika harbor.register( username=\u0026#34;jane\u0026#34;, email=\u0026#34;jane@example.com\u0026#34;, password=\u0026#34;StrongPassword123!\u0026#34;, ) # Weryfikacja adresu e-mail harbor.verify_email(\u0026#34;verification-token-from-email\u0026#34;) # Logowanie session_token = harbor.login( username=\u0026#34;jane\u0026#34;, password=\u0026#34;StrongPassword123!\u0026#34;, ) # Weryfikacja sesji if harbor.verify_session(session_token): print(\u0026#34;Użytkownik jest zalogowany\u0026#34;) # Pobranie bieżącego użytkownika current_user = harbor.get_current_user(session_token) print(current_user.username) # Utworzenie ról i uprawnień harbor.roles.create(\u0026#34;admin\u0026#34;) harbor.permissions.create(\u0026#34;users.delete\u0026#34;) harbor.roles.grant_permission(\u0026#34;admin\u0026#34;, \u0026#34;users.delete\u0026#34;) harbor.grant_role(\u0026#34;jane\u0026#34;, \u0026#34;admin\u0026#34;) # Sprawdzenie dostępu if harbor.has_permission(session_token, \u0026#34;users.delete\u0026#34;): print(\u0026#34;Użytkownik może usuwać innych użytkowników\u0026#34;) current_admin = harbor.require_role(session_token, \u0026#34;admin\u0026#34;) print(current_admin.username) # Wylogowanie harbor.logout(session_token) # Zmiana hasła session_token = harbor.login( username=\u0026#34;jane\u0026#34;, password=\u0026#34;StrongPassword123!\u0026#34;, ) harbor.change_password( old_password=\u0026#34;StrongPassword123!\u0026#34;, new_password=\u0026#34;EvenStrongerPassword123!\u0026#34;, session_token=session_token, ) # Wysłanie wiadomości umożliwiającej zresetowanie hasła harbor.send_password_reset(\u0026#34;jane@example.com\u0026#34;) # Reset hasła harbor.reset_password( new_password=\u0026#34;NewStrongPassword123!\u0026#34;, reset_token=\u0026#34;reset-token-from-email\u0026#34;, ) # Usunięcie konta session_token = harbor.login( username=\u0026#34;jane\u0026#34;, password=\u0026#34;NewStrongPassword123!\u0026#34;, ) harbor.delete_account( password=\u0026#34;NewStrongPassword123!\u0026#34;, session_token=session_token, ) Pełny przykład FastAPI z oficjalnymi integracjami Jeśli chcesz wypróbować pełną konfigurację z FastAPI, SQLAlchemy i SMTP, zainstaluj wszystkie oficjalne integracje:\npip install \u0026#34;userharbor[all]\u0026#34; Następnie utwórz aplikację FastAPI:\nimport os from fastapi import FastAPI from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from userharbor import UserHarbor from userharbor_fastapi import UserHarborFastAPI from userharbor_smtp import SMTPEmailSender from userharbor_sqlalchemy import SQLAlchemyUserStore engine = create_engine(\u0026#34;sqlite:///users.db\u0026#34;) SessionLocal = sessionmaker(bind=engine) store = SQLAlchemyUserStore(SessionLocal) store.metadata.create_all(engine) email_sender = SMTPEmailSender( host=os.getenv(\u0026#34;HOST\u0026#34;, \u0026#34;smtp.example.com\u0026#34;), port=int(os.getenv(\u0026#34;PORT\u0026#34;, 587)), username=os.getenv(\u0026#34;USERNAME\u0026#34;), password=os.getenv(\u0026#34;PASSWORD\u0026#34;), from_email=os.getenv(\u0026#34;USERNAME\u0026#34;, \u0026#34;\u0026#34;), ) harbor = UserHarbor( secret_key=\u0026#34;your-secret-key\u0026#34;, store=store, email_sender=email_sender, ) auth = UserHarborFastAPI(harbor) app = FastAPI() app.include_router(auth.router, prefix=\u0026#34;/auth\u0026#34;, tags=[\u0026#34;auth\u0026#34;]) if __name__ == \u0026#34;__main__\u0026#34;: import uvicorn uvicorn.run(app, host=\u0026#34;0.0.0.0\u0026#34;, port=8000) Zasady projektowe Projekt opiera się na kilku założeniach.\nRdzeń powinien pozostać mały UserHarbor nie ma stać się kompletną platformą do zarządzania tożsamością.\nRdzeń koncentruje się na podstawowych procesach związanych z zarządzaniem kontami:\nrejestracji logowaniu sesjach weryfikacji adresu e-mail resetowaniu hasła zmianie hasła usuwaniu konta prostej kontroli dostępu opartej na rolach Wszystko, co jest wysoce specyficzne dla danej aplikacji, powinno pozostać poza rdzeniem.\nAdaptery powinny znajdować się poza rdzeniem Integracje z bazami danych, ORM-ami, pocztą i frameworkami powinny być osobnymi pakietami.\nDzięki temu rdzeń pozostaje niezależny, a inni mogą łatwiej tworzyć własne integracje.\nKtoś mógłby na przykład stworzyć:\nuserharbor-redis userharbor-mongodb userharbor-sendgrid userharbor-resend userharbor-django userharbor-flask bez modyfikowania głównego pakietu.\nAPI powinno być nudne Staram się, aby publiczne API było jawne i przewidywalne.\nBez ukrytej magii frameworka. Bez narzuconego modelu bazy danych. Bez zależności od jednego konkretnego sposobu budowania aplikacji w Pythonie.\nObecny stan Projekt jest nadal na wczesnym etapie rozwoju.\nPodstawowe procesy działają, ale API nie jest jeszcze w pełni stabilne. Obecnie nie nazwałbym tej biblioteki gotową do zastosowań produkcyjnych.\nW tej chwili zależy mi przede wszystkim na opiniach dotyczących:\npublicznego API architektury adapterów granicy pomiędzy rdzeniem a integracjami integracji z SQLAlchemy integracji z FastAPI tego, czy prosty RBAC powinien należeć do rdzenia tego, jak powinno wyglądać wygodne tworzenie własnych adapterów Linki Dokumentacja:\nhttps://userharbor.github.io/userharbor/\nRepozytorium:\nhttps://github.com/userharbor/userharbor\nIntegracja FastAPI:\nhttps://github.com/userharbor/userharbor-fastapi\nAdapter SQLAlchemy:\nhttps://github.com/userharbor/userharbor-sqlalchemy\nAdapter SMTP:\nhttps://github.com/userharbor/userharbor-smtp\nOpinie mile widziane Będę wdzięczny za wszelkie uwagi, zwłaszcza od osób, które wielokrotnie tworzyły w Pythonie mechanizmy zarządzania użytkownikami.\nCzy takie podejście oparte na adapterach ma sens?\nCzy spodziewalibyście się prostych ról i uprawnień w rdzeniu, czy raczej w osobnym pakiecie?\nA gdybyście integrowali UserHarbor z własnym projektem, jakiego API byście oczekiwali?\nAktualizacja: później napisałem bardziej szczegółowy artykuł o architekturze adapterów UserHarbor i wykonywalnym kontrakcie warstwy danych.\nArtykuł pierwotnie opublikowany po angielsku na DEV Community.\n","permalink":"https://spaceshaman.github.io/pl/posts/i-built-userharbor-a-framework-agnostic-user-management-library-for-python/","summary":"\u003cp\u003ePracując ostatnio nad aplikacją SaaS, po raz kolejny musiałem zaimplementować ten sam zestaw funkcji związanych z kontami użytkowników:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003erejestrację\u003c/li\u003e\n\u003cli\u003elogowanie\u003c/li\u003e\n\u003cli\u003esesje\u003c/li\u003e\n\u003cli\u003eweryfikację adresu e-mail\u003c/li\u003e\n\u003cli\u003ereset hasła\u003c/li\u003e\n\u003cli\u003ezmianę hasła\u003c/li\u003e\n\u003cli\u003eusuwanie konta\u003c/li\u003e\n\u003cli\u003epodstawowe role i uprawnienia\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eŻadna z tych rzeczy nie była szczególnie trudna.\u003c/p\u003e\n\u003cp\u003eByła za to powtarzalna.\u003c/p\u003e\n\u003cp\u003ePisałem już wcześniej podobny kod i nie chciałem w każdym nowym projekcie w Pythonie odtwarzać od podstaw tej samej warstwy zarządzania użytkownikami.\u003c/p\u003e\n\u003cp\u003eZacząłem więc pracować nad \u003cstrong\u003eUserHarbor\u003c/strong\u003e.\u003c/p\u003e","title":"Stworzyłem UserHarbor — niezależną od frameworka bibliotekę do zarządzania użytkownikami w Pythonie"},{"content":"Tworzę oprogramowanie i narzędzia open source. Najbardziej interesuje mnie cały proces tworzenia — od pomysłu, przez projekt architektury, aż po działające i użyteczne rozwiązanie. Pracuję w różnych obszarach programowania i dobieram technologie do problemu, zamiast dopasowywać problem do konkretnego stosu technologicznego.\nMoje projekty obejmują biblioteki, API działające w czasie rzeczywistym, narzędzia do pracy z bazami danych oraz automatyzację codziennych zadań programistycznych. Niezależnie od obszaru zależy mi na przejrzystej architekturze, prostych rozwiązaniach i tworzeniu narzędzi, które rozwiązują konkretne problemy bez zbędnej złożoności.\nW pracy i w życiu staram się kierować zasadą: Simple is better than complex.\nWybrane projekty UserHarbor — system zarządzania kontami użytkowników w aplikacjach Python, działający niezależnie od używanego frameworka. SocketAPI — lekki framework API czasu rzeczywistego wykorzystujący jedno multipleksowane połączenie WebSocket, akcje podobne do endpointów i subskrypcje. SQLift — celowo niewielkie narzędzie wiersza poleceń do migracji baz SQL. ORMagic — prosty i lekki ORM dla Pythona, zbudowany na bazie Pydantica. autopy.fish i autoenv.fish — wtyczki Fish automatycznie aktywujące środowiska Pythona i wczytujące zmienne z plików .env. Znajdziesz mnie tutaj GitHub LinkedIn CoderLegion spaceshaman@tuta.io ","permalink":"https://spaceshaman.github.io/pl/about/","summary":"\u003cp\u003eTworzę oprogramowanie i narzędzia open source. Najbardziej interesuje mnie cały proces tworzenia — od pomysłu, przez projekt architektury, aż po działające i użyteczne rozwiązanie. Pracuję w różnych obszarach programowania i dobieram technologie do problemu, zamiast dopasowywać problem do konkretnego stosu technologicznego.\u003c/p\u003e\n\u003cp\u003eMoje projekty obejmują biblioteki, API działające w czasie rzeczywistym, narzędzia do pracy z bazami danych oraz automatyzację codziennych zadań programistycznych. Niezależnie od obszaru zależy mi na przejrzystej architekturze, prostych rozwiązaniach i tworzeniu narzędzi, które rozwiązują konkretne problemy bez zbędnej złożoności.\u003c/p\u003e","title":"O mnie"}]