Handle missing security spec more elegantly

- remove the optional auth_setup_handler() callback mechanism
- add _global_auth_setup() method on ApiClient to analyse config when
security spec not provided
- add methods on the Configuration class to abstract getting and setting
tokens
This commit is contained in:
Dave Baird 2015-11-11 13:43:40 +01:00
parent 06db67210c
commit 2144cf5d31
13 changed files with 461 additions and 293 deletions

View File

@ -34,6 +34,8 @@ sub _new_instance
return bless \%args, $class;
}
sub _cfg {'WWW::{{moduleName}}::Configuration'}
# Set the user agent of the API client
#
# @param string $user_agent The user agent of the API client
@ -308,18 +310,8 @@ sub get_api_key_with_prefix
sub update_params_for_auth {
my ($self, $header_params, $query_params, $auth_settings) = @_;
# we can defer to the application if the spec doesn't describe authentication
if ($self->{auth_setup_handler_object}) {
$self->{auth_setup_handler_object}->auth_setup_handler(
api_client => $self,
header_params => $header_params,
query_params => $query_params,
auth_settings => $auth_settings, # presumably this won't be defined if we're doing it this way
);
return;
}
return if (!defined($auth_settings) || scalar(@$auth_settings) == 0);
return $self->_global_auth_setup($header_params, $query_params)
unless $auth_settings && @$auth_settings;
# one endpoint can have more than 1 auth settings
foreach my $auth (@$auth_settings) {
@ -332,10 +324,47 @@ sub update_params_for_auth {
}
{{/authMethods}}
else {
# TODO show warning about security definition not found
# TODO show warning about security definition not found
}
}
}
# The endpoint API class has not found any settings for auth. This may be deliberate,
# in which case update_params_for_auth() will be a no-op. But it may also be that the
# swagger spec does not describe the intended authorization. So we check in the config for any
# auth tokens and if we find any, we use them for all endpoints;
sub _global_auth_setup {
my ($self, $header_params, $query_params) = @_;
my $tokens = $self->_cfg->get_tokens;
return unless keys %$tokens;
# basic
if (my $uname = delete $tokens->{username}) {
my $pword = delete $tokens->{password};
$header_params->{'Authorization'} = 'Basic '.encode_base64($uname.":".$pword);
}
# oauth
if (my $access_token = delete $tokens->{access_token}) {
$header_params->{'Authorization'} = 'Bearer ' . $access_token;
}
# other keys
foreach my $token_name (keys %$tokens) {
my $in = $tokens->{$token_name}->{in};
my $token = $self->get_api_key_with_prefix($token_name);
if ($in eq 'head') {
$header_params->{$token_name} = $token;
}
elsif ($in eq 'query') {
$query_params->{$token_name} = $token;
}
else {
die "Don't know where to put token '$token_name' ('$in' is not 'head' or 'query')";
}
}
}
1;

View File

@ -16,6 +16,7 @@ our $http_user_agent = 'Perl-Swagger';
# authenticaiton setting
our $api_key = {};
our $api_key_prefix = {};
our $api_key_in = {};
# username and password for HTTP basic authentication
our $username = '';
@ -24,4 +25,56 @@ our $password = '';
# access token for OAuth
our $access_token = '';
sub get_tokens {
my $class = shift;
my $tokens = {};
$tokens->{username} = $username if $username;
$tokens->{password} = $password if $password;
$tokens->{access_token} = $access_token if $access_token;
foreach my $token_name (keys %{ $api_key }) {
$tokens->{$token_name}->{token} = $api_key->{$token_name};
$tokens->{$token_name}->{prefix} = $api_key_prefix->{$token_name};
$tokens->{$token_name}->{in} = $api_key_in->{$token_name};
}
return $tokens;
}
sub clear_tokens {
my $class = shift;
my %tokens = %{$class->get_tokens}; # copy
$username = undef;
$password = undef;
$access_token = undef;
$api_key = {};
$api_key_prefix = {};
$api_key_in = {};
return \%tokens;
}
sub accept_tokens {
my ($class, $tokens) = @_;
foreach my $known_name (qw(username password access_token)) {
next unless $tokens->{$known_name};
eval "\$$known_name = delete \$tokens->{\$known_name}";
die $@ if $@;
}
foreach my $token_name (keys %$tokens) {
$api_key->{$token_name} = $tokens->{$token_name}->{token};
if ($tokens->{$token_name}->{prefix}) {
$api_key_prefix->{$token_name} = $tokens->{$token_name}->{prefix};
}
my $in = $tokens->{$token_name}->{in} || 'head';
croak "Tokens can only go in 'head' or 'query' (not in '$in')" unless $in =~ /^(?:head|query)$/;
$api_key_in->{$token_name} = $in;
}
}
1;

View File

@ -23,7 +23,7 @@ role.
package main;
my $api = MyApp->new;
my $api = MyApp->new({ tokens => $tokens });
my $pet = $api->get_pet_by_id(pet_id => $pet_id);
@ -46,14 +46,40 @@ For documentation of all these methods, see AUTOMATIC DOCUMENTATION below.
## Configuring authentication
If your Swagger spec does not describe authentication, you can write an
`auth_setup_handler()` method in your base class to handle it (see below).
In the normal case, the Swagger spec will describe what parameters are
required and where to put them. You just need to supply the tokens.
In the normal case, the Swagger spec will describe what parameters are required
and where to put them. You just need to supply the authorization tokens.
my $tokens = {
# basic
username => $username,
password => $password,
# oauth
access_token => $oauth_token,
# keys
$some_key => { token => $token,
prefix => $prefix,
in => $in, # 'head||query',
},
$another => { token => $token,
prefix => $prefix,
in => $in, # 'head||query',
},
...,
};
my $api = MyApp->new({ tokens => $tokens });
These should go in the `WWW::{{moduleName}}::Configuration` namespace as follows.
Note these are all optional, and depend on the API you are accessing.
Note these are all optional, as are `prefix` and `in`, and depend on the API
you are accessing. Usually `prefix` and `in` will be determined by the code generator from
the spec and you will not need to set them at run time. If not, `in` will
default to 'head' and `prefix` to the empty string.
The tokens will be placed in the `WWW::{{moduleName}}::Configuration` namespace
as follows, but you don't need to know about this.
- `$WWW::{{moduleName}}::Configuration::username`
@ -88,63 +114,19 @@ Note these are all optional, and depend on the API you are accessing.
# METHODS
## `auth_setup_handler()`
This method does not exist! But if you add it to the class that consumes this
role, it will be called to set up authentication.
package MyApp;
use Moose;
with 'WWW::{{moduleName}}::Role';
sub auth_setup_handler {
my ($self, %p) = @_;
$p{header_params}->{'X-TargetApp-apiKey'} = $api_key;
$p{header_params}->{'X-TargetApp-secretKey'} = $secret_key;
}
# somewhere else...
my $api = MyApp->new;
my $pet = $api->get_pet_by_id(pet_id => $pet_id);
So, `auth_setup_handler()` will be called on your `$api` object and passed the
following parameters:
- `header_params`
A hashref that will become the request headers. You can insert auth
parameters.
- `query_params`
A hashref that will be encoded into the request URL. You can insert auth
parameters.
- `auth_settings`
TODO. Probably not necessary?
- `api_client`
A reference to the `WWW::{{moduleName}}::ApiClient` object that is responsible
for communicating with the server. Just in case that's useful.
## base\_url
## `base_url`
The generated code has the `base_url` already set as a default value. This method
returns (and optionally sets, but only if the API client has not been
created yet) the current value of `base_url`.
## api\_factory
## `api_factory`
Returns an API factory object. You probably won't need to call this directly.
$self->api_factory('Pet'); # returns a WWW::{{moduleName}}::PetApi instance
$self->pet_api; # the same
$self->pet_api; # the same
# MISSING METHODS
@ -202,11 +184,11 @@ Additional documentation for each class and method may be provided by the Swagge
spec. If so, this is available via the `class_documentation()` and
`method_documentation()` methods on each generated API and class:
my $cdoc = $api->pet_api->class_documentation;
my $cdoc = $api->pet_api->class_documentation;
my $cmdoc = $api->pet_api->method_documentation->{$method_name};
my $odoc = $api->get_pet_by_id->(pet_id => $pet_id)->class_documentation;
my $odoc = $api->get_pet_by_id->(pet_id => $pet_id)->class_documentation;
my $omdoc = $api->get_pet_by_id->(pet_id => $pet_id)->method_documentation->{method_name};
Each of these calls returns a hashref with various useful pieces of information.
Each of these calls returns a hashref with various useful pieces of information.

View File

@ -8,19 +8,32 @@ use Log::Any qw($log);
use WWW::{{moduleName}}::ApiFactory;
has base_url => ( is => 'ro',
required => 0,
isa => 'Str',
);
required => 0,
isa => 'Str',
);
has api_factory => ( is => 'ro',
isa => 'WWW::{{moduleName}}::ApiFactory',
builder => '_build_af',
lazy => 1,
);
has tokens => ( is => 'ro',
isa => 'HashRef',
required => 0,
default => sub {{=<% %>=}}{{}}<%={{ }}=%>, # !
);
has _cfg => ( is => 'ro',
isa => 'Str',
default => 'WWW::{{moduleName}}::Configuration',
);
sub BUILD {
my $self = shift;
$self->_cfg->accept_tokens( $self->tokens ) if keys %{$self->tokens};
# ignore these symbols imported into API namespaces
my %outsiders = map {$_ => 1} qw( croak );
@ -93,7 +106,7 @@ role.
package main;
my $api = MyApp->new;
my $api = MyApp->new({ tokens => $tokens });
my $pet = $api->get_pet_by_id(pet_id => $pet_id);
@ -115,14 +128,40 @@ For documentation of all these methods, see AUTOMATIC DOCUMENTATION below.
=head2 Configuring authentication
If your Swagger spec does not describe authentication, you can write an
C<auth_setup_handler()> method in your base class to handle it (see below).
In the normal case, the Swagger spec will describe what parameters are
required and where to put them. You just need to supply the tokens.
In the normal case, the Swagger spec will describe what parameters are required
and where to put them. You just need to supply the authorization tokens.
my $tokens = {
# basic
username => $username,
password => $password,
# oauth
access_token => $oauth_token,
# keys
$some_key => { token => $token,
prefix => $prefix,
in => $in, # 'head||query',
},
$another => { token => $token,
prefix => $prefix,
in => $in, # 'head||query',
},
...,
};
my $api = MyApp->new({ tokens => $tokens });
These should go in the C<WWW::{{moduleName}}::Configuration> namespace as follows.
Note these are all optional, and depend on the API you are accessing.
Note these are all optional, as are C<prefix> and C<in>, and depend on the API
you are accessing. Usually C<prefix> and C<in> will be determined by the code generator from
the spec and you will not need to set them at run time. If not, C<in> will
default to 'head' and C<prefix> to the empty string.
The tokens will be placed in the C<WWW::{{moduleName}}::Configuration> namespace
as follows, but you don't need to know about this.
=over 4
@ -161,68 +200,19 @@ String. The OAuth access token.
=head1 METHODS
=head2 C<auth_setup_handler()>
This method does not exist! But if you add it to the class that consumes this
role, it will be called to set up authentication.
package MyApp;
use Moose;
with 'WWW::{{moduleName}}::Role';
sub auth_setup_handler {
my ($self, %p) = @_;
$p{header_params}->{'X-TargetApp-apiKey'} = $api_key;
$p{header_params}->{'X-TargetApp-secretKey'} = $secret_key;
}
# somewhere else...
my $api = MyApp->new;
my $pet = $api->get_pet_by_id(pet_id => $pet_id);
So, C<auth_setup_handler()> will be called on your C<$api> object and passed the
following parameters:
=over 4
=item C<header_params>
A hashref that will become the request headers. You can insert auth
parameters.
=item C<query_params>
A hashref that will be encoded into the request URL. You can insert auth
parameters.
=item C<auth_settings>
TODO. Probably not necessary?
=item C<api_client>
A reference to the C<WWW::{{moduleName}}::ApiClient> object that is responsible
for communicating with the server. Just in case that's useful.
=back
=head2 base_url
=head2 C<base_url>
The generated code has the C<base_url> already set as a default value. This method
returns (and optionally sets, but only if the API client has not been
created yet) the current value of C<base_url>.
=head2 api_factory
=head2 C<api_factory>
Returns an API factory object. You probably won't need to call this directly.
$self->api_factory('Pet'); # returns a WWW::{{moduleName}}::PetApi instance
$self->pet_api; # the same
$self->pet_api; # the same
=head1 MISSING METHODS
@ -280,13 +270,13 @@ Additional documentation for each class and method may be provided by the Swagge
spec. If so, this is available via the C<class_documentation()> and
C<method_documentation()> methods on each generated API and class:
my $cdoc = $api->pet_api->class_documentation;
my $cdoc = $api->pet_api->class_documentation;
my $cmdoc = $api->pet_api->method_documentation->{$method_name};
my $odoc = $api->get_pet_by_id->(pet_id => $pet_id)->class_documentation;
my $odoc = $api->get_pet_by_id->(pet_id => $pet_id)->class_documentation;
my $omdoc = $api->get_pet_by_id->(pet_id => $pet_id)->method_documentation->{method_name};
Each of these calls returns a hashref with various useful pieces of information.
Each of these calls returns a hashref with various useful pieces of information.
=cut

View File

@ -134,7 +134,7 @@ sub {{nickname}} {
}{{/bodyParams}}
# authentication setting, if any
my $auth_settings = [{{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}];
my $auth_settings = [qw({{#authMethods}}{{name}} {{/authMethods}})];
# make the API Call
{{#returnType}}my $response = $self->{api_client}->call_api($_resource_path, $_method,

View File

@ -23,7 +23,7 @@ role.
package main;
my $api = MyApp->new;
my $api = MyApp->new({ tokens => $tokens });
my $pet = $api->get_pet_by_id(pet_id => $pet_id);
@ -46,14 +46,40 @@ For documentation of all these methods, see AUTOMATIC DOCUMENTATION below.
## Configuring authentication
If your Swagger spec does not describe authentication, you can write an
`auth_setup_handler()` method in your base class to handle it (see below).
In the normal case, the Swagger spec will describe what parameters are
required and where to put them. You just need to supply the tokens.
In the normal case, the Swagger spec will describe what parameters are required
and where to put them. You just need to supply the authorization tokens.
my $tokens = {
# basic
username => $username,
password => $password,
# oauth
access_token => $oauth_token,
# keys
$some_key => { token => $token,
prefix => $prefix,
in => $in, # 'head||query',
},
$another => { token => $token,
prefix => $prefix,
in => $in, # 'head||query',
},
...,
};
my $api = MyApp->new({ tokens => $tokens });
These should go in the `WWW::SwaggerClient::Configuration` namespace as follows.
Note these are all optional, and depend on the API you are accessing.
Note these are all optional, as are `prefix` and `in`, and depend on the API
you are accessing. Usually `prefix` and `in` will be determined by the code generator from
the spec and you will not need to set them at run time. If not, `in` will
default to 'head' and `prefix` to the empty string.
The tokens will be placed in the `WWW::SwaggerClient::Configuration` namespace
as follows, but you don't need to know about this.
- `$WWW::SwaggerClient::Configuration::username`
@ -88,63 +114,19 @@ Note these are all optional, and depend on the API you are accessing.
# METHODS
## `auth_setup_handler()`
This method does not exist! But if you add it to the class that consumes this
role, it will be called to set up authentication.
package MyApp;
use Moose;
with 'WWW::SwaggerClient::Role';
sub auth_setup_handler {
my ($self, %p) = @_;
$p{header_params}->{'X-TargetApp-apiKey'} = $api_key;
$p{header_params}->{'X-TargetApp-secretKey'} = $secret_key;
}
# somewhere else...
my $api = MyApp->new;
my $pet = $api->get_pet_by_id(pet_id => $pet_id);
So, `auth_setup_handler()` will be called on your `$api` object and passed the
following parameters:
- `header_params`
A hashref that will become the request headers. You can insert auth
parameters.
- `query_params`
A hashref that will be encoded into the request URL. You can insert auth
parameters.
- `auth_settings`
TODO. Probably not necessary?
- `api_client`
A reference to the `WWW::SwaggerClient::ApiClient` object that is responsible
for communicating with the server. Just in case that's useful.
## base\_url
## `base_url`
The generated code has the `base_url` already set as a default value. This method
returns (and optionally sets, but only if the API client has not been
created yet) the current value of `base_url`.
## api\_factory
## `api_factory`
Returns an API factory object. You probably won't need to call this directly.
$self->api_factory('Pet'); # returns a WWW::SwaggerClient::PetApi instance
$self->pet_api; # the same
$self->pet_api; # the same
# MISSING METHODS
@ -202,11 +184,11 @@ Additional documentation for each class and method may be provided by the Swagge
spec. If so, this is available via the `class_documentation()` and
`method_documentation()` methods on each generated API and class:
my $cdoc = $api->pet_api->class_documentation;
my $cdoc = $api->pet_api->class_documentation;
my $cmdoc = $api->pet_api->method_documentation->{$method_name};
my $odoc = $api->get_pet_by_id->(pet_id => $pet_id)->class_documentation;
my $odoc = $api->get_pet_by_id->(pet_id => $pet_id)->class_documentation;
my $omdoc = $api->get_pet_by_id->(pet_id => $pet_id)->method_documentation->{method_name};
Each of these calls returns a hashref with various useful pieces of information.
Each of these calls returns a hashref with various useful pieces of information.

View File

@ -34,6 +34,8 @@ sub _new_instance
return bless \%args, $class;
}
sub _cfg {'WWW::SwaggerClient::Configuration'}
# Set the user agent of the API client
#
# @param string $user_agent The user agent of the API client
@ -308,18 +310,8 @@ sub get_api_key_with_prefix
sub update_params_for_auth {
my ($self, $header_params, $query_params, $auth_settings) = @_;
# we can defer to the application if the spec doesn't describe authentication
if ($self->{auth_setup_handler_object}) {
$self->{auth_setup_handler_object}->auth_setup_handler(
api_client => $self,
header_params => $header_params,
query_params => $query_params,
auth_settings => $auth_settings, # presumably this won't be defined if we're doing it this way
);
return;
}
return if (!defined($auth_settings) || scalar(@$auth_settings) == 0);
return $self->_global_auth_setup($header_params, $query_params)
unless $auth_settings && @$auth_settings;
# one endpoint can have more than 1 auth settings
foreach my $auth (@$auth_settings) {
@ -336,10 +328,47 @@ sub update_params_for_auth {
}
else {
# TODO show warning about security definition not found
# TODO show warning about security definition not found
}
}
}
# The endpoint API class has not found any settings for auth. This may be deliberate,
# in which case update_params_for_auth() will be a no-op. But it may also be that the
# swagger spec does not describe the intended authorization. So we check in the config for any
# auth tokens and if we find any, we use them for all endpoints;
sub _global_auth_setup {
my ($self, $header_params, $query_params) = @_;
my $tokens = $self->_cfg->get_tokens;
return unless keys %$tokens;
# basic
if (my $uname = delete $tokens->{username}) {
my $pword = delete $tokens->{password};
$header_params->{'Authorization'} = 'Basic '.encode_base64($uname.":".$pword);
}
# oauth
if (my $access_token = delete $tokens->{access_token}) {
$header_params->{'Authorization'} = 'Bearer ' . $access_token;
}
# other keys
foreach my $token_name (keys %$tokens) {
my $in = $tokens->{$token_name}->{in};
my $token = $self->get_api_key_with_prefix($token_name);
if ($in eq 'head') {
$header_params->{$token_name} = $token;
}
elsif ($in eq 'query') {
$query_params->{$token_name} = $token;
}
else {
die "Don't know where to put token '$token_name' ('$in' is not 'head' or 'query')";
}
}
}
1;

View File

@ -16,6 +16,7 @@ our $http_user_agent = 'Perl-Swagger';
# authenticaiton setting
our $api_key = {};
our $api_key_prefix = {};
our $api_key_in = {};
# username and password for HTTP basic authentication
our $username = '';
@ -24,4 +25,56 @@ our $password = '';
# access token for OAuth
our $access_token = '';
sub get_tokens {
my $class = shift;
my $tokens = {};
$tokens->{username} = $username if $username;
$tokens->{password} = $password if $password;
$tokens->{access_token} = $access_token if $access_token;
foreach my $token_name (keys %{ $api_key }) {
$tokens->{$token_name}->{token} = $api_key->{$token_name};
$tokens->{$token_name}->{prefix} = $api_key_prefix->{$token_name};
$tokens->{$token_name}->{in} = $api_key_in->{$token_name};
}
return $tokens;
}
sub clear_tokens {
my $class = shift;
my %tokens = %{$class->get_tokens}; # copy
$username = undef;
$password = undef;
$access_token = undef;
$api_key = {};
$api_key_prefix = {};
$api_key_in = {};
return \%tokens;
}
sub accept_tokens {
my ($class, $tokens) = @_;
foreach my $known_name (qw(username password access_token)) {
next unless $tokens->{$known_name};
eval "\$$known_name = delete \$tokens->{\$known_name}";
die $@ if $@;
}
foreach my $token_name (keys %$tokens) {
$api_key->{$token_name} = $tokens->{$token_name}->{token};
if ($tokens->{$token_name}->{prefix}) {
$api_key_prefix->{$token_name} = $tokens->{$token_name}->{prefix};
}
my $in = $tokens->{$token_name}->{in} || 'head';
croak "Tokens can only go in 'head' or 'query' (not in '$in')" unless $in =~ /^(?:head|query)$/;
$api_key_in->{$token_name} = $in;
}
}
1;

View File

@ -106,7 +106,7 @@ sub update_pet {
}
# authentication setting, if any
my $auth_settings = ['petstore_auth'];
my $auth_settings = [qw(petstore_auth )];
# make the API Call
@ -170,7 +170,7 @@ sub add_pet {
}
# authentication setting, if any
my $auth_settings = ['petstore_auth'];
my $auth_settings = [qw(petstore_auth )];
# make the API Call
@ -234,7 +234,7 @@ sub find_pets_by_status {
# authentication setting, if any
my $auth_settings = ['petstore_auth'];
my $auth_settings = [qw(petstore_auth )];
# make the API Call
my $response = $self->{api_client}->call_api($_resource_path, $_method,
@ -301,7 +301,7 @@ sub find_pets_by_tags {
# authentication setting, if any
my $auth_settings = ['petstore_auth'];
my $auth_settings = [qw(petstore_auth )];
# make the API Call
my $response = $self->{api_client}->call_api($_resource_path, $_method,
@ -375,7 +375,7 @@ sub get_pet_by_id {
# authentication setting, if any
my $auth_settings = ['api_key'];
my $auth_settings = [qw(api_key )];
# make the API Call
my $response = $self->{api_client}->call_api($_resource_path, $_method,
@ -471,7 +471,7 @@ sub update_pet_with_form {
# authentication setting, if any
my $auth_settings = ['petstore_auth'];
my $auth_settings = [qw(petstore_auth )];
# make the API Call
@ -551,7 +551,7 @@ sub delete_pet {
# authentication setting, if any
my $auth_settings = ['petstore_auth'];
my $auth_settings = [qw(petstore_auth )];
# make the API Call
@ -645,7 +645,7 @@ sub upload_file {
# authentication setting, if any
my $auth_settings = ['petstore_auth'];
my $auth_settings = [qw(petstore_auth )];
# make the API Call

View File

@ -8,19 +8,32 @@ use Log::Any qw($log);
use WWW::SwaggerClient::ApiFactory;
has base_url => ( is => 'ro',
required => 0,
isa => 'Str',
);
required => 0,
isa => 'Str',
);
has api_factory => ( is => 'ro',
isa => 'WWW::SwaggerClient::ApiFactory',
builder => '_build_af',
lazy => 1,
);
has tokens => ( is => 'ro',
isa => 'HashRef',
required => 0,
default => sub {{}}, # !
);
has _cfg => ( is => 'ro',
isa => 'Str',
default => 'WWW::SwaggerClient::Configuration',
);
sub BUILD {
my $self = shift;
$self->_cfg->accept_tokens( $self->tokens ) if keys %{$self->tokens};
# ignore these symbols imported into API namespaces
my %outsiders = map {$_ => 1} qw( croak );
@ -93,7 +106,7 @@ role.
package main;
my $api = MyApp->new;
my $api = MyApp->new({ tokens => $tokens });
my $pet = $api->get_pet_by_id(pet_id => $pet_id);
@ -115,14 +128,40 @@ For documentation of all these methods, see AUTOMATIC DOCUMENTATION below.
=head2 Configuring authentication
If your Swagger spec does not describe authentication, you can write an
C<auth_setup_handler()> method in your base class to handle it (see below).
In the normal case, the Swagger spec will describe what parameters are
required and where to put them. You just need to supply the tokens.
In the normal case, the Swagger spec will describe what parameters are required
and where to put them. You just need to supply the authorization tokens.
my $tokens = {
# basic
username => $username,
password => $password,
# oauth
access_token => $oauth_token,
# keys
$some_key => { token => $token,
prefix => $prefix,
in => $in, # 'head||query',
},
$another => { token => $token,
prefix => $prefix,
in => $in, # 'head||query',
},
...,
};
my $api = MyApp->new({ tokens => $tokens });
These should go in the C<WWW::SwaggerClient::Configuration> namespace as follows.
Note these are all optional, and depend on the API you are accessing.
Note these are all optional, as are C<prefix> and C<in>, and depend on the API
you are accessing. Usually C<prefix> and C<in> will be determined by the code generator from
the spec and you will not need to set them at run time. If not, C<in> will
default to 'head' and C<prefix> to the empty string.
The tokens will be placed in the C<WWW::SwaggerClient::Configuration> namespace
as follows, but you don't need to know about this.
=over 4
@ -161,68 +200,19 @@ String. The OAuth access token.
=head1 METHODS
=head2 C<auth_setup_handler()>
This method does not exist! But if you add it to the class that consumes this
role, it will be called to set up authentication.
package MyApp;
use Moose;
with 'WWW::SwaggerClient::Role';
sub auth_setup_handler {
my ($self, %p) = @_;
$p{header_params}->{'X-TargetApp-apiKey'} = $api_key;
$p{header_params}->{'X-TargetApp-secretKey'} = $secret_key;
}
# somewhere else...
my $api = MyApp->new;
my $pet = $api->get_pet_by_id(pet_id => $pet_id);
So, C<auth_setup_handler()> will be called on your C<$api> object and passed the
following parameters:
=over 4
=item C<header_params>
A hashref that will become the request headers. You can insert auth
parameters.
=item C<query_params>
A hashref that will be encoded into the request URL. You can insert auth
parameters.
=item C<auth_settings>
TODO. Probably not necessary?
=item C<api_client>
A reference to the C<WWW::SwaggerClient::ApiClient> object that is responsible
for communicating with the server. Just in case that's useful.
=back
=head2 base_url
=head2 C<base_url>
The generated code has the C<base_url> already set as a default value. This method
returns (and optionally sets, but only if the API client has not been
created yet) the current value of C<base_url>.
=head2 api_factory
=head2 C<api_factory>
Returns an API factory object. You probably won't need to call this directly.
$self->api_factory('Pet'); # returns a WWW::SwaggerClient::PetApi instance
$self->pet_api; # the same
$self->pet_api; # the same
=head1 MISSING METHODS
@ -280,13 +270,13 @@ Additional documentation for each class and method may be provided by the Swagge
spec. If so, this is available via the C<class_documentation()> and
C<method_documentation()> methods on each generated API and class:
my $cdoc = $api->pet_api->class_documentation;
my $cdoc = $api->pet_api->class_documentation;
my $cmdoc = $api->pet_api->method_documentation->{$method_name};
my $odoc = $api->get_pet_by_id->(pet_id => $pet_id)->class_documentation;
my $odoc = $api->get_pet_by_id->(pet_id => $pet_id)->class_documentation;
my $omdoc = $api->get_pet_by_id->(pet_id => $pet_id)->method_documentation->{method_name};
Each of these calls returns a hashref with various useful pieces of information.
Each of these calls returns a hashref with various useful pieces of information.
=cut

View File

@ -97,7 +97,7 @@ sub get_inventory {
# authentication setting, if any
my $auth_settings = ['api_key'];
my $auth_settings = [qw(api_key )];
# make the API Call
my $response = $self->{api_client}->call_api($_resource_path, $_method,
@ -164,7 +164,7 @@ sub place_order {
}
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
my $response = $self->{api_client}->call_api($_resource_path, $_method,
@ -238,7 +238,7 @@ sub get_order_by_id {
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
my $response = $self->{api_client}->call_api($_resource_path, $_method,
@ -312,7 +312,7 @@ sub delete_order {
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call

View File

@ -106,7 +106,7 @@ sub create_user {
}
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
@ -170,7 +170,7 @@ sub create_users_with_array_input {
}
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
@ -234,7 +234,7 @@ sub create_users_with_list_input {
}
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
@ -307,7 +307,7 @@ sub login_user {
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
my $response = $self->{api_client}->call_api($_resource_path, $_method,
@ -365,7 +365,7 @@ sub logout_user {
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
@ -436,7 +436,7 @@ sub get_user_by_name {
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
my $response = $self->{api_client}->call_api($_resource_path, $_method,
@ -519,7 +519,7 @@ sub update_user {
}
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
@ -590,7 +590,7 @@ sub delete_user {
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call

View File

@ -1,4 +1,4 @@
use Test::More tests => 21;
use Test::More tests => 29;
use Test::Exception;
use Test::Warnings 'warnings';
use Test::Deep;
@ -15,7 +15,7 @@ SKIP: {
sub auth_setup_handler {}
";
skip 'Moose not installed', 21 if $@;
skip 'Moose not installed', 29 if $@;
my $api;
@ -76,5 +76,65 @@ my $pet_class_doco = { 'description' => '' };
is_deeply($get_pet->class_documentation, $pet_class_doco, 'Pet object class_documentation is available');
# / documentation tests
my $tokens = {
username => 'UserName',
password => 'PassWord',
access_token => 'OAuth_token',
someKey => { token => 'some_key_token',
prefix => 'some_key_prefix',
in => 'query',
},
anotherKey => { token => 'another_key_token',
},
};
$api->_cfg->accept_tokens({%$tokens}); # pass a copy
no warnings 'once';
is $WWW::SwaggerClient::Configuration::username, 'UserName', 'accept_tokens() correctly set the username';
is $WWW::SwaggerClient::Configuration::password, 'PassWord', 'accept_tokens() correctly set the password';
is $WWW::SwaggerClient::Configuration::access_token, 'OAuth_token', 'accept_tokens() correctly set the oauth';
my $api_key_href = {
'anotherKey' => 'another_key_token',
'someKey' => 'some_key_token'
};
cmp_deeply( $WWW::SwaggerClient::Configuration::api_key, $api_key_href, 'accept_tokens() correctly set api_key' );
my $api_key_prefix_href = {
'someKey' => 'some_key_prefix'
};
cmp_deeply( $WWW::SwaggerClient::Configuration::api_key_prefix, $api_key_prefix_href, 'accept_tokens() correctly set api_key_prefix' );
my $api_key_in = {
'someKey' => 'query',
'anotherKey' => 'head'
};
cmp_deeply( $WWW::SwaggerClient::Configuration::api_key_in, $api_key_in, 'accept_tokens() correctly set api_key_in' );
use warnings 'once';
my $cleared_tokens_cmp = {
'anotherKey' => {
'in' => 'head',
'token' => 'another_key_token',
'prefix' => undef
},
'access_token' => 'OAuth_token',
'someKey' => {
'token' => 'some_key_token',
'in' => 'query',
'prefix' => 'some_key_prefix'
},
'username' => 'UserName',
'password' => 'PassWord'
};
cmp_deeply( $api->_cfg->clear_tokens, $cleared_tokens_cmp, 'clear_tokens() returns the correct data structure' );
my $bad_token = { bad_token_name => 'bad token value' }; # value should should be hashref
dies_ok { $api->_cfg->accept_tokens($bad_token) } "bad token causes exception";
} # / SKIP