mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-26 00:56:21 +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-i18n'
|
||||
gem 'devise_invitable'
|
||||
gem 'distributed-press-api-client', '~> 0.2.0'
|
||||
gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n'
|
||||
gem 'exception_notification'
|
||||
gem 'fast_blank'
|
||||
|
|
40
Gemfile.lock
40
Gemfile.lock
|
@ -114,6 +114,7 @@ GEM
|
|||
rack-test (>= 0.5.4)
|
||||
xpath (>= 2.0, < 4.0)
|
||||
chartkick (4.2.1)
|
||||
climate_control (1.2.0)
|
||||
coderay (1.1.3)
|
||||
colorator (1.1.0)
|
||||
commonmarker (0.23.6-x86_64-linux-musl)
|
||||
|
@ -151,12 +152,45 @@ GEM
|
|||
devise_invitable (2.0.6)
|
||||
actionmailer (>= 5.0)
|
||||
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-rails (2.8.1)
|
||||
dotenv (= 2.8.1)
|
||||
railties (>= 3.2)
|
||||
down (5.4.0)
|
||||
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)
|
||||
em-websocket (0.5.3)
|
||||
eventmachine (>= 0.12.9)
|
||||
|
@ -215,8 +249,8 @@ GEM
|
|||
thor
|
||||
hiredis (0.6.3-x86_64-linux-musl)
|
||||
http_parser.rb (0.8.0-x86_64-linux-musl)
|
||||
httparty (0.20.0)
|
||||
mime-types (~> 3.0)
|
||||
httparty (0.21.0)
|
||||
mini_mime (>= 1.0.0)
|
||||
multi_xml (>= 0.5.2)
|
||||
i18n (1.8.11)
|
||||
concurrent-ruby (~> 1.0)
|
||||
|
@ -262,6 +296,7 @@ GEM
|
|||
jekyll-watch (2.2.1)
|
||||
listen (~> 3.0)
|
||||
json (2.6.3-x86_64-linux-musl)
|
||||
jwt (2.6.0)
|
||||
kaminari (1.2.2)
|
||||
activesupport (>= 4.1.0)
|
||||
kaminari-actionview (= 1.2.2)
|
||||
|
@ -546,6 +581,7 @@ DEPENDENCIES
|
|||
devise
|
||||
devise-i18n
|
||||
devise_invitable
|
||||
distributed-press-api-client (~> 0.2.0)
|
||||
dotenv-rails
|
||||
down
|
||||
ed25519
|
||||
|
|
1
Procfile
1
Procfile
|
@ -1,2 +1,3 @@
|
|||
cleanup: bundle exec rake cleanup:everything
|
||||
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"
|
||||
every "0 1 * * *"
|
||||
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