Sistema de autenticação de clientes (Customers) que fornece funcionalidades de:
- Registro de novos usuários (Signup)
- Autenticação (Login)
- Logout com invalidação de token
- Gerenciamento de perfil do usuário
- Operações CRUD para administradores
| Componente | Versão |
|---|---|
| Django | 5.2.8 |
| Django REST Framework | 3.16.1 |
| djangorestframework-simplejwt | 5.5.1 |
| drf-spectacular | 0.29.0 |
| Python | 3.x (inferido) |
| App | Responsabilidade |
|---|---|
core |
Configurações gerais do projeto (settings, urls raiz, wsgi/asgi) |
customers |
Gerenciamento de clientes: modelos, autenticação, views, serializers |
- Framework: Django + Django REST Framework
- Organização: Separação por apps com responsabilidades isoladas
- Autenticação: JWT via
djangorestframework-simplejwt - Documentação automática: OpenAPI 3.0 via
drf-spectacular - Banco de dados: SQLite3 (ambiente de desenvolvimento)
- CORS: Habilitado via
django-cors-headers
JWT (JSON Web Token) utilizando a biblioteca djangorestframework-simplejwt.
| Biblioteca | Função |
|---|---|
djangorestframework-simplejwt |
Geração e validação de tokens JWT |
rest_framework_simplejwt.token_blacklist |
Blacklist de tokens para logout |
PyJWT |
Dependência para manipulação de JWT |
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=15),
"REFRESH_TOKEN_LIFETIME": timedelta(days=7),
"ROTATE_REFRESH_TOKENS": True,
"BLACKLIST_AFTER_ROTATION": True,
"AUTH_HEADER_TYPES": ('Bearer',),
"UPDATE_LAST_LOGIN": True,
}| Configuração | Valor | Descrição |
|---|---|---|
| Access Token Lifetime | 15 minutos | Tempo de validade do token de acesso |
| Refresh Token Lifetime | 7 dias | Tempo de validade do token de refresh |
| Rotate Refresh Tokens | True |
Gera novo refresh token a cada renovação |
| Blacklist After Rotation | True |
Invalida refresh tokens antigos após rotação |
| Update Last Login | True |
Atualiza campo last_login do usuário |
┌─────────────────────────────────────────────────────────────────┐
│ FLUXO DE AUTENTICAÇÃO │
└─────────────────────────────────────────────────────────────────┘
1. SIGNUP (Registro)
POST /api/v1/customers/signup/
↓
Retorna: { user, tokens: { access, refresh } }
2. LOGIN
POST /api/v1/customers/login/
Body: { identifier (email ou username), password }
↓
Retorna: { user, tokens: { access, refresh } }
3. ACESSO A RECURSOS PROTEGIDOS
GET/POST/PUT/DELETE /api/v1/...
Header: Authorization: Bearer <access_token>
4. REFRESH TOKEN
POST /api/v1/customers/token/refresh/
Body: { refresh }
↓
Retorna: { access, refresh (novo) }
5. LOGOUT
POST /api/v1/customers/logout/
Header: Authorization: Bearer <access_token>
Body: { refresh }
↓
Token é adicionado à blacklist
| Header | Valor | Endpoints |
|---|---|---|
Authorization |
Bearer <access_token> |
Todos os endpoints protegidos |
Content-Type |
application/json |
Todos os endpoints (padrão) |
| Permission | Descrição | Uso |
|---|---|---|
AllowAny |
Acesso público sem autenticação | Signup, Login, Token Refresh |
IsAuthenticated |
Requer usuário autenticado | Profile, Logout |
IsAdminUser |
Requer is_staff=True |
Listagem/criação de clientes (admin) |
IsSelfOrAdmin |
Usuário próprio ou admin | Atualizar/deletar clientes específicos |
Permission Customizada:
class IsSelfOrAdmin(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
return request.user.is_staff or obj.pk == request.user.pkO sistema permite login tanto por email quanto por username através do backend customizado:
class EmailOrUsernameModelBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
identifier = username or kwargs.get('email') or kwargs.get('username')
if '@' in identifier:
user = Customer.objects.get(email__iexact=identifier)
else:
user = Customer.objects.get(username__iexact=identifier)
# ...| Propriedade | Valor |
|---|---|
| Método HTTP | POST |
| URL | /api/v1/customers/signup/ |
| App | customers |
| View | CustomerSignupView (CreateAPIView) |
| Serializer | CustomerRegistrationSerializer |
| Permission | AllowAny |
Descrição: Registra um novo cliente e retorna os tokens JWT.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
username |
string | ✅ | Nome de usuário único (max 25 chars) |
email |
string | ✅ | Email único do usuário |
password |
string | ✅ | Senha (validações do Django) |
password_confirm |
string | ✅ | Confirmação da senha |
name |
string | ❌ | Nome completo |
POST /api/v1/customers/signup/
Content-Type: application/json
{
"username": "johndoe",
"email": "john@example.com",
"password": "SecurePass123!",
"password_confirm": "SecurePass123!",
"name": "John Doe"
}{
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"username": "johndoe",
"email": "john@example.com",
"name": "John Doe",
"created_at": "2026-01-21T10:30:00Z",
"updated_at": "2026-01-21T10:30:00Z"
},
"tokens": {
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
},
"message": "Customer registered successfully."
}{
"password": ["Password fields didn't match."]
}{
"email": ["customer with this email already exists."]
}| Código | Descrição |
|---|---|
| 201 | Criado com sucesso |
| 400 | Erro de validação |
- Senhas devem coincidir (
password==password_confirm) - Senha passa pelas validações padrão do Django:
- Similaridade com atributos do usuário
- Mínimo 8 caracteres
- Não pode ser senha comum
- Não pode ser inteiramente numérica
- Email deve ser único
- Username deve ser único (max 25 caracteres)
| Propriedade | Valor |
|---|---|
| Método HTTP | POST |
| URL | /api/v1/customers/login/ |
| App | customers |
| View | CustomerLoginView (APIView) |
| Serializer | CustomerLoginSerializer |
| Permission | AllowAny |
Descrição: Autentica o cliente usando email ou username.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
identifier |
string | ✅ | Email ou Username |
password |
string | ✅ | Senha do usuário |
POST /api/v1/customers/login/
Content-Type: application/json
{
"identifier": "john@example.com",
"password": "SecurePass123!"
}ou
{
"identifier": "johndoe",
"password": "SecurePass123!"
}{
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"username": "johndoe",
"email": "john@example.com",
"name": "John Doe",
"created_at": "2026-01-21T10:30:00Z",
"updated_at": "2026-01-21T10:30:00Z"
},
"tokens": {
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
},
"message": "Customer logged in successfully."
}{
"error": "Invalid credentials or inactive account."
}| Código | Descrição |
|---|---|
| 200 | Login bem-sucedido |
| 400 | Dados inválidos |
| 401 | Credenciais inválidas ou conta inativa |
| Propriedade | Valor |
|---|---|
| Método HTTP | POST |
| URL | /api/v1/customers/logout/ |
| App | customers |
| View | CustomerLogoutView (APIView) |
| Serializer | N/A |
| Permission | IsAuthenticated |
Descrição: Invalida o refresh token adicionando-o à blacklist.
| Header | Valor |
|---|---|
Authorization |
Bearer <access_token> |
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
refresh |
string | ✅ | Refresh token a ser invalidado |
POST /api/v1/customers/logout/
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
{
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}{
"message": "Logout successful."
}{
"error": "Refresh token is required."
}{
"error": "Invalid refresh token."
}| Código | Descrição |
|---|---|
| 205 | Logout bem-sucedido (Reset Content) |
| 400 | Token não fornecido ou inválido |
| 401 | Não autenticado |
| Propriedade | Valor |
|---|---|
| Método HTTP | POST |
| URL | /api/v1/customers/token/refresh/ |
| App | customers |
| View | JWTTokenRefreshView (TokenRefreshView) |
| Serializer | TokenRefreshSerializer (simplejwt) |
| Permission | AllowAny |
Descrição: Gera um novo par de tokens usando o refresh token.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
refresh |
string | ✅ | Refresh token válido |
POST /api/v1/customers/token/refresh/
Content-Type: application/json
{
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}{
"access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}Nota: Como
ROTATE_REFRESH_TOKENS=True, um novo refresh token é gerado e o antigo é adicionado à blacklist.
| Código | Descrição |
|---|---|
| 200 | Tokens renovados |
| 401 | Token inválido, expirado ou na blacklist |
| Propriedade | Valor |
|---|---|
| Métodos HTTP | GET, PUT, PATCH, DELETE |
| URL | /api/v1/customers/profile/ |
| App | customers |
| View | CustomerProfileView (RetrieveUpdateDestroyAPIView) |
| Serializer | CustomerSerializer |
| Permission | IsAuthenticated |
Descrição: Gerencia o perfil do usuário autenticado.
GET /api/v1/customers/profile/
Authorization: Bearer <access_token>Response (200):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"username": "johndoe",
"email": "john@example.com",
"name": "John Doe",
"created_at": "2026-01-21T10:30:00Z",
"updated_at": "2026-01-21T10:30:00Z"
}Campos editáveis: name apenas (outros são read-only)
PATCH /api/v1/customers/profile/
Authorization: Bearer <access_token>
Content-Type: application/json
{
"name": "John Updated Doe"
}Response (200):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"username": "johndoe",
"email": "john@example.com",
"name": "John Updated Doe",
"created_at": "2026-01-21T10:30:00Z",
"updated_at": "2026-01-21T12:00:00Z"
}DELETE /api/v1/customers/profile/
Authorization: Bearer <access_token>Response (204): No Content
| Código | Descrição |
|---|---|
| 200 | Sucesso (GET, PUT, PATCH) |
| 204 | Deletado (DELETE) |
| 401 | Não autenticado |
| Propriedade | Valor |
|---|---|
| Métodos HTTP | GET, POST |
| URL | /api/v1/customers/ |
| App | customers |
| View | CustomerCreateListView (ListCreateAPIView) |
| Serializer | CustomerSerializer (GET), CustomerRegistrationSerializer (POST) |
| Permission | IsAdminUser |
Descrição: Listagem e criação de clientes (apenas para administradores).
GET /api/v1/customers/
Authorization: Bearer <access_token_admin>Response (200) (paginado):
{
"count": 25,
"next": "http://localhost:8000/api/v1/customers/?page=2",
"previous": null,
"results": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"username": "johndoe",
"email": "john@example.com",
"name": "John Doe",
"created_at": "2026-01-21T10:30:00Z",
"updated_at": "2026-01-21T10:30:00Z"
}
]
}Query Params (Paginação):
| Parâmetro | Tipo | Default | Descrição |
|---|---|---|---|
page |
int | 1 | Número da página |
Nota: Página padrão de 10 itens (configurado em settings).
POST /api/v1/customers/
Authorization: Bearer <access_token_admin>
Content-Type: application/json
{
"username": "newuser",
"email": "newuser@example.com",
"password": "SecurePass123!",
"password_confirm": "SecurePass123!",
"name": "New User"
}Response (201):
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"username": "newuser",
"email": "newuser@example.com",
"name": "New User",
"created_at": "2026-01-21T14:00:00Z",
"updated_at": "2026-01-21T14:00:00Z"
}| Código | Descrição |
|---|---|
| 200 | Lista retornada |
| 201 | Cliente criado |
| 400 | Erro de validação |
| 401 | Não autenticado |
| 403 | Sem permissão (não é admin) |
| Propriedade | Valor |
|---|---|
| Métodos HTTP | GET, PUT, PATCH, DELETE |
| URL | /api/v1/customers/<uuid:pk>/ |
| App | customers |
| View | CustomerRetrieveUpdateDestroyView (RetrieveUpdateDestroyAPIView) |
| Serializer | CustomerSerializer |
| Permission | IsAuthenticated, IsSelfOrAdmin |
Descrição: CRUD de cliente específico. Apenas o próprio usuário ou admin podem acessar.
| Parâmetro | Tipo | Descrição |
|---|---|---|
pk |
UUID | ID único do cliente |
GET /api/v1/customers/550e8400-e29b-41d4-a716-446655440000/
Authorization: Bearer <access_token>Response (200):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"username": "johndoe",
"email": "john@example.com",
"name": "John Doe",
"created_at": "2026-01-21T10:30:00Z",
"updated_at": "2026-01-21T10:30:00Z"
}PATCH /api/v1/customers/550e8400-e29b-41d4-a716-446655440000/
Authorization: Bearer <access_token>
Content-Type: application/json
{
"name": "John Modified"
}DELETE /api/v1/customers/550e8400-e29b-41d4-a716-446655440000/
Authorization: Bearer <access_token>Response (204): No Content
| Código | Descrição |
|---|---|
| 200 | Sucesso (GET, PUT, PATCH) |
| 204 | Deletado (DELETE) |
| 401 | Não autenticado |
| 403 | Sem permissão (não é owner nem admin) |
| 404 | Cliente não encontrado |
| Endpoint | Método | Descrição |
|---|---|---|
/api/schema/ |
GET | Schema OpenAPI 3.0 (JSON) |
/api/swagger-ui/ |
GET | Interface Swagger UI |
/api/redoc/ |
GET | Interface ReDoc |
Localização: customers/models.py
O modelo Customer é o modelo de usuário customizado do sistema, estendendo AbstractBaseUser e PermissionsMixin.
class Customer(AbstractBaseUser, PermissionsMixin):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
email = models.EmailField(unique=True)
username = models.CharField(max_length=25, unique=True)
name = models.CharField(max_length=255, blank=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)| Campo | Tipo | Obrigatório | Único | Default | Descrição |
|---|---|---|---|---|---|
id |
UUIDField | Auto | ✅ | uuid4 | Chave primária |
email |
EmailField | ✅ | ✅ | - | Email do usuário |
username |
CharField(25) | ✅ | ✅ | - | Nome de usuário |
name |
CharField(255) | ❌ | ❌ | "" | Nome completo |
password |
CharField(128) | ✅ | ❌ | - | Hash da senha (herdado) |
is_active |
BooleanField | - | - | True |
Conta ativa |
is_staff |
BooleanField | - | - | False |
Acesso ao admin |
is_superuser |
BooleanField | - | - | False |
Super usuário (herdado) |
last_login |
DateTimeField | ❌ | ❌ | null | Último login (herdado) |
created_at |
DateTimeField | Auto | - | now | Data de criação |
updated_at |
DateTimeField | Auto | - | now | Última atualização |
groups |
ManyToMany | ❌ | - | - | Grupos de permissão |
user_permissions |
ManyToMany | ❌ | - | - | Permissões específicas |
| Campo | Tipo | Modelo Relacionado | Descrição |
|---|---|---|---|
groups |
ManyToManyField | auth.Group |
Grupos do usuário |
user_permissions |
ManyToManyField | auth.Permission |
Permissões individuais |
USERNAME_FIELD = "email"- Login por emailREQUIRED_FIELDS = ["username", "name"]- Campos obrigatórios no createsuperuser- Usa
CustomerManagerpara criação de usuários
Manager customizado para criação de usuários:
class CustomerManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
# Valida email, password e username
# Normaliza email
# Cria e salva o usuário
def create_superuser(self, email, password=None, **extra_fields):
# Define defaults para username (parte do email)
# Define is_staff=True, is_superuser=True, is_active=TrueUso: Registro de novos clientes
| Campo | Tipo | Leitura | Escrita | Descrição |
|---|---|---|---|---|
id |
UUID | ✅ | ❌ | ID gerado |
username |
string | ✅ | ✅ | Nome de usuário |
email |
string | ✅ | ✅ | |
password |
string | ❌ | ✅ | Senha |
password_confirm |
string | ❌ | ✅ | Confirmação |
name |
string | ✅ | ✅ | Nome completo |
Validações Customizadas:
validate(): Verifica sepassword==password_confirm- Aplica validadores de senha do Django (
validate_password)
Método create(): Remove password_confirm e usa Customer.objects.create_user()
Uso: Leitura e atualização de dados do cliente
| Campo | Tipo | Leitura | Escrita | Descrição |
|---|---|---|---|---|
id |
UUID | ✅ | ❌ | ID (read-only) |
username |
string | ✅ | ❌ | Username (read-only) |
email |
string | ✅ | ❌ | Email (read-only) |
name |
string | ✅ | ✅ | Nome (editável) |
created_at |
datetime | ✅ | ❌ | Data criação |
updated_at |
datetime | ✅ | ❌ | Última atualização |
Nota: Apenas o campo
nameé editável após a criação.
Uso: Validação de dados de login
| Campo | Tipo | Leitura | Escrita | Descrição |
|---|---|---|---|---|
identifier |
string | ❌ | ✅ | Email ou Username |
password |
string | ❌ | ✅ | Senha |
Nota: Não é um
ModelSerializer, apenas valida campos de entrada.
Request POST /api/v1/customers/signup/
│
▼
CustomerSignupView.create()
│
├── CustomerRegistrationSerializer.is_valid()
│ ├── Valida password == password_confirm
│ └── Valida password (Django validators)
│
├── CustomerRegistrationSerializer.save()
│ └── Customer.objects.create_user()
│ ├── Normaliza email
│ ├── Hash da senha (set_password)
│ └── Salva no banco
│
├── RefreshToken.for_user(user)
│ └── Gera par de tokens JWT
│
└── Response 201 { user, tokens, message }
Request POST /api/v1/customers/login/
│
▼
CustomerLoginView.post()
│
├── CustomerLoginSerializer.is_valid()
│
├── authenticate(identifier, password)
│ │
│ └── EmailOrUsernameModelBackend
│ ├── Busca por email OU username
│ ├── Verifica senha
│ └── Retorna user ou None
│
├── [Se user válido e ativo]
│ ├── RefreshToken.for_user(user)
│ └── Response 200 { user, tokens }
│
└── [Se inválido]
└── Response 401 { error }
Request POST /api/v1/customers/logout/
│
├── [JWT Authentication middleware]
│ └── Valida access token no header
│
▼
CustomerLogoutView.post()
│
├── Extrai refresh token do body
│
├── RefreshToken(refresh_token)
│
├── token.blacklist()
│ └── Adiciona token à tabela OutstandingToken/BlacklistedToken
│
└── Response 205 { message }
| Evento | Ação | Descrição |
|---|---|---|
| Login | UPDATE_LAST_LOGIN=True |
Atualiza last_login do usuário |
| Token Refresh | BLACKLIST_AFTER_ROTATION=True |
Token antigo vai para blacklist |
| Logout | token.blacklist() |
Refresh token vai para blacklist |
Observação: Não foram identificados signals (
post_save,pre_save), tarefas assíncronas, envio de emails ou webhooks no código atual.
Arquivo principal: core/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include('customers.urls')),
path('api/schema/', SpectacularAPIView.as_view()),
path('api/swagger-ui/', SpectacularSwaggerView.as_view()),
path('api/redoc/', SpectacularRedocView.as_view()),
]Arquivo do app: customers/urls.py
app_name = 'customers'
urlpatterns = [
path('customers/token/refresh/', ...),
path('customers/', ...),
path('customers/signup/', ...),
path('customers/login/', ...),
path('customers/logout/', ...),
path('customers/<uuid:pk>/', ...),
path('customers/profile/', ...),
]- Padrão: URL Path versioning (
/api/v1/) - Versão Atual: v1
- Inferido: Não há implementação de múltiplas versões no momento
| URL | Método(s) | Name | View |
|---|---|---|---|
/admin/ |
ALL | - | Django Admin |
/api/v1/customers/ |
GET, POST | customer_create_list |
CustomerCreateListView |
/api/v1/customers/signup/ |
POST | customer_signup |
CustomerSignupView |
/api/v1/customers/login/ |
POST | customer_login |
CustomerLoginView |
/api/v1/customers/logout/ |
POST | customer_logout |
CustomerLogoutView |
/api/v1/customers/profile/ |
GET, PUT, PATCH, DELETE | customer_profile |
CustomerProfileView |
/api/v1/customers/<uuid:pk>/ |
GET, PUT, PATCH, DELETE | customer_retrieve_update_destroy |
CustomerRetrieveUpdateDestroyView |
/api/v1/customers/token/refresh/ |
POST | customer_token_refresh |
JWTTokenRefreshView |
/api/schema/ |
GET | schema |
SpectacularAPIView |
/api/swagger-ui/ |
GET | swagger-ui |
SpectacularSwaggerView |
/api/redoc/ |
GET | redoc |
SpectacularRedocView |
Nota: Routers do DRF (DefaultRouter) não são utilizados. As rotas são definidas manualmente.
| Tipo | Limite | Descrição |
|---|---|---|
AnonRateThrottle |
10/min | Requisições de usuários não autenticados |
UserRateThrottle |
60/min | Requisições de usuários autenticados |
| Middleware | Função |
|---|---|
CorsMiddleware |
Habilita CORS para requisições cross-origin |
SecurityMiddleware |
Headers de segurança |
SessionMiddleware |
Sessões (para Django Admin) |
CsrfViewMiddleware |
Proteção CSRF (desabilitado para API via DRF) |
AuthenticationMiddleware |
Autenticação de sessão do Django |
| Configuração | Valor | Descrição |
|---|---|---|
CORS_ALLOW_CREDENTIALS |
True |
Permite cookies em requisições CORS |
CORS_ALLOW_ALL_ORIGINS |
True (se DEBUG) |
Permite todas as origens em desenvolvimento |
CORS_ALLOWED_ORIGINS |
via env CORS_ALLOWED_ORIGINS |
Lista de origens permitidas em produção |
- Classe:
PageNumberPagination - Tamanho da página: 10 itens
- Parâmetro:
?page=N
- Parser padrão:
JSONParser(apenas JSON aceito) - Renderer padrão:
JSONRenderer(apenas JSON retornado)
| Item | Observação |
|---|---|
| Hardcoded no settings.py - NÃO usar em produção | |
| Modo de depuração ativo - desabilitar em produção | |
| Permite qualquer host - restringir em produção | |
| Banco de desenvolvimento - usar PostgreSQL em produção | |
| 📝 Testes | Arquivo customers/tests.py está vazio |
| 📝 Soft Delete | Não implementado - delete é permanente |
| Não há envio de emails (confirmação, recuperação de senha) | |
| 📝 Password Reset | Não implementado |
| 📝 Email Verification | Não implementado |
O modelo Customer está registrado no Django Admin com configuração personalizada:
- Campos de busca: email, username, name
- Ordenação: created_at
- Campos exibidos: email, username, name, id, is_active, is_staff, created_at
- Campos readonly: created_at
SPECTACULAR_SETTINGS = {
"TITLE": "Signup, Login and Logout API",
"DESCRIPTION": "API for managing customers with signup, login, and logout functionality.",
"VERSION": "1.0.0",
"SECURITY": [{"BearerAuth": []}],
}- Swagger UI disponível em
/api/swagger-ui/ - ReDoc disponível em
/api/redoc/ - Schema JSON em
/api/schema/
| Endpoint | Método | Auth | Descrição |
|---|---|---|---|
/api/v1/customers/signup/ |
POST | ❌ | Registro de novo usuário |
/api/v1/customers/login/ |
POST | ❌ | Login (email ou username) |
/api/v1/customers/logout/ |
POST | ✅ | Logout (blacklist token) |
/api/v1/customers/token/refresh/ |
POST | ❌ | Renovar tokens |
/api/v1/customers/profile/ |
GET/PUT/PATCH/DELETE | ✅ | Perfil do usuário logado |
/api/v1/customers/ |
GET/POST | ✅ Admin | Listar/criar clientes |
/api/v1/customers/<uuid>/ |
GET/PUT/PATCH/DELETE | ✅ Self/Admin | CRUD cliente específico |
Documentação gerada em: 21 de Janeiro de 2026
Baseada exclusivamente no código-fonte do projeto.