encontrar la api independientemente del dominio que la aloje
This commit is contained in:
parent
73d1a7dcd8
commit
1d6cf11d52
8 changed files with 84 additions and 28 deletions
24
app/lib/constraints/api_subdomain.rb
Normal file
24
app/lib/constraints/api_subdomain.rb
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Constraints
|
||||||
|
# Detecta si el dominio comienzo con api. para servir la API.
|
||||||
|
#
|
||||||
|
# Hacemos esto porque Rails históricamente tiene un largo fijo de TLD
|
||||||
|
# y como alojamos dominios que pueden tener distintas terminaciones,
|
||||||
|
# no siempre detecta el subdominio como corresponde.
|
||||||
|
#
|
||||||
|
# Antes de llegar a este punto tenemos que tener un certificado
|
||||||
|
# correspondiente en el servidor web, que se expide dentro del
|
||||||
|
# servidor, por lo que sería la primera línea para detener
|
||||||
|
# api.cualquiercosa.que.no.existe.org si hiciera falta.
|
||||||
|
class ApiSubdomain
|
||||||
|
API_SUBDOMAIN = 'api.'
|
||||||
|
|
||||||
|
def initialize; end
|
||||||
|
|
||||||
|
# Sólo verificamos que el subdominio empiece con api.
|
||||||
|
def matches?(request)
|
||||||
|
request.hostname.start_with? API_SUBDOMAIN
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,7 +10,7 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
get 'markdown', to: 'application#markdown'
|
get 'markdown', to: 'application#markdown'
|
||||||
|
|
||||||
constraints subdomain: 'api' do
|
constraints(Constraints::ApiSubdomain.new) do
|
||||||
scope module: 'api' do
|
scope module: 'api' do
|
||||||
namespace :v1 do
|
namespace :v1 do
|
||||||
resources :csp_reports, only: %i[create]
|
resources :csp_reports, only: %i[create]
|
||||||
|
|
|
@ -13,6 +13,7 @@ module Api
|
||||||
@site.update contact: true, design: Design.find_by_gem('editorial-autogestiva-jekyll-theme')
|
@site.update contact: true, design: Design.find_by_gem('editorial-autogestiva-jekyll-theme')
|
||||||
@site.config.write
|
@site.config.write
|
||||||
@site.reload
|
@site.reload
|
||||||
|
@host = { host: "api.#{Site.domain}" }
|
||||||
end
|
end
|
||||||
|
|
||||||
teardown do
|
teardown do
|
||||||
|
@ -22,11 +23,11 @@ module Api
|
||||||
test 'el sitio tiene que existir' do
|
test 'el sitio tiene que existir' do
|
||||||
@site.destroy
|
@site.destroy
|
||||||
|
|
||||||
get v1_site_contact_cookie_url(@site.hostname)
|
get v1_site_contact_cookie_url(@site.hostname, **@host)
|
||||||
|
|
||||||
assert_not cookies[@site.name]
|
assert_not cookies[@site.name]
|
||||||
|
|
||||||
post v1_site_contact_url(site_id: @site.hostname, form: :contacto),
|
post v1_site_contact_url(site_id: @site.hostname, form: :contacto, **@host),
|
||||||
params: {
|
params: {
|
||||||
name: SecureRandom.hex,
|
name: SecureRandom.hex,
|
||||||
pronouns: SecureRandom.hex,
|
pronouns: SecureRandom.hex,
|
||||||
|
@ -41,8 +42,8 @@ module Api
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'hay que enviar desde el sitio principal' do
|
test 'hay que enviar desde el sitio principal' do
|
||||||
get v1_site_contact_cookie_url(@site.hostname)
|
get v1_site_contact_cookie_url(@site.hostname, **@host)
|
||||||
post v1_site_contact_url(site_id: @site.hostname, form: :contacto),
|
post v1_site_contact_url(site_id: @site.hostname, form: :contacto, **@host),
|
||||||
params: {
|
params: {
|
||||||
name: SecureRandom.hex,
|
name: SecureRandom.hex,
|
||||||
pronouns: SecureRandom.hex,
|
pronouns: SecureRandom.hex,
|
||||||
|
@ -57,8 +58,8 @@ module Api
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'hay que dar consentimiento' do
|
test 'hay que dar consentimiento' do
|
||||||
get v1_site_contact_cookie_url(@site.hostname)
|
get v1_site_contact_cookie_url(@site.hostname, **@host)
|
||||||
post v1_site_contact_url(site_id: @site.hostname, form: :contacto),
|
post v1_site_contact_url(site_id: @site.hostname, form: :contacto, **@host),
|
||||||
headers: {
|
headers: {
|
||||||
origin: @site.url
|
origin: @site.url
|
||||||
},
|
},
|
||||||
|
@ -77,14 +78,14 @@ module Api
|
||||||
test 'enviar un mensaje genera correos' do
|
test 'enviar un mensaje genera correos' do
|
||||||
ActionMailer::Base.deliveries.clear
|
ActionMailer::Base.deliveries.clear
|
||||||
|
|
||||||
redirect = @site.url + '?thanks'
|
redirect = "#{@site.url}?thanks"
|
||||||
|
|
||||||
10.times do
|
10.times do
|
||||||
create :rol, site: @site
|
create :rol, site: @site
|
||||||
end
|
end
|
||||||
|
|
||||||
get v1_site_contact_cookie_url(@site.hostname)
|
get v1_site_contact_cookie_url(@site.hostname, **@host)
|
||||||
post v1_site_contact_url(site_id: @site.hostname, form: :contacto),
|
post v1_site_contact_url(site_id: @site.hostname, form: :contacto, **@host),
|
||||||
headers: {
|
headers: {
|
||||||
Origin: @site.url
|
Origin: @site.url
|
||||||
},
|
},
|
||||||
|
@ -107,14 +108,14 @@ module Api
|
||||||
|
|
||||||
@site.update name: 'example.org.'
|
@site.update name: 'example.org.'
|
||||||
|
|
||||||
redirect = @site.url + '?thanks'
|
redirect = "#{@site.url}?thanks"
|
||||||
|
|
||||||
10.times do
|
10.times do
|
||||||
create :rol, site: @site
|
create :rol, site: @site
|
||||||
end
|
end
|
||||||
|
|
||||||
get v1_site_contact_cookie_url(@site.hostname)
|
get v1_site_contact_cookie_url(@site.hostname, **@host)
|
||||||
post v1_site_contact_url(site_id: @site.hostname, form: :contacto),
|
post v1_site_contact_url(site_id: @site.hostname, form: :contacto, **@host),
|
||||||
headers: { origin: @site.url },
|
headers: { origin: @site.url },
|
||||||
params: {
|
params: {
|
||||||
name: SecureRandom.hex,
|
name: SecureRandom.hex,
|
||||||
|
|
|
@ -9,10 +9,11 @@ module Api
|
||||||
skip
|
skip
|
||||||
|
|
||||||
post v1_csp_reports_url,
|
post v1_csp_reports_url,
|
||||||
|
host: "api.#{Site.domain}",
|
||||||
params: {
|
params: {
|
||||||
'csp-report': {
|
'csp-report': {
|
||||||
'document-uri': 'http://example.com/signup.html',
|
'document-uri': 'http://example.com/signup.html',
|
||||||
'referrer': '',
|
referrer: '',
|
||||||
'blocked-uri': 'http://example.com/css/style.css',
|
'blocked-uri': 'http://example.com/css/style.css',
|
||||||
'violated-directive': 'style-src cdn.example.com',
|
'violated-directive': 'style-src cdn.example.com',
|
||||||
'original-policy': "default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports"
|
'original-policy': "default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports"
|
||||||
|
|
|
@ -11,6 +11,7 @@ module Api
|
||||||
@usuarie = @rol.usuarie
|
@usuarie = @rol.usuarie
|
||||||
|
|
||||||
@site.update_attribute :colaboracion_anonima, true
|
@site.update_attribute :colaboracion_anonima, true
|
||||||
|
@host = { host: "api.#{Site.domain}" }
|
||||||
end
|
end
|
||||||
|
|
||||||
teardown do
|
teardown do
|
||||||
|
@ -18,7 +19,7 @@ module Api
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'primero hay que pedir una cookie' do
|
test 'primero hay que pedir una cookie' do
|
||||||
get v1_site_invitades_cookie_url(@site.hostname)
|
get v1_site_invitades_cookie_url(@site.hostname, **@host)
|
||||||
|
|
||||||
assert cookies[@site.name]
|
assert cookies[@site.name]
|
||||||
assert cookies['_sutty_session']
|
assert cookies['_sutty_session']
|
||||||
|
@ -27,7 +28,7 @@ module Api
|
||||||
test 'solo si el sitio existe' do
|
test 'solo si el sitio existe' do
|
||||||
site = SecureRandom.hex
|
site = SecureRandom.hex
|
||||||
|
|
||||||
get v1_site_invitades_cookie_url(site_id: site)
|
get v1_site_invitades_cookie_url(site_id: site, **@host)
|
||||||
|
|
||||||
assert_not cookies[site]
|
assert_not cookies[site]
|
||||||
assert_not cookies['_sutty_session']
|
assert_not cookies['_sutty_session']
|
||||||
|
@ -36,7 +37,7 @@ module Api
|
||||||
test 'solo si el sitio tiene colaboracion anonima' do
|
test 'solo si el sitio tiene colaboracion anonima' do
|
||||||
@site.update_attribute :colaboracion_anonima, false
|
@site.update_attribute :colaboracion_anonima, false
|
||||||
|
|
||||||
get v1_site_invitades_cookie_url(@site.hostname)
|
get v1_site_invitades_cookie_url(@site.hostname, **@host)
|
||||||
|
|
||||||
assert_not cookies[@site.name]
|
assert_not cookies[@site.name]
|
||||||
assert_not cookies['_sutty_session']
|
assert_not cookies['_sutty_session']
|
||||||
|
|
|
@ -18,7 +18,7 @@ module Api
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'no se pueden enviar sin cookie' do
|
test 'no se pueden enviar sin cookie' do
|
||||||
post v1_site_posts_url(@site.hostname, layout: :post), params: {
|
post v1_site_posts_url(@site.hostname, layout: :post, **@host), params: {
|
||||||
post: {
|
post: {
|
||||||
title: SecureRandom.hex,
|
title: SecureRandom.hex,
|
||||||
description: SecureRandom.hex
|
description: SecureRandom.hex
|
||||||
|
@ -36,15 +36,15 @@ module Api
|
||||||
test 'no se pueden enviar a sitios que no existen' do
|
test 'no se pueden enviar a sitios que no existen' do
|
||||||
site = SecureRandom.hex
|
site = SecureRandom.hex
|
||||||
|
|
||||||
get v1_site_invitades_cookie_url(site_id: site)
|
get v1_site_invitades_cookie_url(site_id: site, **@host)
|
||||||
|
|
||||||
assert_not cookies[site]
|
assert_not cookies[site]
|
||||||
|
|
||||||
get v1_site_invitades_cookie_url(@site.hostname)
|
get v1_site_invitades_cookie_url(@site.hostname, **@host)
|
||||||
|
|
||||||
assert cookies[@site.name]
|
assert cookies[@site.name]
|
||||||
|
|
||||||
post v1_site_posts_url(site_id: site, layout: :post),
|
post v1_site_posts_url(site_id: site, layout: :post, **@host),
|
||||||
headers: { cookies: cookies },
|
headers: { cookies: cookies },
|
||||||
params: {
|
params: {
|
||||||
consent: true,
|
consent: true,
|
||||||
|
@ -61,9 +61,9 @@ module Api
|
||||||
test 'antes hay que pedir una cookie' do
|
test 'antes hay que pedir una cookie' do
|
||||||
assert_equal 2, @site.posts.size
|
assert_equal 2, @site.posts.size
|
||||||
|
|
||||||
get v1_site_invitades_cookie_url(@site.hostname)
|
get v1_site_invitades_cookie_url(@site.hostname, **@host)
|
||||||
|
|
||||||
post v1_site_posts_url(@site.hostname, layout: :post),
|
post v1_site_posts_url(@site.hostname, layout: :post, **@host),
|
||||||
headers: {
|
headers: {
|
||||||
cookies: cookies,
|
cookies: cookies,
|
||||||
origin: @site.url
|
origin: @site.url
|
||||||
|
@ -88,9 +88,9 @@ module Api
|
||||||
title = SecureRandom.hex
|
title = SecureRandom.hex
|
||||||
order = (rand * 100).to_i
|
order = (rand * 100).to_i
|
||||||
|
|
||||||
get v1_site_invitades_cookie_url(@site.hostname)
|
get v1_site_invitades_cookie_url(@site.hostname, **@host)
|
||||||
|
|
||||||
post v1_site_posts_url(@site.hostname, layout: :post),
|
post v1_site_posts_url(@site.hostname, layout: :post, **@host),
|
||||||
headers: {
|
headers: {
|
||||||
cookies: cookies,
|
cookies: cookies,
|
||||||
origin: @site.url
|
origin: @site.url
|
||||||
|
@ -119,12 +119,12 @@ module Api
|
||||||
test 'las cookies tienen un vencimiento interno' do
|
test 'las cookies tienen un vencimiento interno' do
|
||||||
assert_equal 2, @site.posts.size
|
assert_equal 2, @site.posts.size
|
||||||
|
|
||||||
get v1_site_invitades_cookie_url(@site.hostname)
|
get v1_site_invitades_cookie_url(@site.hostname, **@host)
|
||||||
|
|
||||||
expired = (ENV.fetch('COOKIE_DURATION', '30').to_i + 1).minutes
|
expired = (ENV.fetch('COOKIE_DURATION', '30').to_i + 1).minutes
|
||||||
|
|
||||||
Timecop.freeze(Time.now + expired) do
|
Timecop.freeze(Time.now + expired) do
|
||||||
post v1_site_posts_url(@site.hostname, layout: :post),
|
post v1_site_posts_url(@site.hostname, layout: :post, **@host),
|
||||||
headers: {
|
headers: {
|
||||||
cookies: cookies,
|
cookies: cookies,
|
||||||
origin: @site.url
|
origin: @site.url
|
||||||
|
|
|
@ -22,7 +22,7 @@ module Api
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'se puede obtener un listado de todos' do
|
test 'se puede obtener un listado de todos' do
|
||||||
get v1_sites_url, headers: @authorization, as: :json
|
get v1_sites_url(host: "api.#{Site.domain}"), headers: @authorization, as: :json
|
||||||
assert_equal Site.all.pluck(:name), JSON.parse(response.body)
|
assert_equal Site.all.pluck(:name), JSON.parse(response.body)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
29
test/system/constraints_api_subdomain_test.rb
Normal file
29
test/system/constraints_api_subdomain_test.rb
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class ConstraintsApiSubdomainTest < ActiveSupport::TestCase
|
||||||
|
setup do
|
||||||
|
@constraint = Constraints::ApiSubdomain.new
|
||||||
|
|
||||||
|
MockRequest = Struct.new(:hostname, keyword_init: true) unless defined? MockRequest
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'cualquier subdominio que empiece con api. matchea' do
|
||||||
|
request = MockRequest.new hostname: 'api.'
|
||||||
|
|
||||||
|
(rand * 10).to_i.times do
|
||||||
|
request.hostname += "#{SecureRandom.hex}."
|
||||||
|
|
||||||
|
assert @constraint.matches?(request)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'cualquier subdominio que no empiece con api. matchea' do
|
||||||
|
request = MockRequest.new hostname: 'panel.'
|
||||||
|
|
||||||
|
(rand * 10).to_i.times do
|
||||||
|
request.hostname += "#{SecureRandom.hex}."
|
||||||
|
|
||||||
|
assert_not @constraint.matches?(request)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue