diff --git a/Gemfile b/Gemfile index 00b556d0..61c8de3c 100644 --- a/Gemfile +++ b/Gemfile @@ -90,6 +90,7 @@ gem 'prometheus_exporter' gem 'fast_jsonparser' gem 'down' gem 'sourcemap' +gem 'rack-cors' group :themes do gem 'adhesiones-jekyll-theme', require: false diff --git a/Gemfile.lock b/Gemfile.lock index 0ebf1842..f6987aea 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -337,6 +337,8 @@ GEM pundit (2.1.0) activesupport (>= 3.0.0) rack (2.2.3) + rack-cors (1.1.1) + rack (>= 2.0.0) rack-mini-profiler (2.1.0) rack (>= 1.2.0) rack-proxy (0.6.5) @@ -616,6 +618,7 @@ DEPENDENCIES pry puma pundit + rack-cors rack-mini-profiler radios-comunitarias-jekyll-theme rails (~> 6) diff --git a/config/initializers/cors.rb b/config/initializers/cors.rb new file mode 100644 index 00000000..7117dbb3 --- /dev/null +++ b/config/initializers/cors.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +# CORS +# +# @see {https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS} +# @see {https://github.com/cyu/rack-cors#origin} +Rails.application.config.middleware.insert_before 0, Rack::Cors do + allow do + # Queremos obtener un dominio válido y no permitir ningún otro + # origen. Como los sitios pueden tener muchos orígenes, necesitamos + # una forma de encontrarlos por su URL. + # + # El problema sería que otros sitios con JS malicioso hagan pedidos + # a nuestra API desde otros sitios infectados. + # + # XXX: La primera parte del dominio tiene que coincidir con el + # nombre del sitio. + # + # XXX: Al terminar de entender esto nos pasó que el servidor recibe + # la petición de todas maneras, con lo que no estamos previniendo + # que nos hablen, sino que lean información. + # + # TODO: Limitar el acceso desde Nginx también. + # TODO: Poder consultar por sitios por todas sus URLs posibles. + origins do |source, _| + # Cacheamos la respuesta para no tener que volver a procesarla + # cada vez. + Rails.cache.fetch(source, expires_in: 1.hour) do + if (name = URI(source)&.host&.split('.', 2)&.first).present? + Site.where(name: name).pluck(:name).first.present? + else + false + end + rescue URI::Error + false + end + end + + resource '*', headers: :any, methods: %i[get post patch put] + end +end