# frozen_string_literal: true module Api module V1 # API para formulario de contacto class ContactController < BaseController # Permitir conexiones desde varios sitios, estamos chequeando más # adelante. skip_forgery_protection # Aplicar algunos chequeos básicos. Deberíamos registrar de # alguna forma los errores pero tampoco queremos que nos usen # recursos. # # TODO: Agregar los mismos chequeos que en PostsController before_action :site_exists?, unless: :performed? before_action :site_is_origin?, unless: :performed? before_action :from_is_address?, unless: :performed? before_action :gave_consent?, unless: :performed? # Recibe un mensaje a través del formulario de contacto y lo envía # a les usuaries del sitio. # # Tenemos que verificar que el sitio exista y que algunos campos # estén llenos para detener spambots o DDOS. También nos vamos a # estar apoyando en la limitación de peticiones en el servidor web. def receive # No hacer nada si no se pasaron los chequeos return if performed? # Si todo salió bien, enviar los correos y redirigir al sitio. # El sitio nos dice a dónde tenemos que ir. ContactJob.perform_async site_id: site.id, **contact_params.to_h.symbolize_keys redirect_to contact_params[:redirect] || site.url end private # Comprueba que el sitio existe # # TODO: Responder con una zip bomb! def site_exists? render html: body(:site_exists), status: status unless site end # Comprueba que el mensaje vino fue enviado desde el sitio def site_is_origin? return if origin.to_s == site.url render html: body(:site_is_origin), status: status end # Detecta si la dirección de contacto es válida. Además es # opcional. def from_is_address? return unless contact_params[:from] return if EmailAddress.valid? contact_params[:from] render html: body(:from_is_address), status: status end # No aceptar nada si no dió su consentimiento def gave_consent? return if contact_params[:gdpr].present? render html: body(:gave_consent), status: status end # Realiza la inversa de Site#hostname def site_id @site_id ||= if params[:site_id].end_with? Site.domain params[:site_id].gsub(/\.#{Site.domain}\z/, '') else "#{params[:site_id]}." end end # Encuentra el sitio def site @site ||= Site.find_by(name: site_id) end # Parámetros limpios def contact_params @contact_params ||= params.permit(:gdpr, :name, :pronouns, :from, :contact, :body, :redirect) end # Para poder testear, enviamos un mensaje en el cuerpo de la # respuesta # # @param [Any] el mensaje def body(message) return message.to_s if Rails.env.test? end # No queremos informar nada a los spammers, pero en testeo # queremos saber por qué. :no_content oculta el cuerpo. def status Rails.env.test? ? :unprocessable_entity : :no_content end end end end