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'
|
||||
|
||||
constraints subdomain: 'api' do
|
||||
constraints(Constraints::ApiSubdomain.new) do
|
||||
scope module: 'api' do
|
||||
namespace :v1 do
|
||||
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.config.write
|
||||
@site.reload
|
||||
@host = { host: "api.#{Site.domain}" }
|
||||
end
|
||||
|
||||
teardown do
|
||||
|
@ -22,11 +23,11 @@ module Api
|
|||
test 'el sitio tiene que existir' do
|
||||
@site.destroy
|
||||
|
||||
get v1_site_contact_cookie_url(@site.hostname)
|
||||
get v1_site_contact_cookie_url(@site.hostname, **@host)
|
||||
|
||||
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: {
|
||||
name: SecureRandom.hex,
|
||||
pronouns: SecureRandom.hex,
|
||||
|
@ -41,8 +42,8 @@ module Api
|
|||
end
|
||||
|
||||
test 'hay que enviar desde el sitio principal' do
|
||||
get v1_site_contact_cookie_url(@site.hostname)
|
||||
post v1_site_contact_url(site_id: @site.hostname, form: :contacto),
|
||||
get v1_site_contact_cookie_url(@site.hostname, **@host)
|
||||
post v1_site_contact_url(site_id: @site.hostname, form: :contacto, **@host),
|
||||
params: {
|
||||
name: SecureRandom.hex,
|
||||
pronouns: SecureRandom.hex,
|
||||
|
@ -57,8 +58,8 @@ module Api
|
|||
end
|
||||
|
||||
test 'hay que dar consentimiento' do
|
||||
get v1_site_contact_cookie_url(@site.hostname)
|
||||
post v1_site_contact_url(site_id: @site.hostname, form: :contacto),
|
||||
get v1_site_contact_cookie_url(@site.hostname, **@host)
|
||||
post v1_site_contact_url(site_id: @site.hostname, form: :contacto, **@host),
|
||||
headers: {
|
||||
origin: @site.url
|
||||
},
|
||||
|
@ -77,14 +78,14 @@ module Api
|
|||
test 'enviar un mensaje genera correos' do
|
||||
ActionMailer::Base.deliveries.clear
|
||||
|
||||
redirect = @site.url + '?thanks'
|
||||
redirect = "#{@site.url}?thanks"
|
||||
|
||||
10.times do
|
||||
create :rol, site: @site
|
||||
end
|
||||
|
||||
get v1_site_contact_cookie_url(@site.hostname)
|
||||
post v1_site_contact_url(site_id: @site.hostname, form: :contacto),
|
||||
get v1_site_contact_cookie_url(@site.hostname, **@host)
|
||||
post v1_site_contact_url(site_id: @site.hostname, form: :contacto, **@host),
|
||||
headers: {
|
||||
Origin: @site.url
|
||||
},
|
||||
|
@ -107,14 +108,14 @@ module Api
|
|||
|
||||
@site.update name: 'example.org.'
|
||||
|
||||
redirect = @site.url + '?thanks'
|
||||
redirect = "#{@site.url}?thanks"
|
||||
|
||||
10.times do
|
||||
create :rol, site: @site
|
||||
end
|
||||
|
||||
get v1_site_contact_cookie_url(@site.hostname)
|
||||
post v1_site_contact_url(site_id: @site.hostname, form: :contacto),
|
||||
get v1_site_contact_cookie_url(@site.hostname, **@host)
|
||||
post v1_site_contact_url(site_id: @site.hostname, form: :contacto, **@host),
|
||||
headers: { origin: @site.url },
|
||||
params: {
|
||||
name: SecureRandom.hex,
|
||||
|
|
|
@ -9,10 +9,11 @@ module Api
|
|||
skip
|
||||
|
||||
post v1_csp_reports_url,
|
||||
host: "api.#{Site.domain}",
|
||||
params: {
|
||||
'csp-report': {
|
||||
'document-uri': 'http://example.com/signup.html',
|
||||
'referrer': '',
|
||||
referrer: '',
|
||||
'blocked-uri': 'http://example.com/css/style.css',
|
||||
'violated-directive': 'style-src cdn.example.com',
|
||||
'original-policy': "default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports"
|
||||
|
|
|
@ -11,6 +11,7 @@ module Api
|
|||
@usuarie = @rol.usuarie
|
||||
|
||||
@site.update_attribute :colaboracion_anonima, true
|
||||
@host = { host: "api.#{Site.domain}" }
|
||||
end
|
||||
|
||||
teardown do
|
||||
|
@ -18,7 +19,7 @@ module Api
|
|||
end
|
||||
|
||||
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['_sutty_session']
|
||||
|
@ -27,7 +28,7 @@ module Api
|
|||
test 'solo si el sitio existe' do
|
||||
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['_sutty_session']
|
||||
|
@ -36,7 +37,7 @@ module Api
|
|||
test 'solo si el sitio tiene colaboracion anonima' do
|
||||
@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['_sutty_session']
|
||||
|
|
|
@ -18,7 +18,7 @@ module Api
|
|||
end
|
||||
|
||||
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: {
|
||||
title: SecureRandom.hex,
|
||||
description: SecureRandom.hex
|
||||
|
@ -36,15 +36,15 @@ module Api
|
|||
test 'no se pueden enviar a sitios que no existen' do
|
||||
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]
|
||||
|
||||
get v1_site_invitades_cookie_url(@site.hostname)
|
||||
get v1_site_invitades_cookie_url(@site.hostname, **@host)
|
||||
|
||||
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 },
|
||||
params: {
|
||||
consent: true,
|
||||
|
@ -61,9 +61,9 @@ module Api
|
|||
test 'antes hay que pedir una cookie' do
|
||||
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: {
|
||||
cookies: cookies,
|
||||
origin: @site.url
|
||||
|
@ -88,9 +88,9 @@ module Api
|
|||
title = SecureRandom.hex
|
||||
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: {
|
||||
cookies: cookies,
|
||||
origin: @site.url
|
||||
|
@ -119,12 +119,12 @@ module Api
|
|||
test 'las cookies tienen un vencimiento interno' do
|
||||
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
|
||||
|
||||
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: {
|
||||
cookies: cookies,
|
||||
origin: @site.url
|
||||
|
|
|
@ -22,7 +22,7 @@ module Api
|
|||
end
|
||||
|
||||
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)
|
||||
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