Persist RS auth tokens in Redis

This commit is contained in:
galfert 2023-06-20 14:02:48 +02:00
parent dabd892a25
commit 42af148168
Signed by: galfert
GPG Key ID: EED8863A3A607B8D
4 changed files with 86 additions and 0 deletions

View File

@ -0,0 +1,10 @@
class ExpireRemoteStorageAuthorizationJob < ApplicationJob
queue_as :remote_storage
def perform(rs_auth_id)
rs_auth = RemoteStorageAuthorization.find rs_auth_id
return unless rs_auth.expire_at.nil? || rs_auth.expire_at <= DateTime.now
rs_auth.destroy!
end
end

View File

@ -14,6 +14,10 @@ class RemoteStorageAuthorization < ApplicationRecord
end end
before_create :generate_token before_create :generate_token
before_create :store_token_in_redis
after_create :schedule_token_expiry
before_destroy :delete_token_from_redis
after_destroy :remove_token_expiry_job
def url def url
if self.redirect_uri if self.redirect_uri
@ -24,9 +28,36 @@ class RemoteStorageAuthorization < ApplicationRecord
end end
end end
def delete_token_from_redis
key = "rs:authorizations:#{user.address}:#{token}"
# You can't delete multiple members of a set with Redis 2
redis.smembers(key).each { |auth| redis.srem(key, auth) }
end
private private
def redis
@redis ||= Redis.new(url: Setting.redis_url)
end
def generate_token(length=16) def generate_token(length=16)
self.token = SecureRandom.hex(length) if self.token.blank? self.token = SecureRandom.hex(length) if self.token.blank?
end end
def store_token_in_redis
redis.sadd "rs:authorizations:#{user.address}:#{token}", permissions
end
def schedule_token_expiry
return unless expire_at.present?
ExpireRemoteStorageAuthorizationJob.set(wait_unil: expire_at).perform_later(id)
end
def remove_token_expiry_job
queue = Sidekiq::Queue.new(ExpireRemoteStorageAuthorizationJob.queue_name)
queue.each do |job|
next unless job.display_class == "ExpireRemoteStorageAuthorizationJob"
job.delete if job.display_args == [id]
end
end
end end

View File

@ -0,0 +1,9 @@
FactoryBot.define do
factory :remote_storage_authorization do
permissions { ["documents:rw"] }
client_id { "some-fancy-app" }
redirect_uri { "https://example.com/some-fancy-app" }
app_name { "Fancy App" }
expire_at { nil }
end
end

View File

@ -0,0 +1,36 @@
require 'rails_helper'
RSpec.describe ExpireRemoteStorageAuthorizationJob, type: :job do
before do
@user = create :user, cn: "ronald", ou: "kosmos.org"
@rs_authorization = create :remote_storage_authorization, user: @user, expire_at: 1.day.ago
end
after do
clear_enqueued_jobs
clear_performed_jobs
end
subject(:job) {
described_class.perform_later(@rs_authorization.id)
}
let(:redis) {
@redis ||= Redis.new(url: Setting.redis_url)
}
it "removes the RS authorization from redis" do
redis_key = "rs:authorizations:#{@user.address}:#{@rs_authorization.token}"
expect(redis.keys(redis_key)).to_not be_empty
perform_enqueued_jobs { job }
expect(redis.keys(redis_key)).to be_empty
end
it "deletes the RS authorization object" do
expect {
perform_enqueued_jobs { job }
}.to change(RemoteStorageAuthorization, :count).by(-1)
end
end