From b09250ed333857f30c503fc6028d60371712a325 Mon Sep 17 00:00:00 2001 From: geekerzp Date: Wed, 27 May 2015 17:07:43 +0800 Subject: [PATCH] added authentication for python client. completed. --- .../src/main/resources/python/api.mustache | 5 +- .../src/main/resources/python/config.mustache | 49 ++++++++++++++++++- .../main/resources/python/swagger.mustache | 36 +++++++------- .../SwaggerPetstore/apis/pet_api.py | 40 ++++++++++++--- .../SwaggerPetstore/apis/store_api.py | 20 ++++++-- .../SwaggerPetstore/apis/user_api.py | 40 ++++++++++++--- .../SwaggerPetstore/config.py | 40 +++++++++++++-- .../SwaggerPetstore/swagger.py | 27 +++++++++- .../tests/test_api_client.py | 26 ++++++++++ 9 files changed, 238 insertions(+), 45 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/python/api.mustache b/modules/swagger-codegen/src/main/resources/python/api.mustache index d5e24398f0e..55bfd9e82a4 100644 --- a/modules/swagger-codegen/src/main/resources/python/api.mustache +++ b/modules/swagger-codegen/src/main/resources/python/api.mustache @@ -81,9 +81,12 @@ class {{classname}}(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([{{#consumes}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}]) + # Authentication setting + auth_settings = [{{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}) + response={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, auth_settings=auth_settings) {{#returnType}} return response {{/returnType}}{{/operation}} diff --git a/modules/swagger-codegen/src/main/resources/python/config.mustache b/modules/swagger-codegen/src/main/resources/python/config.mustache index 3063b4ff026..a6de7299cba 100644 --- a/modules/swagger-codegen/src/main/resources/python/config.mustache +++ b/modules/swagger-codegen/src/main/resources/python/config.mustache @@ -1,2 +1,49 @@ +import base64 + + +def get_api_key_with_prefix(key): + global api_key + global api_key_prefix + + if api_key_prefix[key]: + return api_key_prefix[key] + ' ' + api_key[key] + else: + return api_key[key] + +def get_basic_auth_token(): + global username + global password + + return base64.base64encode('Basic ' + username + password) + +def auth_settings(): + return { {{#authMethods}}{{#isApiKey}} + '{{name}}': { + 'type': 'api_key', + 'in': {{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}}, + 'key': '{{keyParamName}}', + 'value': get_api_key_with_prefix('{{keyParamName}}') + }, + {{/isApiKey}}{{#isBasic}} + '{{name}}': { + 'type': 'basic', + 'in': 'header', + 'key': 'Authorization', + 'value': get_basic_auth_token() + }, + {{/isBasic}}{{/authMethods}} + } + + + # Default Base url -HOST = "{{basePath}}" +host = "{{basePath}}" + +# Authentication settings + +api_key = {} +api_key_prefix = {} +username = '' +password = '' + + diff --git a/modules/swagger-codegen/src/main/resources/python/swagger.mustache b/modules/swagger-codegen/src/main/resources/python/swagger.mustache index b97d4ed515a..bd478820435 100644 --- a/modules/swagger-codegen/src/main/resources/python/swagger.mustache +++ b/modules/swagger-codegen/src/main/resources/python/swagger.mustache @@ -38,7 +38,7 @@ class ApiClient(object): :param header_name: a header to pass when making calls to the API :param header_value: a header value to pass when making calls to the API """ - def __init__(self, host=config.HOST, header_name=None, header_value=None): + def __init__(self, host=config.host, header_name=None, header_value=None): self.default_headers = {} if header_name is not None: self.default_headers[header_name] = header_value @@ -59,7 +59,7 @@ class ApiClient(object): self.default_headers[header_name] = header_value def call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None, - body=None, post_params=None, files=None, response=None): + body=None, post_params=None, files=None, response=None, auth_settings=None): # headers parameters headers = self.default_headers.copy() @@ -86,6 +86,9 @@ class ApiClient(object): post_params = self.prepare_post_parameters(post_params, files) post_params = self.sanitize_for_serialization(post_params) + # auth setting + self.update_params_for_auth(header_params, query_params, auth_settings) + # body if body: body = self.sanitize_for_serialization(body) @@ -281,22 +284,21 @@ class ApiClient(object): else: return content_types[0] - def get_api_key_with_prefix(api_key): - """ - Get API key (with prefix if possible) - """ - if config.api_prefix[api_key]: - return config.api_prefix[api_key] + config.api_key[api_key] - else: - return config.api_key[api_key] - - def update_params_for_auth(headers, querys, auths): + def update_params_for_auth(self, headers, querys, auth_settings): """ Update header and query params based on authentication setting """ - auths_map = { - {{#authMethods}} - - {{/authMethods}} - } + if not auth_settings: + return + + for auth in auth_settings: + auth_setting = config.auth_settings().get(auth) + if auth_setting: + if auth_setting['in'] == 'header': + headers[auth_setting['key']] = auth_setting['value'] + elif auth_setting['in'] == 'query': + querys[auth_setting['key']] = auth_setting['value'] + else: + raise ValueError('Authentication token must be in `query` or `header`') + diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py index ad4bad57412..37da9901597 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py @@ -76,9 +76,12 @@ class PetApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type(['application/json', 'application/xml']) + # Authentication setting + auth_settings = ['petstore_auth'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def add_pet(self, **kwargs): """ @@ -117,9 +120,12 @@ class PetApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type(['application/json', 'application/xml']) + # Authentication setting + auth_settings = ['petstore_auth'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def find_pets_by_status(self, **kwargs): """ @@ -158,9 +164,12 @@ class PetApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = ['petstore_auth'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='list[Pet]') + response='list[Pet]', auth_settings=auth_settings) return response @@ -201,9 +210,12 @@ class PetApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = ['petstore_auth'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='list[Pet]') + response='list[Pet]', auth_settings=auth_settings) return response @@ -248,9 +260,12 @@ class PetApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = ['api_key', 'petstore_auth'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='Pet') + response='Pet', auth_settings=auth_settings) return response @@ -297,9 +312,12 @@ class PetApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type(['application/x-www-form-urlencoded']) + # Authentication setting + auth_settings = ['petstore_auth'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def delete_pet(self, pet_id, **kwargs): """ @@ -343,9 +361,12 @@ class PetApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = ['petstore_auth'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def upload_file(self, pet_id, **kwargs): """ @@ -390,9 +411,12 @@ class PetApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type(['multipart/form-data']) + # Authentication setting + auth_settings = ['petstore_auth'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py index e973d3a6ba5..649cb5f704d 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py @@ -75,9 +75,12 @@ class StoreApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = ['api_key'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='map(String, int)') + response='map(String, int)', auth_settings=auth_settings) return response @@ -118,9 +121,12 @@ class StoreApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='Order') + response='Order', auth_settings=auth_settings) return response @@ -165,9 +171,12 @@ class StoreApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='Order') + response='Order', auth_settings=auth_settings) return response @@ -212,9 +221,12 @@ class StoreApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py index 82874000d59..3f2b36a85fa 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py @@ -76,9 +76,12 @@ class UserApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def create_users_with_array_input(self, **kwargs): """ @@ -117,9 +120,12 @@ class UserApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def create_users_with_list_input(self, **kwargs): """ @@ -158,9 +164,12 @@ class UserApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def login_user(self, **kwargs): """ @@ -200,9 +209,12 @@ class UserApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='str') + response='str', auth_settings=auth_settings) return response @@ -242,9 +254,12 @@ class UserApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def get_user_by_name(self, username, **kwargs): """ @@ -287,9 +302,12 @@ class UserApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='User') + response='User', auth_settings=auth_settings) return response @@ -335,9 +353,12 @@ class UserApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def delete_user(self, username, **kwargs): """ @@ -380,9 +401,12 @@ class UserApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/config.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/config.py index 6e158eedd70..edcee6fe90b 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/config.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/config.py @@ -1,8 +1,40 @@ -from __future__ import absolute_import +import base64 -from .swagger import ApiClient -# Configuration variables +def get_api_key_with_prefix(key): + global api_key + global api_key_prefix -api_client = ApiClient("http://petstore.swagger.io/v2") + if api_key_prefix[key]: + return api_key_prefix[key] + ' ' + api_key[key] + else: + return api_key[key] +def get_basic_auth_token(): + global username + global password + + return base64.base64encode('Basic ' + username + password) + +def auth_settings(): + return { + 'api_key': { + 'type': 'api_key', + 'in': 'header', + 'key': 'api_key', + 'value': get_api_key_with_prefix('api_key') + }, + + } + + + +# Default Base url +host = "http://petstore.swagger.io/v2" + +# Authentication settings + +api_key = {} +api_key_prefix = {} +username = '' +password = '' diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/swagger.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/swagger.py index 21430c469c8..bd478820435 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/swagger.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/swagger.py @@ -28,6 +28,7 @@ except ImportError: # for python2 from urllib import quote +from . import config class ApiClient(object): """ @@ -37,7 +38,7 @@ class ApiClient(object): :param header_name: a header to pass when making calls to the API :param header_value: a header value to pass when making calls to the API """ - def __init__(self, host=None, header_name=None, header_value=None): + def __init__(self, host=config.host, header_name=None, header_value=None): self.default_headers = {} if header_name is not None: self.default_headers[header_name] = header_value @@ -58,7 +59,7 @@ class ApiClient(object): self.default_headers[header_name] = header_value def call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None, - body=None, post_params=None, files=None, response=None): + body=None, post_params=None, files=None, response=None, auth_settings=None): # headers parameters headers = self.default_headers.copy() @@ -85,6 +86,9 @@ class ApiClient(object): post_params = self.prepare_post_parameters(post_params, files) post_params = self.sanitize_for_serialization(post_params) + # auth setting + self.update_params_for_auth(header_params, query_params, auth_settings) + # body if body: body = self.sanitize_for_serialization(body) @@ -279,3 +283,22 @@ class ApiClient(object): return 'application/json' else: return content_types[0] + + def update_params_for_auth(self, headers, querys, auth_settings): + """ + Update header and query params based on authentication setting + """ + if not auth_settings: + return + + for auth in auth_settings: + auth_setting = config.auth_settings().get(auth) + if auth_setting: + if auth_setting['in'] == 'header': + headers[auth_setting['key']] = auth_setting['value'] + elif auth_setting['in'] == 'query': + querys[auth_setting['key']] = auth_setting['value'] + else: + raise ValueError('Authentication token must be in `query` or `header`') + + diff --git a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_client.py b/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_client.py index 5243430a93a..6bc3000f267 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_client.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_client.py @@ -12,6 +12,7 @@ import time import unittest import SwaggerPetstore +import SwaggerPetstore.config HOST = 'http://petstore.swagger.io/v2' @@ -21,6 +22,31 @@ class ApiClientTests(unittest.TestCase): def setUp(self): self.api_client = SwaggerPetstore.ApiClient(HOST) + def test_configuratjion(self): + SwaggerPetstore.config.api_key['api_key'] = '123456' + SwaggerPetstore.config.api_key_prefix['api_key'] = 'PREFIX' + SwaggerPetstore.config.username = 'test_username' + SwaggerPetstore.config.password = 'test_password' + + header_params = {'test1': 'value1'} + query_params = {'test2': 'value2'} + auth_settings = ['api_key', 'unknown'] + + # test prefix + self.assertEqual('PREFIX', SwaggerPetstore.config.api_key_prefix['api_key']) + + # update parameters based on auth setting + self.api_client.update_params_for_auth(header_params, query_params, auth_settings) + + # test api key auth + self.assertEqual(header_params['test1'], 'value1') + self.assertEqual(header_params['api_key'], 'PREFIX 123456') + self.assertEqual(query_params['test2'], 'value2') + + # test basic auth + self.assertEqual('test_username', SwaggerPetstore.config.username) + self.assertEqual('test_password', SwaggerPetstore.config.password) + def test_select_header_accept(self): accepts = ['APPLICATION/JSON', 'APPLICATION/XML'] accept = self.api_client.select_header_accept(accepts)