API REST em Ruby on Rails para autenticação, perfil de usuário e acompanhamento de medidas corporais do Brocolito.
- Ruby 4.0.1
- Rails 8.1
- PostgreSQL
- Puma
- JWT
- bcrypt
- rack-cors
- RuboCop Rails Omakase
- Docker: empacotamento da aplicação em containers.
- Kamal: deploy de aplicações Rails usando Docker.
- Solid Queue: processamento de jobs em background usando banco de dados.
- Solid Cache: cache usando banco de dados.
- Solid Cable: Action Cable usando banco de dados.
- Brakeman: análise estática de segurança para aplicações Rails.
- Bundler Audit: auditoria de vulnerabilidades conhecidas nas gems.
- Cadastro e login de usuários
- Autenticação via JWT
- Perfil do usuário autenticado
- Objetivo do usuário: perder peso ou ganhar peso
- Atualização de senha com validação da senha atual
- Controle de acesso para administradores
- CRUD de medidas corporais
- Comparativo entre medições do usuário autenticado
- Ruby 4.0.1
- Bundler
- PostgreSQL rodando localmente
O banco de desenvolvimento usa a configuração padrão do PostgreSQL local:
database: brocolito_api_development
Se o seu PostgreSQL exigir usuário, senha, host ou porta, ajuste config/database.yml ou use variáveis compatíveis com Rails/PostgreSQL no seu ambiente.
Instale as dependências:
bundle installCrie e prepare o banco:
bin/rails db:setupSe o banco já existir e você só precisa aplicar novas migrations:
bin/rails db:migrateInicie a API:
bin/rails serverURL local:
http://localhost:3000
Health check:
GET /upO projeto possui seeds com usuários e medições para desenvolvimento:
bin/rails db:seedCredenciais disponíveis:
admin@exemplo.com / 123123
bruno@exemplo.com / 123123
julia@exemplo.com / 123123
Faça login:
POST /login{
"authentication": {
"email": "admin@exemplo.com",
"password": "123123"
}
}Resposta:
{
"token": "jwt_token",
"user": {
"id": 1,
"name": "Admin",
"email": "admin@exemplo.com",
"weight_goal": "lose_weight"
}
}Use o token nas rotas protegidas:
Authorization: Bearer jwt_token| Valor | Descrição |
|---|---|
lose_weight |
Usuário quer perder peso |
gain_weight |
Usuário quer ganhar peso |
| Método | Rota | Acesso | Descrição |
|---|---|---|---|
GET |
/up |
Público | Health check da aplicação |
| Método | Rota | Acesso | Descrição |
|---|---|---|---|
POST |
/login |
Público | Autentica usuário e retorna JWT |
| Método | Rota | Acesso | Descrição |
|---|---|---|---|
POST |
/users |
Público | Cria usuário |
GET |
/users |
Admin | Lista usuários |
GET |
/users/:id |
Admin | Exibe usuário |
PATCH |
/users/:id |
Admin | Atualiza usuário |
DELETE |
/users/:id |
Admin ou dono | Remove usuário |
GET |
/users/me |
Autenticado | Exibe usuário autenticado |
PATCH |
/users/me |
Autenticado | Atualiza perfil e objetivo |
PATCH |
/users/me/password |
Autenticado | Atualiza senha |
| Método | Rota | Acesso | Descrição |
|---|---|---|---|
GET |
/body_measurements |
Autenticado | Lista medições do usuário |
POST |
/body_measurements |
Autenticado | Cria medição |
GET |
/body_measurements/:id |
Autenticado | Exibe medição do usuário |
PATCH |
/body_measurements/:id |
Autenticado | Atualiza medição |
DELETE |
/body_measurements/:id |
Autenticado | Remove medição |
GET |
/body_measurements/compare |
Autenticado | Compara primeira e última medição com valor disponível por campo |
POST /users{
"user": {
"name": "Bruno",
"email": "bruno@exemplo.com",
"password": "123123",
"weight_goal": "lose_weight"
}
}PATCH /users/me
Authorization: Bearer jwt_token{
"user": {
"name": "Bruno Netto",
"email": "bruno@exemplo.com",
"weight_goal": "gain_weight"
}
}PATCH /users/me/password
Authorization: Bearer jwt_token{
"user": {
"current_password": "123123",
"password": "nova_senha"
}
}POST /body_measurements
Authorization: Bearer jwt_token{
"body_measurement": {
"weight_kg": 84.2,
"height_cm": 178,
"waist_circumference_cm": 90,
"abdomen_circumference_cm": 92,
"chest_circumference_cm": 102
}
}Campos aceitos em body_measurement:
weight_kg
height_cm
neck_circumference_cm
chest_circumference_cm
shoulder_circumference_cm
waist_circumference_cm
hip_circumference_cm
abdomen_circumference_cm
relaxed_arm_circumference_cm
flexed_arm_circumference_cm
forearm_circumference_cm
thigh_circumference_cm
calf_circumference_cm
weight_kg e height_cm são obrigatórios. As demais medidas são opcionais.
GET /body_measurements/compare
Authorization: Bearer jwt_tokenResposta:
{
"weight_change_kg": -3.5,
"neck_circumference_change_cm": null,
"chest_circumference_change_cm": 1.0,
"shoulder_circumference_change_cm": null,
"waist_circumference_change_cm": -4.0,
"hip_circumference_change_cm": null,
"abdomen_circumference_change_cm": -5.0,
"relaxed_arm_circumference_change_cm": null,
"flexed_arm_circumference_change_cm": null,
"forearm_circumference_change_cm": null,
"thigh_circumference_change_cm": null,
"calf_circumference_change_cm": null
}Cada campo compara a primeira e a última medição que possuem valor para aquele campo.
RuboCop:
bin/rubocopTestes:
bin/rails testPipeline local, quando disponível:
bin/ciFerramentas auxiliares:
bin/brakeman
bin/bundler-auditEm produção, configure:
DATABASE_URL
RAILS_MASTER_KEY
O projeto inclui arquivos de Docker/Kamal gerados pelo template Rails.
password_digestnão deve ser retornado nas respostas.- Rotas protegidas exigem JWT no header
Authorization. - Rotas administrativas exigem usuário com
admin: true. - A troca de senha exige a senha atual.