Skip to content

Latest commit

 

History

History
575 lines (451 loc) · 16.8 KB

File metadata and controls

575 lines (451 loc) · 16.8 KB

PROJECT.md - Python Hexagonal Study

Visão Geral

Nome do Projeto: python-hexagonal-study Repositório: marcellmartini/python-hexagonal-study Autor: Marcell Martini Licença: MIT

Descrição: Projeto de estudo e demonstração de arquitetura hexagonal (Ports & Adapters) em Python com FastAPI. Inclui User Management com JWT, RBAC, File Storage com MinIO e Frontend React com shadcn/ui.


Stack Tecnológica

Backend

Componente Tecnologia Versão
Framework FastAPI 0.127.x
Linguagem Python 3.10+
ORM SQLAlchemy 2.x
Migrations Alembic 1.17.x
Auth python-jose (JWT) 3.x
Password passlib + bcrypt 1.7.x
Validation Pydantic 2.x
Settings pydantic-settings 2.x

Frontend

Componente Tecnologia Versão
Framework React 19
Build Vite 6.x
Linguagem TypeScript 5.x
Estilo Tailwind CSS 4.x
Componentes shadcn/ui latest
Estado Zustand 5.x
Routing React Router 7.x
HTTP Axios 1.7.x

Infraestrutura

Componente Tecnologia Versão
Database PostgreSQL 16
Object Storage MinIO Latest
Container Docker + Compose Latest

Estrutura do Monorepo

python-hexagonal-study/
├── apps/
│   ├── backend/                   # API FastAPI
│   │   ├── src/
│   │   │   ├── domain/            # Entidades, Ports, Exceções
│   │   │   │   ├── user/          # User entity, UserPersistencePort
│   │   │   │   ├── storage/       # StoragePort
│   │   │   │   ├── builder/       # BuilderPort
│   │   │   │   ├── exceptions.py
│   │   │   │   └── value_objects.py
│   │   │   ├── application/       # Serviços de aplicação
│   │   │   │   ├── user/          # AuthService, UserService
│   │   │   │   └── services/      # FileService
│   │   │   ├── infrastructure/    # Adapters
│   │   │   │   ├── database/      # PostgreSQL adapter
│   │   │   │   └── storage/       # MinIO adapter
│   │   │   ├── api/               # FastAPI routes
│   │   │   │   ├── auth/          # /auth/*
│   │   │   │   ├── users/         # /users/*
│   │   │   │   ├── files/         # /files/*
│   │   │   │   └── security/      # Permissões
│   │   │   └── main.py
│   │   ├── tests/                 # 122 testes, 100% coverage
│   │   ├── alembic/               # Migrations
│   │   ├── pyproject.toml
│   │   ├── Dockerfile
│   │   └── compose.yaml           # PostgreSQL standalone
│   │
│   └── frontend/                  # React + shadcn/ui
│       ├── src/
│       │   ├── components/
│       │   │   └── ui/            # Componentes shadcn/ui
│       │   ├── features/
│       │   │   ├── auth/          # Login, Register
│       │   │   ├── users/         # User management
│       │   │   ├── files/         # File manager
│       │   │   └── profile/       # User profile
│       │   ├── hooks/             # Custom hooks
│       │   ├── lib/
│       │   │   └── utils.ts       # cn() utility
│       │   ├── services/
│       │   │   └── api.ts         # Axios client
│       │   ├── stores/
│       │   │   └── auth.ts        # Zustand store
│       │   ├── App.tsx
│       │   ├── main.tsx
│       │   └── index.css          # Tailwind + CSS vars
│       ├── package.json
│       ├── vite.config.ts
│       ├── components.json        # shadcn/ui config
│       ├── Dockerfile
│       └── nginx.conf
│
├── docker-compose.yaml            # Full stack (postgres, minio, backend, frontend)
├── CLAUDE.md                      # Instruções para Claude CLI
├── PROJECT.md                     # Este arquivo
└── .gitignore

Arquitetura Hexagonal

Padrões Utilizados

Protocol (Port)

from typing import Protocol, runtime_checkable

@runtime_checkable
class UserPersistencePort(Protocol):
    def save(self, user: User) -> User: ...
    def find_by_id(self, user_id: UUID) -> Optional[User]: ...

Factory + Registry

class DatabaseRegistry:
    _builders: Dict[str, UserPersistenceBuilder] = {}

    def register(self, provider: str, builder: UserPersistenceBuilder):
        self._builders[provider] = builder

def create_user_persistence(session: Session) -> UserPersistencePort:
    builder = DatabaseRegistry.get(config.provider)
    return builder.build(session)

API Endpoints

Auth (/api/auth)

Método Endpoint Auth Descrição
POST /auth/register - Registrar usuário
POST /auth/login - Login (retorna JWT)
POST /auth/refresh - Refresh token
GET /auth/me Dados do usuário atual
POST /auth/logout Logout

Users (/api/users)

Método Endpoint Auth Role Descrição
GET /users any Listar usuários
GET /users/{id} any Buscar usuário
POST /users admin Criar usuário
PUT /users/{id} admin Atualizar usuário
DELETE /users/{id} admin Deletar usuário

Files (/api/files)

Método Endpoint Auth Descrição
POST /files/upload Upload de arquivo (owner: current user)
GET /files/{id} Download de arquivo (owner ou admin)
GET /files/ Listar arquivos (próprios ou todos se admin)
DELETE /files/{id} Deletar arquivo (owner ou admin)
PUT /files/{id} Atualizar arquivo (owner ou admin)

Ambiente de Desenvolvimento

Pré-requisitos

  • Python 3.10+
  • Node.js 22+
  • Docker e Docker Compose
  • Poetry (Python)
  • npm/pnpm/bun (Node)

Setup Completo (Docker)

# Clonar repositório
git clone https://github.com/marcellmartini/python-hexagonal-study.git
cd python-hexagonal-study

# Subir todos os serviços
docker compose up -d

# Acessar:
# - Frontend: http://localhost:3000
# - Backend API: http://localhost:8000/docs
# - MinIO Console: http://localhost:9001

Setup Backend (Desenvolvimento)

cd apps/backend

# Criar ambiente virtual
python -m venv .venv
source .venv/bin/activate

# Instalar dependências
pip install poetry
poetry install

# Subir PostgreSQL
docker compose up -d

# Rodar migrations
alembic upgrade head

# Rodar aplicação
PYTHONPATH=src uvicorn api.main:app --reload

Setup Frontend (Desenvolvimento)

cd apps/frontend

# Instalar dependências
npm install

# Adicionar componentes shadcn/ui
npx shadcn@latest add button card input form table dialog toast

# Rodar em desenvolvimento
npm run dev

Frontend com shadcn/ui

Componentes Disponíveis

shadcn/ui fornece componentes acessíveis e customizáveis baseados em Radix UI:

# Instalar componentes conforme necessário
npx shadcn@latest add button        # Botões
npx shadcn@latest add card          # Cards
npx shadcn@latest add input         # Inputs
npx shadcn@latest add form          # Formulários (react-hook-form + zod)
npx shadcn@latest add table         # Tabelas
npx shadcn@latest add dialog        # Modais
npx shadcn@latest add toast         # Notificações
npx shadcn@latest add dropdown-menu # Menus
npx shadcn@latest add avatar        # Avatares
npx shadcn@latest add badge         # Badges

Estrutura de Features

src/features/auth/
├── components/
│   ├── LoginForm.tsx
│   └── RegisterForm.tsx
├── hooks/
│   └── useAuth.ts
└── pages/
    ├── LoginPage.tsx
    └── RegisterPage.tsx

Zustand Store

// stores/auth.ts
export const useAuthStore = create<AuthState>()(
  persist(
    (set) => ({
      user: null,
      accessToken: null,
      isAuthenticated: false,
      setAuth: (user, token) => set({ user, accessToken: token, isAuthenticated: true }),
      logout: () => set({ user: null, accessToken: null, isAuthenticated: false }),
    }),
    { name: "auth-storage" }
  )
)

Testes

Backend

  • Total de testes: 122
  • Cobertura: 100%
  • Tempo de execução: ~11s
cd apps/backend

# Rodar testes
PYTHONPATH=src pytest tests/ -v

# Com cobertura
PYTHONPATH=src pytest tests/ --cov=src --cov-report=term-missing

# Verificar cobertura mínima
PYTHONPATH=src pytest tests/ --cov=src --cov-fail-under=100

Comandos Úteis

Monorepo (Raiz)

# Subir tudo
docker compose up -d

# Parar tudo
docker compose down

# Ver logs
docker compose logs -f

# Rebuild
docker compose up -d --build

Backend

cd apps/backend

# Testes
PYTHONPATH=src pytest tests/ -v

# Linting
pylint src/
pyright src/
black src/ tests/

# Migrations
alembic upgrade head
alembic revision --autogenerate -m "description"

Frontend

cd apps/frontend

# Desenvolvimento
npm run dev

# Build
npm run build

# Lint
npm run lint

# Adicionar componente shadcn
npx shadcn@latest add [component]

Próximos Passos

Fase 1: Frontend Base ✅

  • Setup monorepo
  • Estrutura React + Vite + TypeScript
  • Configuração Tailwind CSS 4
  • Configuração shadcn/ui
  • Zustand store
  • API client (Axios)
  • Implementar páginas de auth (Login/Register)
  • Implementar Dashboard
  • Implementar User Management

Fase 2: Funcionalidades ✅

  • File Manager (com ownership por usuário e paginação)
  • Profile page
  • Dark mode toggle
  • Sistema dual de temas (Spotlight + Catppuccin)
  • Responsividade (mobile/tablet)

Fase 3: UX/UI ✅

  • Toggle animado para dark/light mode (ThemeModeToggle com sol/lua)
  • Settings popover no sidebar (SettingsPopover)
  • Settings drawer no user menu (SettingsDrawer - abre do lado direito)
  • Página completa de settings (/settings)
  • Notificações toast (sonner)

Fase 4: Qualidade

  • Testes unitários (Vitest)
  • Testes E2E (Playwright)
  • CI/CD (GitHub Actions)

Estado Atual da Implementação

Backend (100% Completo)

User Management

  • Entidade User: apps/backend/src/domain/user/entities.py
    • Campos: id, name, email, password_hash, role, birth_date, created_at, updated_at
    • Roles: USER, ADMIN
  • Port: apps/backend/src/domain/user/ports.py (Protocol)
  • Services:
    • AuthService: JWT tokens, bcrypt hashing, autenticação
    • UserService: CRUD operations
  • Adapter: apps/backend/src/infrastructure/database/postgresql/user_adapter.py
  • API Routes:
    • /auth/*: register, login, refresh, me, logout
    • /users/*: list, get, create, update, delete

File Storage

  • Port: apps/backend/src/domain/storage/ports.py (StoragePort Protocol)
  • Service: apps/backend/src/application/services/file_service.py
  • Adapter: apps/backend/src/infrastructure/storage/minio/storage_adapter.py
  • API Routes: /files/*: upload, download, list, delete, update

Testes

  • Total: 122 testes
  • Cobertura: 100%
  • Estrutura:
    • tests/user/test_api.py: Integração (auth + users endpoints)
    • tests/user/test_unit.py: Unitários (services + adapters)
    • tests/files/test_api.py: Integração (file endpoints)
    • tests/files/test_unit.py: Unitários (FileService)
    • tests/storage/test_unit.py: Adapters de storage
    • tests/domain/test_value_objects.py: Value objects

Frontend (100% Completo)

Implementado

  • Configuração Vite + React 19 + TypeScript
  • Tailwind CSS 4 com CSS variables para temas
  • shadcn/ui configurado (components.json)
  • Zustand store para autenticação (src/stores/auth.ts)
  • Axios client com interceptors JWT (src/services/api.ts)
  • Dockerfile multi-stage + nginx.conf para produção
  • Páginas de Auth: LoginPage, RegisterPage com validação (react-hook-form + zod)
  • Dashboard: Welcome page com cards de estatísticas (dados reais da API)
  • User Management: Tabela CRUD completa (list, create, edit inline, delete admin-only) com avatars e search
  • File Manager: Página completa de gestão de arquivos (upload, list, download, delete) com ownership por usuário, paginação 5/10/20/50/100, ícones por tipo de arquivo
  • Profile: Página de perfil do usuário com ícones coloridos
  • Layout: Navbar responsiva, Sidebar com navegação, MainLayout (estilo Spotlight)
  • Sistema de Temas: Dual theme system (Spotlight zinc/teal + Catppuccin Mocha/Latte)
  • Estado: Zustand stores para auth, theme, users, files com persist

Sistema de Temas (PR #12)

O frontend suporta dois color schemes, cada um com light/dark mode:

Color Scheme Light Dark Cores Principais
Spotlight zinc white zinc black teal (#14b8a6 / #2dd4bf)
Catppuccin Latte Mocha blue (#1e66f5 / #89b4fa)

Arquivos de tema:

  • src/styles/themes/spotlight.css - Tema Spotlight
  • src/styles/themes/catppuccin.css - Tema Catppuccin
  • src/index.css - Importa ambos, fallback para Spotlight

Build-time config:

VITE_DEFAULT_COLOR_SCHEME=spotlight npm run build  # ou catppuccin

API Client (Axios)

// src/services/api.ts - Já configurado com:
// - Request interceptor: adiciona Bearer token
// - Response interceptor: refresh automático em 401
// - Exports: authApi, usersApi, filesApi

Zustand Store

// src/stores/auth.ts - Já configurado com:
// - user, accessToken, refreshToken, isAuthenticated
// - setAuth(), setAccessToken(), logout()
// - persist() para localStorage

Melhorias Implementadas (PR #13)

  1. Toggle Animado: Switch animado sol/lua (ThemeModeToggle.tsx) com tamanhos sm/md
  2. Settings Popover: Engrenagem no footer do sidebar com quick settings
  3. Settings Drawer: Drawer completo no UserMenu (abre do lado direito)
  4. Settings Page: Página dedicada em /settings com todas as configurações
  5. Notificações: Toast configurado (sonner)

Melhorias Futuras

  1. Responsividade: Otimização para mobile/tablet
  2. Testes E2E: Playwright para fluxos críticos (auth, user CRUD, file management)

Referência de animação: https://dribbble.com/shots/25421926-Toggle-Switch-Animation-with-Dark-and-Light-mode


Decisões Arquiteturais

Por que Protocol ao invés de ABC?

  • Structural typing (duck typing) vs nominal typing
  • Não requer herança explícita
  • Melhor integração com type checkers (mypy, pyright)
  • Pattern mais Pythonic

Por que Factory + Registry?

  • Desacoplamento total entre camadas
  • Facilita testes (mock fácil)
  • Suporta múltiplos providers (PostgreSQL, MySQL, etc.)
  • Configuração via ambiente (sem código)

Por que Zustand ao invés de Redux/Context?

  • API mais simples e direta
  • Menos boilerplate
  • Melhor performance (selective subscriptions)
  • Integração nativa com persist middleware

Por que shadcn/ui ao invés de Material UI/Chakra?

  • Componentes copiados para o projeto (não dependência)
  • Customização total via CSS variables
  • Baseado em Radix UI (acessibilidade)
  • Tailwind CSS nativo

Referências


Histórico de Commits (feat/user-management)

8625e32 docs: update for monorepo structure and frontend
3ae269c feat(docker): add full stack docker-compose
f556acf feat(frontend): add React 19 + Vite + shadcn/ui setup
e71a350 refactor(monorepo): move backend code to apps/backend
2991eb2 feat(docs): add PROJECT.md with complete project documentation
c9aff8f fix(user-tests): add missing test cases for full coverage
014e323 feat(file-tests): add comprehensive tests for file storage
665f83e feat(docs): add CLAUDE.md project documentation
6459aee feat(user-tests): add comprehensive tests for user management
45515e6 feat(alembic): add database migrations for users table
a1a2b3c feat(user-api): add auth and user endpoints with security
b2c3d4e feat(user-infra): add PostgreSQL adapter with registry pattern
c3d4e5f feat(user-services): add AuthService and UserService
d4e5f6g feat(user-domain): add User entity, ports and exceptions

Status: 13 commits ahead de origin/feat/user-management, aguardando PR para main