Skip to content
Snippets Groups Projects
Unverified Commit 4ad750b0 authored by Ahmad Farhat's avatar Ahmad Farhat Committed by GitHub
Browse files

More work on provider verification (#4260)

* More work on providers

* lock

* lock
parent 6d066587
No related branches found
No related tags found
No related merge requests found
......@@ -52,4 +52,5 @@ group :test do
gem 'selenium-webdriver'
gem 'shoulda-matchers', '~> 5.0'
gem 'webdrivers'
gem 'webmock'
end
......@@ -124,6 +124,8 @@ GEM
activesupport
childprocess (4.1.0)
concurrent-ruby (1.1.10)
crack (0.4.5)
rexml
crass (1.0.6)
cssbundling-rails (1.1.0)
railties (>= 6.0.0)
......@@ -150,6 +152,7 @@ GEM
ffi (1.15.5)
globalid (1.0.0)
activesupport (>= 5.0)
hashdiff (1.0.1)
hashie (5.0.0)
hcaptcha (7.1.0)
json
......@@ -202,7 +205,7 @@ GEM
net-protocol
timeout
nio4r (2.5.8)
nokogiri (1.13.6-x86_64-linux)
nokogiri (1.13.10-x86_64-linux)
racc (~> 1.4)
omniauth (2.1.0)
hashie (>= 3.4.6)
......@@ -234,7 +237,7 @@ GEM
public_suffix (4.0.7)
puma (5.6.4)
nio4r (~> 2.0)
racc (1.6.0)
racc (1.6.1)
rack (2.2.3.1)
rack-oauth2 (1.19.0)
activesupport
......@@ -366,6 +369,10 @@ GEM
webfinger (1.2.0)
activesupport
httpclient (>= 2.4)
webmock (3.14.0)
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
websocket (1.2.9)
websocket-driver (0.7.5)
websocket-extensions (>= 0.1.0)
......@@ -419,3 +426,4 @@ DEPENDENCIES
tzinfo-data
web-console
webdrivers
webmock
......@@ -52,7 +52,11 @@ class ApplicationController < ActionController::Base
end
# Parses the url for the user domain
def parse_user_domain(hostname)
hostname&.split('.')&.first
def parse_user_domain(_hostname)
provider = hostname&.split('.')&.first
raise 'Invalid domain' unless ProviderValidator.new(provider:).call
provider
end
end
# frozen_string_literal: true
class ProviderValidator
def initialize(provider:)
@provider = provider
@endpoint = File.join(ENV.fetch('LOADBALANCER_ENDPOINT'), '/api2/')
@secret = ENV.fetch('LOADBALANCER_SECRET')
@route = 'getUserGreenlightCredentials'
end
def call
encoded_params = { name: @provider }.to_param
checksum = Digest::SHA1.hexdigest(@route + encoded_params + @secret)
# Cache the response for an hour
# fetch will return the value if already cached, if not, it will compute the value, cache it, then return it
Rails.cache.fetch("#{@provider}/#{@route}", expires_in: 1.hour) do
url = URI.parse("#{@endpoint}#{@route}?#{encoded_params}&checksum=#{checksum}")
res = Net::HTTP.get_response(url)
return false unless res.is_a?(Net::HTTPSuccess)
response = Hash.from_xml(res.body)['response']
response['returncode'] == 'SUCCESS'
end
end
end
......@@ -11,6 +11,7 @@ require 'rspec/rails'
require 'support/factory_bot'
require 'support/shoulda_matchers'
require 'helpers'
require 'webmock/rspec'
# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
......@@ -35,6 +36,10 @@ rescue ActiveRecord::PendingMigrationError => e
puts e.to_s.strip
exit 1
end
# Disables all HTTP Requests to prevent unstubbed calls from being done
WebMock.disable_net_connect!(allow_localhost: true)
RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
......
# frozen_string_literal: true
require 'rails_helper'
describe ProviderValidator, type: :service do
# Enable caching for this test
let(:memory_store) { ActiveSupport::Cache.lookup_store(:memory_store) }
let(:cache) { Rails.cache }
let(:service) { described_class.new(provider: 'greenlight') }
let(:request_url) { 'http://test.com/api2/getUserGreenlightCredentials?name=greenlight&checksum=b36706f149f97a535da7144b851be87cf0d4c045' }
before do
ENV['LOADBALANCER_ENDPOINT'] = 'http://test.com/'
ENV['LOADBALANCER_SECRET'] = 'test'
# Enable caching
allow(Rails).to receive(:cache).and_return(memory_store)
Rails.cache.clear
end
describe '#call' do
context 'no caching' do
it 'returns true if a success returncode is returned' do
stub_request(:get, request_url).to_return(body: success_response)
expect(service.call).to be true
end
it 'returns false if an error returncode is returned' do
stub_request(:get, request_url).to_return(body: error_response)
expect(service.call).to be false
end
end
context 'caching' do
it 'returns true if a success returncode is returned' do
stub_request(:get, request_url).to_return(body: success_response)
expect(Net::HTTP).to receive(:get_response).exactly(:once).and_call_original # Make sure http request is only made once
service.call
service.call
service.call
expect(service.call).to be true
expect(Rails.cache.read('greenlight/getUserGreenlightCredentials')).to be(true)
end
end
end
private
def success_response
"<response>\n<returncode>SUCCESS</returncode>\n</response>\n"
end
def error_response
"<response>\n<returncode>ERROR</returncode>\n</response>\n"
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment