mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-15 05:21:42 +00:00
100 lines
3.2 KiB
Ruby
100 lines
3.2 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
module Api
|
||
|
module V1
|
||
|
class PostsController < BaseController
|
||
|
# Ver doc/anonymous.md
|
||
|
skip_forgery_protection
|
||
|
# Protecciones antes de procesar los datos
|
||
|
before_action :cookie_is_valid?, unless: :performed?
|
||
|
before_action :valid_authenticity_token_in_cookie?, unless: :performed?
|
||
|
before_action :site_exists_and_is_anonymous?, unless: :performed?
|
||
|
before_action :site_is_origin?, unless: :performed?
|
||
|
|
||
|
# Crea un artículo solo si el sitio es invitado, pero antes
|
||
|
# tenemos que averiguar varias cosas:
|
||
|
#
|
||
|
# * la cookie sea válida
|
||
|
# * el token anti CSRF es válido
|
||
|
# * el sitio existe
|
||
|
# * el sitio admite invitades
|
||
|
# * el origen de la petición no es el sitio
|
||
|
#
|
||
|
# TODO: Definir cuáles van a ser las respuestas para cada error
|
||
|
# o si simplemente vamos a aceptarlas sin dar feedback.
|
||
|
def create
|
||
|
# No procesar nada más si ya se aplicaron todos los filtros
|
||
|
return if performed?
|
||
|
|
||
|
# Redirigir a la URL de agradecimiento
|
||
|
redirect_to params[:redirect_to]
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
# Comprueba que no se haya reutilizado una cookie vencida
|
||
|
#
|
||
|
# XXX: Si el navegador envió una cookie vencida es porque la está
|
||
|
# reutilizando, probablemente de forma maliciosa?
|
||
|
def cookie_is_valid?
|
||
|
unless cookies.encrypted[site_id] &&
|
||
|
cookies.encrypted[site_id]['expires'] > Time.now.to_i
|
||
|
render html: nil, status: :no_content
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# Queremos comprobar que la cookie corresponda con la sesión. La
|
||
|
# cookie puede haber vencido, así que es uno de los chequeos más
|
||
|
# simples que hacemos.
|
||
|
#
|
||
|
# TODO: Pensar una forma de redirigir al origen sin vaciar el
|
||
|
# formulario para que le usuarie recargue la cookie.
|
||
|
def valid_authenticity_token_in_cookie?
|
||
|
unless valid_authenticity_token? session, cookies.encrypted[site_id]
|
||
|
render html: nil, status: :no_content
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# El sitio existe y soporta colaboracion anónima
|
||
|
#
|
||
|
# Pedimos el sitio aunque no lo necesitemos para que la consulta
|
||
|
# entre en la caché
|
||
|
def site_exists_and_is_anonymous?
|
||
|
_, anon = site_anon_pair
|
||
|
|
||
|
render html: nil, status: :no_content
|
||
|
end
|
||
|
|
||
|
# El navegador envía la URL del sitio en el encabezado Origin,
|
||
|
# queremos comprobar que los datos son enviados desde ahí.
|
||
|
def site_is_origin?
|
||
|
site, = site_anon_pair
|
||
|
|
||
|
unless "https://#{site}" === request.headers['Origin']
|
||
|
render html: nil, status: :no_content
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# Solo soy un atajo
|
||
|
def site_id
|
||
|
@site_id ||= params[:site_id]
|
||
|
end
|
||
|
|
||
|
# La consulta más barata que podemos hacer y la reutilizamos para
|
||
|
# que esté en la caché
|
||
|
def site_anon_pair
|
||
|
Site.where(name: site_id, colaboracion_anonima: true)
|
||
|
.pluck(:name, :colaboracion_anonima)
|
||
|
.first
|
||
|
end
|
||
|
|
||
|
# Instancia el sitio completo
|
||
|
#
|
||
|
# XXX: Solo usar después de comprobar que el sitio existe!
|
||
|
def site
|
||
|
@site ||= Site.find_by(name: site_id)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|