Skip to content

Commit

Permalink
feat: added device code manager
Browse files Browse the repository at this point in the history
  • Loading branch information
valmoz committed Mar 1, 2024
1 parent ca71578 commit 0f41eb0
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 27 deletions.
150 changes: 124 additions & 26 deletions lib/fattureincloud_ruby_sdk/oauth2/oauth2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,40 @@
require 'typhoeus'

module FattureInCloud_Ruby_Sdk
# The OAuth2AuthorizationCodeManager class is used to manage the OAuth2 authorization code flow.
class OAuth2AuthorizationCodeManager
# The OAuth2Manager class is used to manage the OAuth2 flow.
class OAuth2Manager
attr_accessor :client_id, :base_uri

# Initializes a new instance of the OAuth2Manager class.
# @param [String] client_id The client id.
# @param [String] base_uri The base uri.
def initialize(client_id, base_uri = 'https://api-v2.fattureincloud.it')
@client_id = client_id
@base_uri = base_uri
end

# Get the access token.
# @param [String] url The url.
# @param [Object] data The request data.
# @return [Object] The response body.
def execute_post(url, body)
res = Typhoeus.post(token_uri, body: data)
if res.response_code != 200
raise "Error fetching token: #{res.response_body}"
end
JSON.parse(res.body)
end

# Build the scopes string.
# @param [Array<Scope>] scopes The scopes.
# @return [String] The scopes string.
def self.get_scope_string(scopes)
scopes.map { |scope| scope.to_s }.join(' ')
end
end

# The OAuth2AuthorizationCodeManager class is used to manage the OAuth2 authorization code flow.
class OAuth2AuthorizationCodeManager < OAuth2Manager
attr_accessor :client_id, :client_secret, :redirect_uri, :base_uri

# Initializes a new instance of the OAuth2AuthorizationCodeManager class.
Expand All @@ -12,10 +44,9 @@ class OAuth2AuthorizationCodeManager
# @param [String] redirect_uri The redirect uri.
# @param [String] base_uri The base uri.
def initialize(client_id, client_secret, redirect_uri, base_uri = 'https://api-v2.fattureincloud.it')
@client_id = client_id
super client_id, base_uri
@client_secret = client_secret
@redirect_uri = redirect_uri
@base_uri = base_uri
end

# Get the authorization url.
Expand All @@ -24,7 +55,7 @@ def initialize(client_id, client_secret, redirect_uri, base_uri = 'https://api-v
# @return [String] The authorization url.
def get_authorization_url(scopes, state)
authorization_uri = "#{@base_uri}/oauth/authorize"
scope_string = OAuth2AuthorizationCodeManager.get_scope_string(scopes)
scope_string = OAuth2Manager.get_scope_string(scopes)

params = {
'response_type': 'code',
Expand All @@ -40,7 +71,7 @@ def get_authorization_url(scopes, state)

# Get the access token.
# @param [String] code The code.
# @return [OAuth2AuthorizationCodeTokenResponse] The access token.
# @return [OAuth2TokenResponse] The access token.
def fetch_token(code)
token_uri = "#{@base_uri}/oauth/token"
data = {
Expand All @@ -51,18 +82,14 @@ def fetch_token(code)
'code': code,
}

res = Typhoeus.post(token_uri, body: data)
if res.response_code != 200
raise "Error fetching token: #{res.response_body}"
end
json = JSON.parse(res.body)
json = execute_post(token_uri, data)

OAuth2AuthorizationCodeTokenResponse.new(json["token_type"], json['access_token'], json['refresh_token'], json['expires_in'])
OAuth2TokenResponse.new(json["token_type"], json['access_token'], json['refresh_token'], json['expires_in'])
end

# Get the refresh token.
# @param [String] refresh_token The refresh token.
# @return [OAuth2AuthorizationCodeTokenResponse] The access token.
# @return [OAuth2TokenResponse] The access token.
def refresh_token(refresh_token)
token_uri = "#{@base_uri}/oauth/token"
data = {
Expand All @@ -72,13 +99,9 @@ def refresh_token(refresh_token)
'refresh_token': refresh_token,
}

res = Typhoeus.post(token_uri, body: data)
if res.response_code != 200
raise "Error fetching token: #{res.response_body}"
end
json = JSON.parse(res.body)
json = execute_post(token_uri, data)

OAuth2AuthorizationCodeTokenResponse.new(json["token_type"], json['access_token'], json['refresh_token'], json['expires_in'])
OAuth2TokenResponse.new(json["token_type"], json['access_token'], json['refresh_token'], json['expires_in'])
end


Expand All @@ -89,12 +112,66 @@ def get_params_from_url(url)
url_obj = URI::decode_www_form(URI.parse(url).query).to_h
OAuth2AuthorizationCodeParams.new(url_obj['code'], url_obj['state'])
end
end

# The OAuth2DeviceCodeManager class is used to manage the OAuth2 device code flow.
class OAuth2DeviceCodeManager < OAuth2Manager
attr_accessor :client_id, :base_uri

# Initializes a new instance of the OAuth2DeviceCodeManager class.
# @param [String] client_id The client id.
# @param [String] base_uri The base uri.
def initialize(client_id, base_uri = 'https://api-v2.fattureincloud.it')
super client_id, base_uri
end

# Build rh escopes string.
# Get the device code.
# @param [Array<Scope>] scopes The scopes.
# @return [String] The scopes string.
def self.get_scope_string(scopes)
scopes.map { |scope| scope.to_s }.join(' ')
# @return [OAuth2DeviceCodeResponse] The device code.
def get_device_code(scopes)
device_uri = "#{@base_uri}/oauth/device"
scope_string = OAuth2Manager.get_scope_string(scopes)

data = {
'client_id': @client_id,
'scope': scope_string
}

json = execute_post(device_uri, data)

OAuth2DeviceCodeResponse.new(json["device_code"], json['user_code'], json['scope'], json['verification_uri'], json['interval'], json['expires_in'])
end

# Get the access token.
# @param [String] code The device code.
# @return [OAuth2TokenResponse] The access token.
def fetch_token(code)
token_uri = "#{@base_uri}/oauth/token"
data = {
'grant_type': 'urn:ietf:params:oauth:grant-type:device_code',
'client_id': @client_id,
'device_code': code,
}

json = execute_post(token_uri, data)

OAuth2TokenResponse.new(json["token_type"], json['access_token'], json['refresh_token'], json['expires_in'])
end

# Get the refresh token.
# @param [String] refresh_token The refresh token.
# @return [OAuth2TokenResponse] The access token.
def refresh_token(refresh_token)
token_uri = "#{@base_uri}/oauth/token"
data = {
'grant_type': 'refresh_token',
'client_id': @client_id,
'refresh_token': refresh_token,
}

json = execute_post(token_uri, data)

OAuth2TokenResponse.new(json["token_type"], json['access_token'], json['refresh_token'], json['expires_in'])
end
end

Expand All @@ -111,11 +188,11 @@ def initialize(authorization_code, state)
end
end

# The OAuth2AuthorizationCodeTokenResponse class is used to manage the OAuth2 authorization code token response.
class OAuth2AuthorizationCodeTokenResponse
# The OAuth2TokenResponse class is used to manage the OAuth2 token response.
class OAuth2TokenResponse
attr_accessor :token_type, :access_token, :refresh_token, :expires_in

# Initializes a new instance of the OAuth2AuthorizationCodeTokenResponse class.
# Initializes a new instance of the OAuth2TokenResponse class.
# @param [String] token_type The token type.
# @param [String] access_token The access token.
# @param [String] refresh_token The refresh token.
Expand All @@ -127,4 +204,25 @@ def initialize(token_type, access_token, refresh_token, expires_in)
@expires_in = expires_in
end
end

# The OAuth2DeviceCodeResponse class is used to manage the OAuth2 device code response.
class OAuth2DerviceCodeResponse
attr_accessor :device_code, :user_code, :scope, :verification_uri, :interval, :expires_in

# Initializes a new instance of the OAuth2TokenResponse class.
# @param [String] device_code The token type.
# @param [String] user_code The access token.
# @param [Object] user_code The access token.
# @param [String] verification_uri The verification uri.
# @param [Number] interval The interval between two requests.
# @param [Number] expires_in The expire time.
def initialize(device_code, user_code, scope, verification_uri, interval, expires_in)
@device_code = device_code
@user_code = user_code
@scope = scope
@verification_uri = verification_uri
@interval = interval
@expires_in = expires_in
end
end
end
54 changes: 53 additions & 1 deletion spec/oauth2/oauth2_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

describe 'test an instance of OAuth2AuthorizationCodeParams' do
it 'should work' do
params = FattureInCloud_Ruby_Sdk::OAuth2AuthorizationCodeTokenResponse.new('bearer', 'EXAMPLE_TOKEN', 'EXAMPLE_REFRESH_TOKEN', 86400)
params = FattureInCloud_Ruby_Sdk::OAuth2TokenResponse.new('bearer', 'EXAMPLE_TOKEN', 'EXAMPLE_REFRESH_TOKEN', 86400)
expect(params.token_type).to eq('bearer')
expect(params.access_token).to eq('EXAMPLE_TOKEN')
expect(params.refresh_token).to eq('EXAMPLE_REFRESH_TOKEN')
Expand Down Expand Up @@ -79,3 +79,55 @@
end

end

describe FattureInCloud_Ruby_Sdk::OAuth2DeviceCodeManager do
let(:oauth) { FattureInCloud_Ruby_Sdk::OAuth2DeviceCodeManager.new('CLIENT_ID') }


describe 'test an instance of OAuth2DeviceCodeManager' do
it 'should create an instance of OAuth2DeviceCodeManager' do
expect(oauth).to be_instance_of(FattureInCloud_Ruby_Sdk::OAuth2DeviceCodeManager)
expect(oauth.client_id).to eq('CLIENT_ID')

oauth.client_id = 'CLIENT_ID_2'
expect(oauth.client_id).to eq('CLIENT_ID_2')
end
end

describe 'test an instance of OAuth2DeviceCodeResponse' do
it 'should work' do
scope = { "situation" => "r", "settings" => "a" }
params = FattureInCloud_Ruby_Sdk::OAuth2DeviceCodeResponse.new('PAPAYA', 'LION', scope, 'https://fattureincloud.it/connetti', 5, 300)
expect(params.device_code).to eq('PAPAYA')
expect(params.user_code).to eq('LION')
expect(params.scope).to eq(scope)
expect(params.verification_uri).to eq('https://fattureincloud.it/connetti')
expect(params.interval).to eq(5)
expect(params.expires_in).to eq(300)

scope2 = { "situation" => "a" }
params.device_code = 'TIRAMISU'
expect(params.device_code).to eq('TIRAMISU')
params.user_code = 'FELIX-BEACH'
expect(params.user_code).to eq('FELIX-BEACH')
params.scope = scope2
expect(params.scope).to eq(scope2)
params.verification_uri = 'https://colombiatourism.co'
expect(params.verification_uri).to eq('https://colombiatourism.co')
params.interval = 69
expect(params.interval).to eq(69)
params.expires_in = 3600
expect(params.expires_in).to eq(3600)
end
end

describe 'test method "get_scope_string"' do
it 'should work' do
scopes = [FattureInCloud_Ruby_Sdk::Scope::ISSUED_DOCUMENTS_INVOICES_READ, FattureInCloud_Ruby_Sdk::Scope::SETTINGS_ALL]
scopes_string = FattureInCloud_Ruby_Sdk::OAuth2DeviceCodeManager::get_scope_string(scopes)

expect(scopes_string).to eq('issued_documents.invoices:r settings:a')
end
end

end

0 comments on commit 0f41eb0

Please sign in to comment.