# frozen_string_literal: true module Api module V1 # Obtiene una cookie válida por el tiempo especificado por el # sitio. # # Aunque visitemos el sitio varias veces enviando la cookie # anterior, la cookie se renueva. class InvitadesController < BaseController # Cookie para el formulario de contacto # # Usamos where porque no nos importa encontrar el resultado, todes # les visitantes reciben lo mismo, pero algunes no reciben cookie. def contact_cookie contact = Site.where(name: site_id, contact: true) .pluck(:contact) .first set_cookie if contact render file: Rails.root.join('public', '1x1.png'), content_type: 'image/png', layout: false end # Cookie para colaboraciones anónimas def cookie # XXX: Prestar atención a que estas acciones sean lo más rápidas # y utilicen la menor cantidad posible de recursos, porque son # un vector de DDOS. anon = Site.where(name: site_id, colaboracion_anonima: true) .pluck(:colaboracion_anonima) .first set_cookie if anon render file: Rails.root.join('public', '1x1.png'), content_type: 'image/png', layout: false end private # Genera el Origin correcto a partir de la URL del sitio. # # En desarrollo devuelve el Origin enviado. # # @return [String] def return_origin Rails.env.production? ? Site.find_by(name: site_id).url : origin end # La cookie no es accesible a través de JS y todo su contenido # está cifrado para que no lo modifiquen les visitantes # # Enviamos un token de protección CSRF def set_cookie # TODO: Volver configurable por sitio expires = ENV.fetch('COOKIE_DURATION', '30').to_i.minutes headers['Access-Control-Allow-Origin'] = return_origin headers['Access-Control-Allow-Credentials'] = true headers['Vary'] = 'Origin' headers['Cache-Control'] = "private, max-age=#{expires}, stale-while-revalidate=#{expires}" cookies.encrypted[site_id] = { httponly: true, secure: !Rails.env.test?, expires: expires, same_site: :strict, value: { csrf: form_authenticity_token, expires: (Time.now + expires).to_i } } end end end end