Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ bin/run-ci

This document outlines the available API endpoints for the Enarm API application.

Detailed reference (headers, status codes, examples per endpoint):

- `docs/API_REFERENCE.md`

### Health Check

* **GET /up**
Expand Down
10 changes: 7 additions & 3 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
class ApplicationController < ActionController::API
include SetCurrentRequestDetails

rescue_from ActionController::ParameterMissing do |exception|
render json: { error: exception.message }, status: :bad_request
end

def authenticate_user!
token = decoded_token
user_id = token[:user_id] || token[:player_id]
@current_user = User.find_by(id: user_id) if user_id
render json: { error: "No autorizado" }, status: :unauthorized unless @current_user
Current.user = nil
Current.user = User.find_by(id: user_id) if user_id
@current_user = Current.user # Compatibilidad con controladores existentes
render json: { error: "No autorizado" }, status: :unauthorized unless Current.user
end

# Alias para compatibilidad con el frontend si es necesario
Expand All @@ -20,7 +24,7 @@ def authenticate_admin!
authenticate_user!
return if performed?

unless @current_user.admin?
unless Current.user.admin?
render json: { error: "Acceso restringido a administradores" }, status: :forbidden
end
end
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/categories_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class CategoriesController < ApplicationController
before_action :authenticate_admin!, except: :index
before_action :authenticate_admin!, except: [ :index, :show ]
before_action :set_category, only: %i[ update show ]

# GET /categories
Expand Down
5 changes: 5 additions & 0 deletions app/controllers/clinical_cases_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ def index
if params[:category_id]
@cases = @cases.where(category_id: params[:category_id])
end
if params[:q].present?
query = "%#{params[:q].to_s.strip.downcase}%"
@cases = @cases.where("LOWER(name) LIKE ?", query)
end
render json: { current_page: @cases.current_page, per_page: @cases.per_page, total_entries: @cases.total_entries, clinical_cases: @cases }
end

Expand Down Expand Up @@ -57,6 +61,7 @@ def clinical_case_params
:description,
:category_id,
:status,
:image,
questions_attributes: [
:id,
:_destroy,
Expand Down
15 changes: 15 additions & 0 deletions app/controllers/concerns/set_current_request_details.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module SetCurrentRequestDetails
extend ActiveSupport::Concern

included do
before_action :set_current_request_details
end

private

def set_current_request_details
Current.request_id = request.request_id
Current.user_agent = request.user_agent
Current.ip_address = request.ip
end
end
5 changes: 5 additions & 0 deletions app/controllers/flashcards_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ def index
render json: @flashcards
end

# GET /flashcards/:id
def show
render json: @flashcard
end

# GET /flashcards/due
def due
@due_cards = @current_user.user_flashcards.due.includes(:flashcard)
Expand Down
10 changes: 5 additions & 5 deletions app/controllers/messages_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ class MessagesController < ApplicationController
# List recent conversations
def index
# This is a bit complex for a simple query, but let's do a basic version
sent_ids = @current_user.sent_messages.select(:receiver_id).distinct.pluck(:receiver_id)
received_ids = @current_user.received_messages.select(:sender_id).distinct.pluck(:sender_id)
sent_ids = Current.user.sent_messages.select(:receiver_id).distinct.pluck(:receiver_id)
received_ids = Current.user.received_messages.select(:sender_id).distinct.pluck(:sender_id)
user_ids = (sent_ids + received_ids).uniq

@users = User.where(id: user_ids)
Expand All @@ -16,15 +16,15 @@ def index
# GET /messages/:user_id
# History with a specific user
def show
@messages = Message.between(@current_user.id, params[:id]).order(created_at: :asc)
@messages = Message.between(Current.user.id, params[:id]).order(created_at: :asc)
# Mark as read
@messages.where(receiver_id: @current_user.id, read_at: nil).update_all(read_at: Time.current)
@messages.where(receiver_id: Current.user.id, read_at: nil).update_all(read_at: Time.current)
render json: @messages
end

# POST /messages
def create
@message = @current_user.sent_messages.build(message_params)
@message = Current.user.sent_messages.build(message_params)
if @message.save
render json: @message, status: :created
else
Expand Down
5 changes: 3 additions & 2 deletions app/controllers/questions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ def index
end
else
# Consider pagination for listing all questions
@questions = Question.all
@questions = Question.all.order(id: :desc)
end
render json: @questions, include: [ :answers, :category, :clinical_case ]
@questions = @questions.paginate(page: params[:page]).includes(:answers, :category, :clinical_case)
render json: { current_page: @questions.current_page, per_page: @questions.per_page, total_entries: @questions.total_entries, questions: @questions }, include: [ :answers, :category, :clinical_case ]
end

# GET /questions/:id
Expand Down
50 changes: 33 additions & 17 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,24 +74,12 @@ def contributions

# POST /google_login
def google_login
google_id = params[:google_id]
email = params[:email]
name = params[:name]

user = User.find_by(google_id: google_id) || User.find_by(email: email)
social_login(provider: :google, provider_id_key: :google_id)
end

if user
user.update(google_id: google_id) if user.google_id.blank?
render json: user_json(user), status: :ok
else
user = User.new(email: email, name: name, google_id: google_id, role: :player)
user.password = SecureRandom.hex(10)
if user.save
render json: user_json(user), status: :created
else
render json: user.errors, status: :unprocessable_entity
end
end
# POST /facebook_login
def facebook_login
social_login(provider: :facebook, provider_id_key: :facebook_id)
end

private
Expand Down Expand Up @@ -120,4 +108,32 @@ def user_json(user)
token: token
}
end

def social_login(provider:, provider_id_key:)
provider_id = params[provider_id_key]
email = params[:email]
name = params[:name]

user = User.find_by(provider_id_key => provider_id) || User.find_by(email: email)

if user
user.update(provider_id_key => provider_id) if user[provider_id_key].blank? && provider_id.present?
render json: user_json(user), status: :ok
else
user_attributes = {
email: email,
name: name,
role: :player,
provider_id_key => provider_id
}
user = User.new(user_attributes)
user.password = SecureRandom.hex(10)

if user.save
render json: user_json(user), status: :created
else
render json: user.errors, status: :unprocessable_entity
end
end
end
end
18 changes: 18 additions & 0 deletions app/models/clinical_case.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
class ClinicalCase < ApplicationRecord
MAX_IMAGE_SIZE = 5.megabytes
ALLOWED_IMAGE_TYPES = [ "image/png", "image/jpeg" ].freeze

belongs_to :category
has_one_attached :image
has_many :questions, dependent: :destroy, inverse_of: :clinical_case
Expand All @@ -8,4 +11,19 @@ class ClinicalCase < ApplicationRecord
enum :status, { pending: 0, published: 1, rejected: 2 }

validates :name, presence: true
validate :image_must_be_valid

private

def image_must_be_valid
return unless image.attached?

unless ALLOWED_IMAGE_TYPES.include?(image.content_type)
errors.add(:image, "debe ser PNG o JPG")
end

if image.blob.byte_size > MAX_IMAGE_SIZE
errors.add(:image, "no debe superar 5 MB")
end
end
end
3 changes: 3 additions & 0 deletions app/models/current.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Current < ActiveSupport::CurrentAttributes
attribute :user, :request_id, :user_agent, :ip_address
end
13 changes: 5 additions & 8 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
collection do
post "login"
post "google_login"
post "facebook_login"
get "me/stats", to: "users#stats"
get "me/contributions", to: "users#contributions"
end
Expand All @@ -15,6 +16,7 @@
collection do
post "login", to: "users#login"
post "google_login", to: "users#google_login"
post "facebook_login", to: "users#facebook_login"
end
resources :achievements, only: [ :index ], controller: "users/achievements"
end
Expand All @@ -28,14 +30,9 @@
resources :achievements, only: [ :index, :create, :update, :destroy ]
resources :user_exams, only: [ :index, :show, :create, :update ]

resources :flashcards, only: [ :index, :show ] do
collection do
get "due"
end
member do
post "review"
end
end
get "flashcards/due", to: "flashcards#due"
post "flashcards/:id/review", to: "flashcards#review"
resources :flashcards, only: [ :index, :show ]

resources :specialists, only: [ :index, :show ]
resources :messages, only: [ :index, :show, :create ]
Expand Down
Loading