diff --git a/app/models/subscription_client_resource.rb b/app/models/subscription_client_resource.rb index fb86662..8b274df 100644 --- a/app/models/subscription_client_resource.rb +++ b/app/models/subscription_client_resource.rb @@ -1,33 +1,10 @@ # frozen_string_literal: true -require "aws-sdk-s3" - class SubscriptionClientResource < ActiveRecord::Base belongs_to :supplier, class_name: "SubscriptionClientSupplier" has_many :notices, class_name: "SubscriptionClientNotice", as: :notice_subject, dependent: :destroy has_many :subscriptions, foreign_key: "resource_id", class_name: "SubscriptionClientSubscription", dependent: :destroy - def can_access_bucket?(bucket) - s3_client.head_bucket(bucket: bucket) - true - rescue Aws::S3::Errors::BadRequest, - Aws::S3::Errors::Forbidden, - Aws::S3::Errors::NotFound - false - end - - def s3_client - @s3_client ||= begin - return nil unless access_key_id && secret_access_key - - Aws::S3::Client.new( - region: region, - access_key_id: access_key_id, - secret_access_key: secret_access_key - ) - end - end - def region "us-east-1" end diff --git a/lib/discourse_subscription_client/engine.rb b/lib/discourse_subscription_client/engine.rb index 247f203..8724fdc 100644 --- a/lib/discourse_subscription_client/engine.rb +++ b/lib/discourse_subscription_client/engine.rb @@ -30,6 +30,7 @@ def configurable? ./request ./authorization ./resources + ./s3_gem ./notices ./subscriptions ./subscriptions/result diff --git a/lib/discourse_subscription_client/s3_gem.rb b/lib/discourse_subscription_client/s3_gem.rb new file mode 100644 index 0000000..1384599 --- /dev/null +++ b/lib/discourse_subscription_client/s3_gem.rb @@ -0,0 +1,114 @@ +# frozen_string_literal: true + +require "aws-sdk-s3" + +module DiscourseSubscriptionClient + class S3Gem + attr_reader :plugin_name, :access_key_id, :secret_access_key, :region, :bucket + + def initialize(opts = {}) + @plugin_name = opts[:plugin_name] + @access_key_id = opts[:access_key_id] + @secret_access_key = opts[:secret_access_key] + @region = opts[:region] + @bucket = opts[:bucket] + end + + def ready? + plugin_name && access_key_id && secret_access_key && region && bucket && can_access_bucket? + end + + def install(gems) + return unless ready? + + write_gemrc + + gems.each do |gem_slug, version| + klass = gem_slug.to_s.underscore.classify + gem_name = gem_slug.to_s.dasherize + opts = { require_name: gem_slug.to_s.gsub(/_/, "/"), config: gemrc_path } + load(plugin_path, gem_name, version, opts) + end + ensure + remove_gemrc + end + + protected + + # Compare PluginGem.load + def load(path, name, version, opts = nil) + opts ||= {} + + gems_path = File.dirname(path) + "/gems/#{RUBY_VERSION}" + spec_path = "#{gems_path}/specifications" + spec_file = spec_path + "/#{name}-#{version}" + + if PluginGem.platform_variants(spec_file).find(&File.method(:exist?)).blank? + command = + "gem install #{name} -v #{version} -i #{gems_path} --no-document --ignore-dependencies --no-user-install --config-file #{opts[:config]}" + puts command + Bundler.with_unbundled_env { puts `#{command}` } + end + + spec_file_variant = PluginGem.platform_variants(spec_file).find(&File.method(:exist?)) + if spec_file_variant.present? + Gem.path << gems_path + Gem::Specification.load(spec_file_variant).activate + require opts[:require_name] + else + puts "You are specifying the gem #{name} in #{path}, however it does not exist!" + puts "Looked for: \n- #{PluginGem.platform_variants(spec_file).join("\n- ")}" + exit(-1) + end + end + + def can_access_bucket? + client.head_bucket(bucket: bucket) + true + rescue Aws::S3::Errors::BadRequest, Aws::S3::Errors::Forbidden, Aws::S3::Errors::NotFound => e + false + end + + def client + @client ||= + begin + return nil unless region && access_key_id && secret_access_key + + Aws::S3::Client.new( + region: region, + access_key_id: access_key_id, + secret_access_key: secret_access_key + ) + end + end + + def gemrc + { + sources: ["s3://#{bucket}/", "https://rubygems.org/"], + s3_source: { + "#{bucket}": { + id: access_key_id, + secret: secret_access_key, + region: region + } + } + } + end + + def write_gemrc + File.write(gemrc_path, gemrc.to_yaml) + end + + def remove_gemrc + File.delete(gemrc_path) if File.exist?(gemrc_path) + end + + def gemrc_path + File.join(Rails.root, "tmp", ".gemrc") + end + + def plugin_path + @plugin_path ||= Discourse.plugins_by_name[plugin_name].path + end + end +end