Skip to content

Commit

Permalink
Merge pull request #30 from COMPEON/add-token-based-authentication
Browse files Browse the repository at this point in the history
Add new api key authentication
  • Loading branch information
anthonyPassler authored Jan 15, 2024
2 parents 26b1683 + 4c12603 commit 7b2b330
Show file tree
Hide file tree
Showing 10 changed files with 83 additions and 11 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
firmenwissen (1.1.0)
firmenwissen (1.2.0)
addressable

GEM
Expand Down
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ suggestion.address # => 'Louise-Dumon-Straße 5'

suggestion.to_h # => { crefo_id: '1234567890', name: 'COMPEON GmbH', ... }
```
### Configuration
### Basic Auth Configuration
```ruby
Firmenwissen.configure do |config|
config.authentication_strategy = 'basic' # This is set to 'basic' by default, eliminating the need for explicit configuration.
config.user = 'username' # Username for Firmenwissen basic auth (required)
config.password = 'password' # Password for Firmenwissen basic auth (required)
config.timeout = 5 # Request timeout in seconds
Expand All @@ -57,6 +58,19 @@ Firmenwissen.configure do |config|
config.endpoint = 'https://example.com/search?query={query}'
end
```
### Api Key Configuration
```ruby
Firmenwissen.configure do |config|
config.authentication_strategy = 'api_key' # Mandatory for all options except 'basic' (required)
config.api_key = 'your api key' # API Key for Firmenwissen API Key authentication (required)
config.timeout = 5 # Request timeout in seconds
config.persistent_session = false # Whether to store/use session information for subsequent requests

# Configure the endpoint yourself. %s will be replaced by the actual query
config.endpoint = 'https://example.com/search?query={query}'
end
```

### Mocking results
In a non production-like environment you will not want to perform real requests to the API. Thus you can configure the gem to respond with mocked data.

Expand Down
9 changes: 7 additions & 2 deletions lib/firmenwissen/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ def configure
end
end

SETTINGS = %i[endpoint password mock_data mock_requests persistent_session timeout user]
SETTINGS = %i[endpoint password mock_data mock_requests persistent_session timeout user authentication_strategy api_key]

DEFAULT_SETTINGS = {
endpoint: 'https://www.firmenwissen.de/search/suggest/companywithaddress/{query}{?country}',
mock_requests: false,
mock_data: [],
persistent_session: false,
timeout: 5
timeout: 5,
authentication_strategy: "basic"
}.freeze

SETTINGS.each do |setting|
Expand Down Expand Up @@ -51,5 +52,9 @@ def mock_requests?
def persistent_session?
persistent_session
end

def api_key_present?
api_key.is_a?(String) && !api_key.empty?
end
end
end
7 changes: 7 additions & 0 deletions lib/firmenwissen/errors/api_key_error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Firmenwissen
class ApiKeyError < StandardError
def initialize(message = 'Firmenwissen API Key is missing')
super
end
end
end
7 changes: 7 additions & 0 deletions lib/firmenwissen/errors/authentication_strategy_error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Firmenwissen
class AuthenticationStrategyError < StandardError
def initialize(message = 'Invalid authentication strategy')
super
end
end
end
3 changes: 2 additions & 1 deletion lib/firmenwissen/http_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ def execute
def request
@request ||= begin
Net::HTTP::Get.new(uri).tap do |req|
req.basic_auth(config.user, config.password)
req.basic_auth(config.user, config.password) if config.authentication_strategy == "basic"
req.add_field('API-KEY', config.api_key) if config.authentication_strategy == "api_key"
req.add_field('Cookie', session_cookie) if config.persistent_session? && !session_cookie.empty?
end
end
Expand Down
9 changes: 8 additions & 1 deletion lib/firmenwissen/request/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ def initialize(query, options = {})
@options = options
@params = options.fetch(:params, {})

raise CredentialsError unless config.credentials_present?
case config.authentication_strategy
when "basic"
raise CredentialsError unless config.credentials_present?
when "api_key"
raise ApiKeyError unless config.api_key_present?
else
raise AuthenticationStrategyError
end
end

def execute
Expand Down
2 changes: 1 addition & 1 deletion lib/firmenwissen/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Firmenwissen
VERSION = '1.1.0'
VERSION = '1.2.0'
end
10 changes: 9 additions & 1 deletion spec/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

describe Firmenwissen::Configuration do
it 'responds to all configuration options' do
%i[endpoint password mock_data mock_requests timeout user].each do |setting|
%i[endpoint password mock_data mock_requests timeout user api_key authentication_strategy].each do |setting|
expect(described_class.new).to respond_to(setting)
end
end
Expand All @@ -16,6 +16,14 @@
end
end

describe '#api_key_present?' do
it 'validates the API Key' do
expect(described_class.new(api_key: 'my-auth-api_key').api_key_present?).to eq(true)
expect(described_class.new(api_key: '').api_key_present?).to eq(false)
expect(described_class.new(api_key: nil).api_key_present?).to eq(false)
end
end

describe '#merge' do
subject do
described_class
Expand Down
29 changes: 26 additions & 3 deletions spec/http_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,32 @@
allow(Net::HTTP::Get).to receive(:new).with(decorated_uri).and_return(http_get_mock)
end

it 'configures basic auth' do
subject.execute
expect(http_get_mock).to have_received(:basic_auth).with(options[:user], options[:password])
describe 'when authentication strategy is basic' do
let(:options) { { user: 'user', password: 'password', timeout: 10, authentication_strategy: 'basic' } }

it 'configures basic auth' do
subject.execute
expect(http_get_mock).to have_received(:basic_auth).with(options[:user], options[:password])
expect(http_get_mock).not_to have_received(:add_field).with('API-KEY', options[:api_key])
end
end

describe 'when authentication strategy is api_key' do
let(:options) { { api_key: 'my-api-key', timeout: 10, authentication_strategy: 'api_key' } }

it 'configures api key authentication' do
subject.execute
expect(http_get_mock).to have_received(:add_field).with('API-KEY', options[:api_key])
expect(http_get_mock).not_to have_received(:basic_auth)
end
end

describe 'when authentication strategy is not provided' do
it 'defaults and configures basic auth' do
subject.execute
expect(http_get_mock).to have_received(:basic_auth).with(options[:user], options[:password])
expect(http_get_mock).not_to have_received(:add_field).with('API-KEY', options[:api_key])
end
end

it 'fires the request' do
Expand Down

0 comments on commit 7b2b330

Please sign in to comment.