Skip to content

Commit

Permalink
Backport #6063 (Google privkey in ENV) to 3.x
Browse files Browse the repository at this point in the history
  • Loading branch information
dlpierce committed Jun 15, 2023
1 parent f5a0d16 commit 34cf04c
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 27 deletions.
4 changes: 2 additions & 2 deletions .dassie/config/analytics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ analytics:
analytics_id: <%= ENV['GOOGLE_ANALYTICS_ID'] %>
app_name: <%= ENV['GOOGLE_OAUTH_APP_NAME'] %>
app_version: <%= ENV['GOOGLE_OAUTH_APP_VERSION'] %>
privkey_value: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_VALUE'] %>
privkey_path: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_PATH'] %>
privkey_secret: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_SECRET'] %>
client_email: <%= ENV['GOOGLE_OAUTH_CLIENT_EMAIL'] %>
matomo:
matomo:
base_url: <%= ENV['MATOMO_BASE_URL'] %>
site_id: <%= ENV['MATOMO_SITE_ID'] %>
auth_token: <%= ENV['MATOMO_AUTH_TOKEN'] %>

3 changes: 2 additions & 1 deletion .regen
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
46
# When updating CI regen seed, set to current date.
2023-05-24T10:43:07
38 changes: 23 additions & 15 deletions app/services/hyrax/analytics/google.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
# frozen_string_literal: true

require 'oauth2'
require 'signet/oauth_2/client'

# rubocop:disable Metrics/ModuleLength
module Hyrax
module Analytics
# rubocop:disable Metrics/ModuleLength
module Google
extend ActiveSupport::Concern
# rubocop:disable Metrics/BlockLength
class_methods do
# Loads configuration options from config/analytics.yml. Expected structure:
# Loads configuration options from config/analytics.yml. You only need PRIVATE_KEY_PATH or
# PRIVATE_KEY_VALUE. VALUE takes precedence.
# Expected structure:
# `analytics:`
# ` google:`
# ` app_name: <%= ENV['GOOGLE_OAUTH_APP_NAME']`
# ` app_version: <%= ENV['GOOGLE_OAUTH_APP_VERSION']`
# ` privkey_path: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_PATH']`
# ` privkey_value: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_VALUE']`
# ` privkey_secret: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_SECRET']`
# ` client_email: <%= ENV['GOOGLE_OAUTH_CLIENT_EMAIL']`
# @return [Config]
Expand All @@ -41,26 +45,25 @@ def self.load_from_yaml
new config
end

REQUIRED_KEYS = %w[analytics_id app_name app_version privkey_path privkey_secret client_email].freeze
KEYS = %w[analytics_id app_name app_version privkey_path privkey_value privkey_secret client_email].freeze
REQUIRED_KEYS = %w[analytics_id app_name app_version privkey_secret client_email].freeze

def initialize(config)
@config = config
end

# @return [Boolean] are all the required values present?
def valid?
config_keys = @config.keys
REQUIRED_KEYS.all? { |required| config_keys.include?(required) }
end
return false unless @config['privkey_value'].present? || @config['privkey_path'].present?

REQUIRED_KEYS.each do |key|
class_eval %{ def #{key}; @config.fetch('#{key}'); end }
REQUIRED_KEYS.all? { |required| @config[required].present? }
end

# This method allows setting the analytics id in the initializer
# @deprecated set the analytics id in either ENV['GOOGLE_ANALYTICS_ID'] or config/analytics.yaml
def analytics_id=(value)
@config['analytics_id'] = value
KEYS.each do |key|
# rubocop:disable Style/EvalWithLocation
class_eval %{ def #{key}; @config.fetch('#{key}'); end }
class_eval %{ def #{key}=(value); @config['#{key}'] = value; end }
# rubocop:enable Style/EvalWithLocation
end
end

Expand All @@ -77,8 +80,12 @@ def oauth_client
end

def auth_client(scope)
raise "Private key file for Google analytics was expected at '#{config.privkey_path}', but no file was found." unless File.exist?(config.privkey_path)
private_key = File.read(config.privkey_path)
private_key = Base64.decode64(config.privkey_value) if config.privkey_value.present?
if private_key.blank?
raise "Private key file for Google analytics was expected at '#{config.privkey_path}', but no file was found." unless File.exist?(config.privkey_path)

private_key = File.read(config.privkey_path)
end
Signet::OAuth2::Client.new token_credential_uri: 'https://accounts.google.com/o/oauth2/token',
audience: 'https://accounts.google.com/o/oauth2/token',
scope: scope,
Expand Down Expand Up @@ -123,7 +130,7 @@ def to_date_range(period)

[start_date, end_date]
end
# rubocop:enabl e Metrics/MethodLength
# rubocop:enable Metrics/MethodLength

def keyword_conversion(date)
case date
Expand Down Expand Up @@ -199,6 +206,7 @@ def total_visitors(period = 'month', date = default_date_range)
end
# rubocop:enable Metrics/BlockLength
end
# rubocop:enable Metrics/ModuleLength
end
end
# rubocop:enable Metrics/ModuleLength
7 changes: 4 additions & 3 deletions app/services/hyrax/analytics/matomo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ module Matomo
# Loads configuration options from config/analytics.yml. Expected structure:
# `analytics:`
# ` matomo:`
# ` base_url: <%= ENV['MATOMOT_BASE_URL']`
# ` site_id: <%= ENV['MATOMOT_SITE_ID']`
# ` auth_token: <%= ENV['MATOMOT_AUTH_TOKEN']`
# ` base_url: <%= ENV['MATOMO_BASE_URL']`
# ` site_id: <%= ENV['MATOMO_SITE_ID']`
# ` auth_token: <%= ENV['MATOMO_AUTH_TOKEN']`
# @return [Config]
def config
@config ||= Config.load_from_yaml
end

class Config
# TODO: test matomo and see if it needs any of the updates from https://github.com/samvera/hyrax/pull/6063
def self.load_from_yaml
filename = Rails.root.join('config', 'analytics.yml')
yaml = YAML.safe_load(ERB.new(File.read(filename)).result)
Expand Down
1 change: 1 addition & 0 deletions lib/generators/hyrax/templates/config/analytics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ analytics:
analytics_id: <%= ENV['GOOGLE_ANALYTICS_ID'] %>
app_name: <%= ENV['GOOGLE_OAUTH_APP_NAME'] %>
app_version: <%= ENV['GOOGLE_OAUTH_APP_VERSION'] %>
privkey_value: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_VALUE'] %>
privkey_path: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_PATH'] %>
privkey_secret: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_SECRET'] %>
client_email: <%= ENV['GOOGLE_OAUTH_CLIENT_EMAIL'] %>
Expand Down
16 changes: 10 additions & 6 deletions spec/lib/hyrax/analytics_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
RSpec.describe Hyrax::Analytics do
before do
ENV['GOOGLE_ANALYTICS_ID'] = 'UA-XXXXXXXX'
ENV['GOOGLE_OAUTH_APP_NAME'] = "My App Name"
ENV['GOOGLE_OAUTH_APP_VERSION'] = "0.0.1"
ENV['GOOGLE_OAUTH_PRIVATE_KEY_PATH'] = "/tmp/privkey.p12"
ENV['GOOGLE_OAUTH_PRIVATE_KEY_SECRET'] = "s00pers3kr1t"
ENV['GOOGLE_OAUTH_CLIENT_EMAIL'] = "oauth@example.org"
ENV['GOOGLE_OAUTH_APP_NAME'] = 'My App Name'
ENV['GOOGLE_OAUTH_APP_VERSION'] = '0.0.1'
ENV['GOOGLE_OAUTH_PRIVATE_KEY_PATH'] = '/tmp/privkey.p12'
ENV['GOOGLE_OAUTH_PRIVATE_KEY_VALUE'] = ''
ENV['GOOGLE_OAUTH_PRIVATE_KEY_SECRET'] = 's00pers3kr1t'
ENV['GOOGLE_OAUTH_CLIENT_EMAIL'] = 'oauth@example.org'

described_class.send(:remove_instance_variable, :@config) if described_class.send(:instance_variable_defined?, :@config)
end
Expand All @@ -23,6 +24,7 @@
expect(config.analytics_id).to eql 'UA-XXXXXXXX'
expect(config.app_name).to eql 'My App Name'
expect(config.app_version).to eql '0.0.1'
expect(config.privkey_value).to be_nil
expect(config.privkey_path).to eql '/tmp/privkey.p12'
expect(config.privkey_secret).to eql 's00pers3kr1t'
expect(config.client_email).to eql 'oauth@example.org'
Expand All @@ -35,6 +37,7 @@
analytics:
app_name: My App Name
app_version: 0.0.1
privkey_value:
privkey_path: /tmp/privkey.p12
privkey_secret: s00pers3kr1t
client_email: oauth@example.org
Expand All @@ -45,6 +48,7 @@
Hyrax.config.google_analytics_id = "UA-XXXXXXXX"
expect(config.app_name).to eql 'My App Name'
expect(config.app_version).to eql '0.0.1'
expect(config.privkey_value).to be_nil
expect(config.privkey_path).to eql '/tmp/privkey.p12'
expect(config.privkey_secret).to eql 's00pers3kr1t'
expect(config.client_email).to eql 'oauth@example.org'
Expand Down Expand Up @@ -79,7 +83,7 @@
describe "#profile" do
subject { described_class.profile }

context "when the private key file is missing" do
context "when the private key file and private key value are missing" do
it "raises an error" do
expect { subject }.to raise_error RuntimeError, "Private key file for Google analytics was expected at '/tmp/privkey.p12', but no file was found."
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ def add_analytics_config
analytics_id: UA-XXXXXXXX
app_name: My App Name
app_version: 0.0.1
privkey_value:
privkey_path: /tmp/privkey.p12
privkey_secret: s00pers3kr1t
client_email: oauth@example.org
Expand Down

0 comments on commit 34cf04c

Please sign in to comment.