mirror of
https://github.com/OpenBankProject/API-Manager.git
synced 2026-02-06 16:21:51 +00:00
178 lines
6.2 KiB
Python
178 lines
6.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
Module to handle the OBP API
|
|
|
|
It instantiates a convenience api object for imports, e.g.:
|
|
from obp.api import api
|
|
"""
|
|
|
|
from datetime import datetime
|
|
import importlib
|
|
import logging
|
|
import time
|
|
|
|
import requests
|
|
from requests.exceptions import ConnectionError
|
|
|
|
from django.conf import settings
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
DATE_FORMAT = '%d/%b/%Y %H:%M:%S'
|
|
LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
def log(level, message):
|
|
"""Logs a given message on a given level to log facility"""
|
|
now = datetime.now().strftime(DATE_FORMAT)
|
|
msg = '[{}] API: {}'.format(now, message)
|
|
LOGGER.log(level, msg)
|
|
|
|
|
|
class APIError(Exception):
|
|
"""Exception class for API errors"""
|
|
pass
|
|
|
|
|
|
class API(object):
|
|
"""Implements an interface to the OBP API"""
|
|
session = None
|
|
swagger = None
|
|
|
|
def __init__(self, session_data=None):
|
|
if session_data:
|
|
self.start_session(session_data)
|
|
self.session_data = session_data
|
|
|
|
def call(self, method='GET', url='', payload=None, version=settings.API_VERSION['v500']):
|
|
"""Workhorse which actually calls the API"""
|
|
log(logging.INFO, '{} {}'.format(method, url))
|
|
if payload:
|
|
log(logging.INFO, 'Payload: {}'.format(payload))
|
|
# use `requests` if no session has been started
|
|
session = self.session or requests
|
|
time_start = time.time()
|
|
try:
|
|
if payload:
|
|
response = session.request(method, url, json=payload, verify=settings.VERIFY)
|
|
else:
|
|
response = session.request(method, url, json={}, verify=settings.VERIFY)
|
|
except ConnectionError as err:
|
|
raise APIError(err)
|
|
time_end = time.time()
|
|
elapsed = int((time_end - time_start) * 1000)
|
|
log(logging.INFO, 'Took {} ms'.format(elapsed))
|
|
response.execution_time = elapsed
|
|
return response
|
|
|
|
def get(self, urlpath='', version=settings.API_VERSION['v500']):
|
|
"""
|
|
Gets data from the API
|
|
|
|
Convenience call which uses API_VERSION from settings
|
|
"""
|
|
url = version + urlpath
|
|
response = self.handle_response(self.call('GET', url))
|
|
if response is not None and 'code' in response:
|
|
raise APIError(response['message'])
|
|
else:
|
|
return response
|
|
|
|
def delete(self, urlpath, version=settings.API_VERSION['v500']):
|
|
"""
|
|
Deletes data from the API
|
|
|
|
Convenience call which uses API_VERSION from settings
|
|
"""
|
|
url = version + urlpath
|
|
response = self.call('DELETE', url)
|
|
return self.handle_response(response)
|
|
|
|
def post(self, urlpath, payload, version=settings.API_VERSION['v500']):
|
|
"""
|
|
Posts data to given urlpath with given payload
|
|
|
|
Convenience call which uses API_VERSION from settings
|
|
"""
|
|
url = version + urlpath
|
|
response = self.call('POST', url, payload)
|
|
return self.handle_response(response)
|
|
|
|
def put(self, urlpath, payload, version=settings.API_VERSION['v500']):
|
|
"""
|
|
Puts data on given urlpath with given payload
|
|
|
|
Convenience call which uses API_VERSION from settings
|
|
"""
|
|
url = version + urlpath
|
|
response = self.call('PUT', url, payload)
|
|
return self.handle_response(response)
|
|
|
|
def handle_response_error(self, prefix, error):
|
|
if 'Invalid or expired access token' in error:
|
|
raise APIError(error)
|
|
msg = '{} {}'.format(prefix, error)
|
|
raise APIError(msg)
|
|
|
|
def handle_response(self, response):
|
|
"""Handles the response, e.g. errors or conversion to JSON"""
|
|
prefix = 'APIError'
|
|
if response.status_code in [204]:
|
|
return response.text
|
|
else:
|
|
data = response.json()
|
|
if isinstance(data,dict) and 'error' in data:
|
|
self.handle_response_error(prefix, data['error'])
|
|
return data
|
|
|
|
def start_session(self, session_data):
|
|
"""
|
|
Starts a session with given session_data:
|
|
- Authenticator class name (e.g. obp.oauth.OAuthAuthenticator)
|
|
- Token data
|
|
for subsequent requests to the API
|
|
"""
|
|
if 'authenticator' in session_data and\
|
|
'authenticator_kwargs' in session_data:
|
|
mod_name, cls_name = session_data['authenticator'].rsplit('.', 1)
|
|
log(logging.INFO, 'Authenticator {}'.format(cls_name))
|
|
cls = getattr(importlib.import_module(mod_name), cls_name)
|
|
authenticator = cls(**session_data['authenticator_kwargs'])
|
|
self.session = authenticator.get_session()
|
|
return self.session
|
|
else:
|
|
return None
|
|
|
|
""" def get_swagger(self):
|
|
Gets the swagger definition from the API
|
|
# Poor man's caching ...
|
|
if not self.session_data.get('swagger'):
|
|
# API throws 500 if authenticated via GatewayLogin ...
|
|
# response = self.call('GET', settings.API_URL_SWAGGER)
|
|
response = requests.get(settings.API_URL_SWAGGER)
|
|
swagger = self.handle_response(response)
|
|
self.session_data['swagger'] = swagger
|
|
return self.session_data.get('swagger') """
|
|
|
|
def get_bank_id_choices(self):
|
|
"""Gets a list of bank ids and bank ids as used by form choices"""
|
|
choices = [('', _('Choose ...'))]
|
|
result = self.get('/banks')
|
|
for bank in sorted(result['banks'], key=lambda d: d['id']) :
|
|
choices.append((bank['id'], bank['id']))
|
|
return choices
|
|
|
|
def get_api_version_choices(self):
|
|
"""Gets a list of APIs Version and APIs Version as used by form choices"""
|
|
choices = [('', _('Choose ...'))]
|
|
result = self.get('/api/versions')
|
|
for version in sorted(result['scanned_api_versions'], key=lambda d: d['API_VERSION']) :
|
|
choices.append((version['API_VERSION'], version['API_VERSION']))
|
|
return choices
|
|
|
|
def get_user_id_choices(self):
|
|
"""Gets a list of user ids and usernames as used by form choices"""
|
|
choices = [('', _('Choose ...'))]
|
|
result = self.get('/users')
|
|
for user in result['users']:
|
|
choices.append((user['user_id'], user['username']))
|
|
return choices |