From e9a5e734fff0574e96340bcd54cf6bb9a696ffa6 Mon Sep 17 00:00:00 2001 From: Rodribm10 Date: Mon, 13 Apr 2026 23:49:11 -0300 Subject: [PATCH] feat: rota + controller esqueleto PublicReservations com token auth --- .../captain/public_reservations_controller.rb | 31 +++++++++++++++++++ config/routes.rb | 8 +++++ .../public_reservations_controller_spec.rb | 20 +++++++----- 3 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 app/controllers/public/api/v1/captain/public_reservations_controller.rb diff --git a/app/controllers/public/api/v1/captain/public_reservations_controller.rb b/app/controllers/public/api/v1/captain/public_reservations_controller.rb new file mode 100644 index 000000000..6b707b673 --- /dev/null +++ b/app/controllers/public/api/v1/captain/public_reservations_controller.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +# Endpoint público para criação de reservas via React app externo (Reserva 1001). +# Autenticado por token estático via header X-Reserva-Token. +class Public::Api::V1::Captain::PublicReservationsController < ActionController::API + before_action :authenticate_reserva_token! + + def create + render json: { error: 'not_implemented' }, status: :not_implemented + end + + def status + render json: { error: 'not_implemented' }, status: :not_implemented + end + + private + + def authenticate_reserva_token! + expected = ENV.fetch('RESERVA_1001_API_TOKEN', nil) + provided = request.headers['X-Reserva-Token'] + + if expected.blank? + Rails.logger.error('[PublicReservations] RESERVA_1001_API_TOKEN not configured') + render json: { error: 'service_unavailable' }, status: :service_unavailable and return + end + + return if provided.present? && ActiveSupport::SecurityUtils.secure_compare(provided, expected) + + render json: { error: 'unauthorized' }, status: :unauthorized + end +end diff --git a/config/routes.rb b/config/routes.rb index 6d1d345b0..5c4d57ccd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -692,6 +692,14 @@ Rails.application.routes.draw do # Página pública de pagamento PIX (link curto gerado via SGID pela IA) get '/r/:token', to: 'public/api/v1/captain/payments#show', as: :short_payment_link + # API pública de reservas (Reserva 1001) + post '/public/api/v1/captain/public_reservations', + to: 'public/api/v1/captain/public_reservations#create', + defaults: { format: 'json' } + get '/public/api/v1/captain/public_reservations/:id/status', + to: 'public/api/v1/captain/public_reservations#status', + defaults: { format: 'json' } + # Webhook do Banco Inter para notificações de PIX pago post '/api/v1/captain/webhooks/inter_pix', to: 'public/api/v1/captain/inter_webhooks#create', diff --git a/spec/enterprise/controllers/public/api/v1/captain/public_reservations_controller_spec.rb b/spec/enterprise/controllers/public/api/v1/captain/public_reservations_controller_spec.rb index 50207725c..d76004571 100644 --- a/spec/enterprise/controllers/public/api/v1/captain/public_reservations_controller_spec.rb +++ b/spec/enterprise/controllers/public/api/v1/captain/public_reservations_controller_spec.rb @@ -6,7 +6,12 @@ RSpec.describe 'Public Captain Reservations API', type: :request do let(:valid_token) { 'test-token-abc' } let(:account) { create(:account) } let(:inbox) { create(:inbox, account: account) } - let(:unit) { create(:captain_unit, account: account, inbox: inbox) } + let(:brand) { create(:captain_brand, account: account) } + let(:unit) do + Captain::Unit.create!(account: account, brand: brand, inbox_id: inbox.id, + name: 'Hotel Teste', inter_pix_key: 'pix@test.com', + inter_account_number: '12345678') + end before do allow(ENV).to receive(:fetch).and_call_original @@ -39,9 +44,13 @@ RSpec.describe 'Public Captain Reservations API', type: :request do context 'with valid token and valid payload' do let(:unit) do - create(:captain_unit, account: account, inbox: inbox, - inter_client_id: 'fake-id', - inter_pix_key: 'fake-key@test.com') + Captain::Unit.create!( + account: account, brand: brand, inbox_id: inbox.id, + name: 'Hotel Teste Com Inter', inter_pix_key: 'fake-key@test.com', + inter_account_number: '1234567', inter_client_id: 'fake-id', + inter_client_secret: 'fake-secret', inter_cert_content: 'FAKE-CERT', + inter_key_content: 'FAKE-KEY' + ) end let(:valid_payload) do @@ -108,11 +117,8 @@ RSpec.describe 'Public Captain Reservations API', type: :request do end describe 'GET /public/api/v1/captain/public_reservations/:id/status' do - let(:account) { create(:account) } - let(:inbox) { create(:inbox, account: account) } let(:contact) { create(:contact, account: account) } let(:contact_inbox) { create(:contact_inbox, inbox: inbox, contact: contact) } - let(:unit) { create(:captain_unit, account: account, inbox: inbox) } let(:reservation) do Captain::Reservation.create!( account: account, inbox: inbox, contact: contact, contact_inbox: contact_inbox,