diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index a24ae62c..09ba0364 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -1,13 +1,43 @@ # frozen_string_literal: true -# Soportar Distributed Press APIv0 -# -# No se realiza ninguna acción porque el deploy se hace desde el plugin -# local. -class DeployDistributedPress < Deploy - store :values, accessors: %i[api_url api_key hostname], coder: JSON +require 'distributed_press/v1/client/auth' +require 'distributed_press/v1/client/site' - def deploy; end +# Soportar Distributed Press APIv1 +# +# Usa tokens de publicación efímeros para todas las acciones. +# +# Al ser creado, genera el sitio en la instancia de Distributed Press +# configurada y almacena el ID. +# +# 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], coder: JSON + + before_create :create_remote_site! + + # Actualiza la información y luego envía los cambios + # + # @param :output [Bool] + # @return [Bool] + def deploy + time_start + + status = false + + site_client.tap do |c| + update remote_info: c.show(publishing_site).to_h + + status = c.publish(publishing_site, deploy_local.destination) + end + + time_stop + + create_stat! status + + status + end def limit; end @@ -15,21 +45,88 @@ class DeployDistributedPress < Deploy deploy_local.size end - # TODO: Devolver hyper:// y otras - def url - "ipfs://#{hostname}/" - end - - # Devuelve variables de entorno para enviarle a DeployLocal - # - # @return [Hash] - def local_env - { - 'DISTRIBUTED_PRESS_PROJECT_DOMAIN' => hostname, - 'DISTRIBUTED_PRESS_API_KEY' => api_key, - 'DISTRIBUTED_PRESS_API_URL' => api_url - } - end - def destination; end + + private + + # El cliente de la API + # + # TODO: cuando soportemos más, tiene que haber una relación entre + # DeployDistributedPress y DistributedPressPublisher. + # + # @return [DistributedPressPublisher] + def publisher + @publisher ||= DistributedPressPublisher.first + end + + # El cliente de autenticación se encarga de intercambiar un token por + # otro + # + # @return [DistributedPress::V1::Client::Auth] + def auth_client + DistributedPress::V1::Client::Auth.new(publisher.client) + end + + # Genera un token con permisos de publicación + # + # @return [DistributedPress::V1::Schemas::NewTokenPayload] + def publishing_token_payload + DistributedPress::V1::Schemas::NewTokenPayload.new.call(capabilities: %w[publisher]) + end + + # Genera un token efímero para publicar el sitio + # + # @return [DistributedPress::V1::Token] + def publishing_token + auth_client.exchange(publishing_token_payload) + end + + # Genera un cliente para publicar el sitio + # + # @return [DistributedPress::V1::Client] + def publishing_client + DistributedPress::V1::Client.new(url: publisher.instance, token: publishing_token) + end + + # El cliente para actualizar el sitio + # + # @return [DistributedPress::V1::Client::Site] + def site_client + DistributedPress::V1::Client::Site.new(publishing_client) + end + + # Genera el esquema de datos para poder publicar el sitio + # + # @return [DistributedPress::V1::Schemas::PublishingSite] + def publishing_site + DistributedPress::V1::Schemas::PublishingSite.new.call(id: remote_site_id) + end + + # Genera el esquema de datos para crear el sitio + # + # @return [DistributedPressPublisher::V1::Schemas::NewSite] + def create_site + DistributedPress::V1::Schemas::NewSite.new.call(domain: hostname, protocols: { http: true, ipfs: true, hyper: true }) + end + + # Crea el sitio en la instancia con el hostname especificado + # + # @return [nil] + def create_remote_site! + created_site = site_client.create(create_site) + + self.remote_site_id = created_site[:id] + self.remote_info = created_site.to_h + + nil + end + + # Registra lo que sucedió + # + # @param status [Bool] + # @return [nil] + def create_stat!(status) + build_stats.create action: publisher.to_s, seconds: time_spent_in_seconds, bytes: size, status: status + nil + end end diff --git a/app/models/distributed_press_publisher.rb b/app/models/distributed_press_publisher.rb index 610d698d..5358e738 100644 --- a/app/models/distributed_press_publisher.rb +++ b/app/models/distributed_press_publisher.rb @@ -46,6 +46,11 @@ class DistributedPressPublisher < ApplicationRecord @client ||= DistributedPress::V1::Client.new(url: instance, token: token) end + # @return [String] + def to_s + "Distributed Press <#{instance}>" + end + private # Actualiza o desactiva la fecha de vencimiento a partir de la