mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-26 08:06:23 +00:00
feat: almacenar y renovar tokens de distributed press
This commit is contained in:
parent
38b5e0e2e0
commit
d59c66b478
8 changed files with 154 additions and 2 deletions
1
Gemfile
1
Gemfile
|
@ -40,6 +40,7 @@ gem 'commonmarker'
|
||||||
gem 'devise'
|
gem 'devise'
|
||||||
gem 'devise-i18n'
|
gem 'devise-i18n'
|
||||||
gem 'devise_invitable'
|
gem 'devise_invitable'
|
||||||
|
gem 'distributed-press-api-client', '~> 0.2.0'
|
||||||
gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n'
|
gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n'
|
||||||
gem 'exception_notification'
|
gem 'exception_notification'
|
||||||
gem 'fast_blank'
|
gem 'fast_blank'
|
||||||
|
|
40
Gemfile.lock
40
Gemfile.lock
|
@ -114,6 +114,7 @@ GEM
|
||||||
rack-test (>= 0.5.4)
|
rack-test (>= 0.5.4)
|
||||||
xpath (>= 2.0, < 4.0)
|
xpath (>= 2.0, < 4.0)
|
||||||
chartkick (4.2.1)
|
chartkick (4.2.1)
|
||||||
|
climate_control (1.2.0)
|
||||||
coderay (1.1.3)
|
coderay (1.1.3)
|
||||||
colorator (1.1.0)
|
colorator (1.1.0)
|
||||||
commonmarker (0.23.6-x86_64-linux-musl)
|
commonmarker (0.23.6-x86_64-linux-musl)
|
||||||
|
@ -151,12 +152,45 @@ GEM
|
||||||
devise_invitable (2.0.6)
|
devise_invitable (2.0.6)
|
||||||
actionmailer (>= 5.0)
|
actionmailer (>= 5.0)
|
||||||
devise (>= 4.6)
|
devise (>= 4.6)
|
||||||
|
distributed-press-api-client (0.2.0)
|
||||||
|
addressable (~> 2.3, >= 2.3.0)
|
||||||
|
climate_control
|
||||||
|
dry-schema
|
||||||
|
httparty (~> 0.18)
|
||||||
|
json (~> 2.1, >= 2.1.0)
|
||||||
|
jwt (~> 2.6.0)
|
||||||
dotenv (2.8.1)
|
dotenv (2.8.1)
|
||||||
dotenv-rails (2.8.1)
|
dotenv-rails (2.8.1)
|
||||||
dotenv (= 2.8.1)
|
dotenv (= 2.8.1)
|
||||||
railties (>= 3.2)
|
railties (>= 3.2)
|
||||||
down (5.4.0)
|
down (5.4.0)
|
||||||
addressable (~> 2.8)
|
addressable (~> 2.8)
|
||||||
|
dry-configurable (1.0.1)
|
||||||
|
dry-core (~> 1.0, < 2)
|
||||||
|
zeitwerk (~> 2.6)
|
||||||
|
dry-core (1.0.0)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
|
zeitwerk (~> 2.6)
|
||||||
|
dry-inflector (1.0.0)
|
||||||
|
dry-initializer (3.1.1)
|
||||||
|
dry-logic (1.5.0)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
|
dry-core (~> 1.0, < 2)
|
||||||
|
zeitwerk (~> 2.6)
|
||||||
|
dry-schema (1.13.0)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
|
dry-configurable (~> 1.0, >= 1.0.1)
|
||||||
|
dry-core (~> 1.0, < 2)
|
||||||
|
dry-initializer (~> 3.0)
|
||||||
|
dry-logic (>= 1.5, < 2)
|
||||||
|
dry-types (>= 1.7, < 2)
|
||||||
|
zeitwerk (~> 2.6)
|
||||||
|
dry-types (1.7.0)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
|
dry-core (~> 1.0, < 2)
|
||||||
|
dry-inflector (~> 1.0, < 2)
|
||||||
|
dry-logic (>= 1.4, < 2)
|
||||||
|
zeitwerk (~> 2.6)
|
||||||
ed25519 (1.3.0-x86_64-linux-musl)
|
ed25519 (1.3.0-x86_64-linux-musl)
|
||||||
em-websocket (0.5.3)
|
em-websocket (0.5.3)
|
||||||
eventmachine (>= 0.12.9)
|
eventmachine (>= 0.12.9)
|
||||||
|
@ -215,8 +249,8 @@ GEM
|
||||||
thor
|
thor
|
||||||
hiredis (0.6.3-x86_64-linux-musl)
|
hiredis (0.6.3-x86_64-linux-musl)
|
||||||
http_parser.rb (0.8.0-x86_64-linux-musl)
|
http_parser.rb (0.8.0-x86_64-linux-musl)
|
||||||
httparty (0.20.0)
|
httparty (0.21.0)
|
||||||
mime-types (~> 3.0)
|
mini_mime (>= 1.0.0)
|
||||||
multi_xml (>= 0.5.2)
|
multi_xml (>= 0.5.2)
|
||||||
i18n (1.8.11)
|
i18n (1.8.11)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
|
@ -262,6 +296,7 @@ GEM
|
||||||
jekyll-watch (2.2.1)
|
jekyll-watch (2.2.1)
|
||||||
listen (~> 3.0)
|
listen (~> 3.0)
|
||||||
json (2.6.3-x86_64-linux-musl)
|
json (2.6.3-x86_64-linux-musl)
|
||||||
|
jwt (2.6.0)
|
||||||
kaminari (1.2.2)
|
kaminari (1.2.2)
|
||||||
activesupport (>= 4.1.0)
|
activesupport (>= 4.1.0)
|
||||||
kaminari-actionview (= 1.2.2)
|
kaminari-actionview (= 1.2.2)
|
||||||
|
@ -546,6 +581,7 @@ DEPENDENCIES
|
||||||
devise
|
devise
|
||||||
devise-i18n
|
devise-i18n
|
||||||
devise_invitable
|
devise_invitable
|
||||||
|
distributed-press-api-client (~> 0.2.0)
|
||||||
dotenv-rails
|
dotenv-rails
|
||||||
down
|
down
|
||||||
ed25519
|
ed25519
|
||||||
|
|
1
Procfile
1
Procfile
|
@ -1,2 +1,3 @@
|
||||||
cleanup: bundle exec rake cleanup:everything
|
cleanup: bundle exec rake cleanup:everything
|
||||||
stats: bundle exec rake stats:process_all
|
stats: bundle exec rake stats:process_all
|
||||||
|
distributed_press_renew_tokens: bundle exec rake distributed_press:tokens:renew
|
||||||
|
|
17
app/jobs/renew_distributed_press_tokens_job.rb
Normal file
17
app/jobs/renew_distributed_press_tokens_job.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Renueva los tokens de Distributed Press antes que se venzan,
|
||||||
|
# activando los callbacks que hacen que se refresque el token.
|
||||||
|
class RenewDistributedPressTokensJob < ApplicationJob
|
||||||
|
# Renueva todos los tokens a punto de vencer o informa el error sin
|
||||||
|
# detener la tarea si algo pasa.
|
||||||
|
def perform
|
||||||
|
DistributedPressPublisher.with_about_to_expire_tokens.find_each do |publisher|
|
||||||
|
publisher.touch
|
||||||
|
rescue DistributedPress::V1::Error => e
|
||||||
|
data = { instance: publisher.instance, expires_at: publisher.client.token.expires_at }
|
||||||
|
|
||||||
|
ExceptionNotifier.notify_exception(e, data: data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
68
app/models/distributed_press_publisher.rb
Normal file
68
app/models/distributed_press_publisher.rb
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'distributed_press/v1'
|
||||||
|
|
||||||
|
# Almacena el token de autenticación y la URL, por ahora solo vamos
|
||||||
|
# a tener uno, pero queda abierta la posibilidad de agregar más.
|
||||||
|
class DistributedPressPublisher < ApplicationRecord
|
||||||
|
# Cifrar la información del token en la base de datos
|
||||||
|
has_encrypted :token
|
||||||
|
|
||||||
|
# La instancia es única
|
||||||
|
validates_uniqueness_of :instance
|
||||||
|
|
||||||
|
# El token es necesario
|
||||||
|
validates_presence_of :token
|
||||||
|
|
||||||
|
# Mantener la fecha de vencimiento actualizada
|
||||||
|
before_save :update_expires_at_from_token!, :update_token_from_client!
|
||||||
|
|
||||||
|
# Devuelve todos los tokens que vencen en una hora
|
||||||
|
scope :with_about_to_expire_tokens, -> do
|
||||||
|
where('expires_at > ? and expires_at < ?', Time.now, Time.now + 1.hour)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Al cambiar el token genera un cliente nuevo
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
|
def token=(new_token)
|
||||||
|
@client = nil
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
# Al cambiar la instancia genera un cliente nuevo
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
|
def instance=(new_instance)
|
||||||
|
@client = nil
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
# Instancia un cliente de Distributed Press a partir del token. Al
|
||||||
|
# cargar un token a punto de vencer se renueva automáticamente.
|
||||||
|
#
|
||||||
|
# @return [DistributedPress::V1::Client]
|
||||||
|
def client
|
||||||
|
@client ||= DistributedPress::V1::Client.new(url: instance, token: token)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Actualiza o desactiva la fecha de vencimiento a partir de la
|
||||||
|
# información del token.
|
||||||
|
#
|
||||||
|
# @return [nil]
|
||||||
|
def update_expires_at_from_token!
|
||||||
|
self.expires_at = client.token.forever? ? nil : client.token.expires_at
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
# Actualiza el token a partir del cliente, que ya actualiza el token
|
||||||
|
# automáticamente.
|
||||||
|
#
|
||||||
|
# @return [nil]
|
||||||
|
def update_token_from_client!
|
||||||
|
self.token = client.token.to_s
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,14 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Crea la tabla de publishers de Distributed Press que contiene las
|
||||||
|
# instancias y tokens
|
||||||
|
class CreateDistributedPressPublisher < ActiveRecord::Migration[6.1]
|
||||||
|
def change
|
||||||
|
create_table :distributed_press_publishers do |t|
|
||||||
|
t.timestamps
|
||||||
|
t.string :instance, unique: true
|
||||||
|
t.text :token_ciphertext, null: false
|
||||||
|
t.datetime :expires_at, null: true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
10
lib/tasks/distributed_press.rake
Normal file
10
lib/tasks/distributed_press.rake
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
namespace :distributed_press do
|
||||||
|
namespace :tokens do
|
||||||
|
desc 'Renew tokens'
|
||||||
|
task renew: :environment do
|
||||||
|
RenewDistributedPressTokensJob.perform_now
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -13,3 +13,8 @@ check program stats
|
||||||
with path "/usr/bin/foreman run -f /srv/Procfile -d /srv stats" as uid "rails" gid "www-data"
|
with path "/usr/bin/foreman run -f /srv/Procfile -d /srv stats" as uid "rails" gid "www-data"
|
||||||
every "0 1 * * *"
|
every "0 1 * * *"
|
||||||
if status != 0 then alert
|
if status != 0 then alert
|
||||||
|
|
||||||
|
check program distributed_press_tokens_renew
|
||||||
|
with path "/usr/bin/foreman run -f /srv/Procfile -d /srv distributed_press_tokens_renew" as uid "rails" gid "www-data"
|
||||||
|
every "0 3 * * *"
|
||||||
|
if status != 0 then alert
|
||||||
|
|
Loading…
Reference in a new issue