# frozen_string_literal: true # Alojar el sitio como un servicio oculto de Tor, que en realidad es un # link simbólico al DeployLocal. class DeployHiddenService < DeployWww validates :hostname, format: { with: /\A[a-z2-7]{56}.onion\z/ } # Sufijo para todos los dominios temporales. # # TODO: Deprecar cuando recuperemos la columna values como JSONB, # agregando un { temporary: true } TEMPORARY_SUFFIX = 'temporary' # Traer todos los servicios ocultos temporales. scope :temporary, -> { where("hostname not like '#{TEMPORARY_SUFFIX}%'") } # Los servicios ocultos son su propio transporte cifrado y # autenticado. # # @return [String] def url "http://#{hostname}" end # Los onions no son creados por Sutty sino por Tor y enviados luego a # través de la API. El hostname por defecto es un nombre temporal que # se parece a una dirección OnionV3. # # @return [String] def default_hostname "#{TEMPORARY_SUFFIX}#{random_base32}.onion" end # Detecta si es una dirección temporal. # # @return [Boolean] def temporary? hostname.start_with? TEMPORARY_SUFFIX end private # No soportamos cambiar de onion def destination_changed? false end def implements_hostname_validation? true end # Adaptado de base32 # # @see {https://github.com/stesla/base32/blob/master/lib/base32.rb} # @see {https://github.com/stesla/base32/blob/master/LICENSE} def random_base32(length = nil) table = 'abcdefghijklmnopqrstuvwxyz234567' length ||= 56 - TEMPORARY_SUFFIX.length OpenSSL::Random.random_bytes(length).each_byte.map do |b| table[b % 32] end.join end end