mirror of
https://0xacab.org/sutty/sutty
synced 2025-03-14 17:18:20 +00:00
Merge branch 'issue-18074' into 'rails'
Draft: fix: optimizar api de sitios #18074 See merge request sutty/sutty!289
This commit is contained in:
commit
f2ddc1b653
11 changed files with 99 additions and 41 deletions
|
@ -4,51 +4,88 @@ module Api
|
|||
module V1
|
||||
# API para sitios
|
||||
class SitesController < BaseController
|
||||
SUBDOMAIN = ".#{Site.domain}"
|
||||
TESTING_SUBDOMAIN = ".testing.#{Site.domain}"
|
||||
PARTS = Site.domain.split('.').count
|
||||
|
||||
if Rails.env.production?
|
||||
http_basic_authenticate_with name: ENV['HTTP_BASIC_USER'],
|
||||
password: ENV['HTTP_BASIC_PASSWORD']
|
||||
end
|
||||
|
||||
# Lista de nombres de dominios a emitir certificados
|
||||
def index
|
||||
render json: alternative_names + api_names + www_names
|
||||
all_names = sites_names.concat(alternative_names).concat(www_names).concat(api_names).uniq.map do |name|
|
||||
canonicalize name
|
||||
end.reject do |name|
|
||||
subdomain? name
|
||||
end.reject do |name|
|
||||
testing? name
|
||||
end.uniq
|
||||
|
||||
render json: all_names
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# @param query [ActiveRecord::Relation]
|
||||
# @return [Array<String>]
|
||||
def hostname_of(query)
|
||||
query.pluck(Arel.sql("values->>'hostname'")).compact.uniq
|
||||
end
|
||||
|
||||
def canonicalize(name)
|
||||
name.end_with?('.') ? name[0..-2] : "#{name}.#{Site.domain}"
|
||||
end
|
||||
|
||||
# Es un subdominio directo del dominio principal
|
||||
#
|
||||
# @param name [String]
|
||||
# @return [Bool]
|
||||
def subdomain?(name)
|
||||
name.end_with? ".#{Site.domain}"
|
||||
name.end_with?(SUBDOMAIN) && name.split('.').count == (PARTS + 1)
|
||||
end
|
||||
|
||||
# Dominios alternativos
|
||||
def alternative_names
|
||||
(DeployAlternativeDomain.all.map(&:hostname) + DeployLocalizedDomain.all.map(&:hostname)).map do |name|
|
||||
canonicalize name
|
||||
end.reject do |name|
|
||||
subdomain? name
|
||||
# Es un dominio de prueba
|
||||
#
|
||||
# @param name [String]
|
||||
# @return [Bool]
|
||||
def testing?(name)
|
||||
name.end_with?(TESTING_SUBDOMAIN) && name.split('.').count == (PARTS + 2)
|
||||
end
|
||||
|
||||
# Nombres de los sitios
|
||||
#
|
||||
# @param name [String]
|
||||
# @return [Array<String>]
|
||||
def sites_names
|
||||
Site.all.order(:name).pluck(:name)
|
||||
end
|
||||
|
||||
# Dominios alternativos, incluyendo todas las clases derivadas de
|
||||
# esta.
|
||||
#
|
||||
# @return [Array<String>]
|
||||
def alternative_names
|
||||
hostname_of(DeployAlternativeDomain.all)
|
||||
end
|
||||
|
||||
# Obtener todos los sitios con API habilitada, es decir formulario
|
||||
# de contacto y/o colaboración anónima.
|
||||
#
|
||||
# TODO: Optimizar
|
||||
# @return [Array<String>]
|
||||
def api_names
|
||||
Site.where(contact: true)
|
||||
.or(Site.where(colaboracion_anonima: true))
|
||||
.select("'api.' || name as name").map(&:name).map do |name|
|
||||
canonicalize name
|
||||
end.reject do |name|
|
||||
subdomain? name
|
||||
.pluck(:name).map do |name|
|
||||
"api.#{name}"
|
||||
end
|
||||
end
|
||||
|
||||
# Todos los dominios con WWW habilitado
|
||||
def www_names
|
||||
Site.where(id: DeployWww.all.pluck(:site_id)).select("'www.' || name as name").map(&:name).map do |name|
|
||||
canonicalize name
|
||||
Site.where(id: DeployWww.all.pluck(:site_id)).pluck(:name).map do |name|
|
||||
"www.#{name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Soportar dominios alternativos
|
||||
class DeployAlternativeDomain < Deploy
|
||||
store :values, accessors: %i[hostname], coder: JSON
|
||||
store_accessor :values, :hostname
|
||||
|
||||
DEPENDENCIES = %i[deploy_local]
|
||||
|
||||
|
|
|
@ -12,7 +12,10 @@ require 'distributed_press/v1/client/site'
|
|||
# Al ser publicado, envía los archivos en un tarball y actualiza la
|
||||
# información.
|
||||
class DeployDistributedPress < Deploy
|
||||
store :values, accessors: %i[hostname remote_site_id remote_info distributed_press_publisher_id], coder: JSON
|
||||
store_accessor :values, :hostname
|
||||
store_accessor :values, :remote_site_id
|
||||
store_accessor :values, :remote_info
|
||||
store_accessor :values, :distributed_press_publisher_id
|
||||
|
||||
before_create :create_remote_site!
|
||||
before_destroy :delete_remote_site!
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Genera una versión onion
|
||||
class DeployHiddenService < DeployWww
|
||||
store :values, accessors: %i[onion], coder: JSON
|
||||
store_accessor :values, :onion
|
||||
|
||||
before_create :create_hidden_service!
|
||||
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
# Alojamiento local, solo genera el sitio, con lo que no necesita hacer
|
||||
# nada más
|
||||
class DeployLocal < Deploy
|
||||
store :values, accessors: %i[], coder: JSON
|
||||
|
||||
before_destroy :remove_destination!
|
||||
|
||||
def bundle(output: false)
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
# Soportar dominios localizados
|
||||
class DeployLocalizedDomain < DeployAlternativeDomain
|
||||
store :values, accessors: %i[hostname locale], coder: JSON
|
||||
store_accessor :values, :hostname
|
||||
store_accessor :values, :locale
|
||||
|
||||
# Generar un link simbólico del sitio principal al alternativo
|
||||
def deploy(**)
|
||||
|
|
|
@ -3,11 +3,15 @@
|
|||
# Sincroniza sitios a servidores remotos usando Rsync. El servidor
|
||||
# remoto tiene que tener rsync instalado.
|
||||
class DeployRsync < Deploy
|
||||
store :values, accessors: %i[hostname destination host_keys], coder: JSON
|
||||
store_accessor :values, :hostname
|
||||
store_accessor :values, :destination
|
||||
store_accessor :values, :host_keys
|
||||
|
||||
DEPENDENCIES = %i[deploy_local deploy_zip]
|
||||
|
||||
def deploy(output: false)
|
||||
raise(ArgumentError, 'destination no está configurado') if destination.blank?
|
||||
|
||||
ssh? && rsync(output: output)
|
||||
end
|
||||
|
||||
|
@ -18,13 +22,6 @@ class DeployRsync < Deploy
|
|||
deploy_local.size
|
||||
end
|
||||
|
||||
# Devolver el destino o lanzar un error si no está configurado
|
||||
def destination
|
||||
values[:destination].tap do |d|
|
||||
raise(ArgumentError, 'destination no está configurado') if d.blank?
|
||||
end
|
||||
end
|
||||
|
||||
# @return [String]
|
||||
def url
|
||||
"https://#{hostname}/"
|
||||
|
@ -43,9 +40,9 @@ class DeployRsync < Deploy
|
|||
ssh_available = false
|
||||
|
||||
Net::SSH.start(host, user, verify_host_key: tofu, timeout: 5) do |ssh|
|
||||
if values[:host_keys].blank?
|
||||
if self.host_keys.blank?
|
||||
# Guardar las llaves que se encontraron en la primera conexión
|
||||
values[:host_keys] = ssh.transport.host_keys.map do |host_key|
|
||||
self.host_keys = ssh.transport.host_keys.map do |host_key|
|
||||
"#{host_key.ssh_type} #{host_key.fingerprint}"
|
||||
end
|
||||
|
||||
|
@ -74,7 +71,7 @@ class DeployRsync < Deploy
|
|||
#
|
||||
# @return [Symbol]
|
||||
def tofu
|
||||
values[:host_keys].present? ? :always : :accept_new
|
||||
self.host_keys.present? ? :always : :accept_new
|
||||
end
|
||||
|
||||
# Devuelve el par user host
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
# Vincula la versión del sitio con www a la versión sin
|
||||
class DeployWww < Deploy
|
||||
store :values, accessors: %i[], coder: JSON
|
||||
|
||||
DEPENDENCIES = %i[deploy_local]
|
||||
|
||||
before_destroy :remove_destination!
|
||||
|
|
|
@ -6,8 +6,6 @@ require 'zip'
|
|||
#
|
||||
# TODO: Firmar con minisign
|
||||
class DeployZip < Deploy
|
||||
store :values, accessors: %i[], coder: JSON
|
||||
|
||||
DEPENDENCIES = %i[deploy_local]
|
||||
|
||||
# Una vez que el sitio está generado, tomar todos los archivos y
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ChangeDeploysValuesTypeToJsonB < ActiveRecord::Migration[6.1]
|
||||
def up
|
||||
add_column :deploys, :values_2, :jsonb, default: {}
|
||||
|
||||
Deploy.find_each do |deploy|
|
||||
deploy.update values_2: JSON.parse(deploy.values)
|
||||
end
|
||||
|
||||
remove_column :deploys, :values
|
||||
rename_column :deploys, :values_2, :values
|
||||
end
|
||||
|
||||
def down
|
||||
add_column :deploys, :values_2, :text
|
||||
|
||||
Deploy.find_each do |deploy|
|
||||
deploy.update values_2: deploy.values.to_json
|
||||
end
|
||||
|
||||
remove_column :deploys, :values
|
||||
rename_column :deploys, :values_2, :values
|
||||
end
|
||||
end
|
|
@ -882,8 +882,8 @@ CREATE TABLE public.deploys (
|
|||
updated_at timestamp without time zone NOT NULL,
|
||||
site_id integer,
|
||||
type character varying,
|
||||
"values" text,
|
||||
rol_id integer
|
||||
rol_id integer,
|
||||
"values" jsonb DEFAULT '{}'::jsonb
|
||||
);
|
||||
|
||||
|
||||
|
@ -2719,6 +2719,7 @@ INSERT INTO "schema_migrations" (version) VALUES
|
|||
('20240316203721'),
|
||||
('20240318183846'),
|
||||
('20240319124212'),
|
||||
('20240319144735');
|
||||
('20240319144735'),
|
||||
('20241223185830');
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue