#5 Moved API handling into its own class

This commit is contained in:
Sebastian Henschel 2016-11-21 08:40:39 +01:00
parent a6afc5f608
commit c36a76fc7a
6 changed files with 82 additions and 76 deletions

67
apimanager/base/api.py Normal file
View File

@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
from datetime import datetime
import logging
import time
from requests_oauthlib import OAuth1Session
from django.conf import settings
DATE_FORMAT = '%d/%b/%Y %H:%M:%S'
LOGGER = logging.getLogger(__name__)
class API(object):
def log(self, level, message):
now = datetime.now().strftime(DATE_FORMAT)
msg = '[{}] API: {}'.format(now, message)
LOGGER.log(level, msg)
def get(self, request, urlpath=''):
return self.call(request, 'GET', urlpath)
def delete(self, request, urlpath):
return self.call(request, 'DELETE', urlpath)
def post(self, request, urlpath, payload):
return self.call(request, 'POST', urlpath, payload)
def put(self, request, urlpath, payload):
return self.call(request, 'PUT', urlpath, payload)
def call(self, request, method='GET', urlpath='', payload=None):
url = settings.OAUTH_API + settings.OAUTH_API_BASE_PATH + urlpath
self.log(logging.INFO, '{} {}'.format(method, url))
if not hasattr(request, 'api'):
request.api = OAuth1Session(
settings.OAUTH_CONSUMER_KEY,
client_secret=settings.OAUTH_CONSUMER_SECRET,
resource_owner_key=request.session['oauth_token'],
resource_owner_secret=request.session['oauth_secret']
)
time_start = time.time()
if payload:
response = request.api.request(method, url, json=payload)
else:
response = request.api.request(method, url)
time_end = time.time()
elapsed = int((time_end - time_start) * 1000)
self.log(logging.INFO, 'Took {} ms'.format(elapsed))
if response.status_code in [404, 500]:
msg = 'Ran into a {}: {}'.format(response.status_code, response.text)
self.log(logging.ERROR, msg)
data = response.text
elif response.status_code in [204]:
data = response.text
else:
data = response.json()
return data
api = API()

View File

@ -2,7 +2,7 @@
from django.conf import settings
from base.utils import api_get
from base.api import api
def api_root(request):
@ -10,7 +10,7 @@ def api_root(request):
def api_username(request):
if request.user.is_authenticated:
data = api_get(request, '/users/current')
data = api.get(request, '/users/current')
api_username = data['username']
else:
api_username = 'not authenticated'

View File

@ -1,18 +1,9 @@
# -*- coding: utf-8 -*-
from datetime import datetime
import logging
import time
from requests_oauthlib import OAuth1Session
from django.conf import settings
from django.contrib.humanize.templatetags.humanize import naturaltime
DATE_FORMAT = '%d/%b/%Y %H:%M:%S'
LOGGER = logging.getLogger(__name__)
def json_serial(obj):
"""JSON serializer for objects not serializable by default json code"""
@ -20,56 +11,3 @@ def json_serial(obj):
serial = naturaltime(obj)
return serial
raise TypeError('Type not serializable')
def api_log(level, message):
now = datetime.now().strftime(DATE_FORMAT)
msg = '[{}] API: {}'.format(now, message)
LOGGER.log(level, msg)
def api_get(request, urlpath=''):
return api_call(request, 'GET', urlpath)
def api_delete(request, urlpath):
return api_call(request, 'DELETE', urlpath)
def api_post(request, urlpath, payload):
return api_call(request, 'POST', urlpath, payload)
def api_put(request, urlpath, payload):
return api_call(request, 'PUT', urlpath, payload)
def api_call(request, method='GET', urlpath='', payload=None):
url = settings.OAUTH_API + settings.OAUTH_API_BASE_PATH + urlpath
api_log(logging.INFO, '{} {}'.format(method, url))
if not hasattr(request, 'api'):
request.api = OAuth1Session(
settings.OAUTH_CONSUMER_KEY,
client_secret=settings.OAUTH_CONSUMER_SECRET,
resource_owner_key=request.session['oauth_token'],
resource_owner_secret=request.session['oauth_secret']
)
time_start = time.time()
if payload:
response = request.api.request(method, url, json=payload)
else:
response = request.api.request(method, url)
time_end = time.time()
elapsed = int((time_end - time_start) * 1000)
api_log(logging.INFO, 'Took {} ms'.format(elapsed))
if response.status_code in [404, 500]:
msg = 'Ran into a {}: {}'.format(response.status_code, response.text)
api_log(logging.ERROR, msg)
data = response.text
elif response.status_code in [204]:
data = response.text
else:
data = response.json()
return data

View File

@ -9,8 +9,9 @@ from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse
from django.views.generic import TemplateView, RedirectView
from base.api import api
from base.filters import BaseFilter, FilterTime
from base.utils import json_serial, api_get, api_put, api_post
from base.utils import json_serial
@ -45,7 +46,7 @@ class IndexView(LoginRequiredMixin, TemplateView):
context = super(IndexView, self).get_context_data(**kwargs)
filtered = []
urlpath = '/management/consumers'
consumers = api_get(self.request, urlpath)
consumers = api.get(self.request, urlpath)
if not isinstance(consumers, dict):
messages.error(self.request, consumers)
@ -77,7 +78,7 @@ class DetailView(LoginRequiredMixin, TemplateView):
def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs)
urlpath = '/management/consumers/{}'.format(kwargs['consumer_id'])
consumer = api_get(self.request, urlpath)
consumer = api.get(self.request, urlpath)
if not isinstance(consumer, dict):
messages.error(self.request, consumer)
@ -98,7 +99,7 @@ class EnableDisableView(LoginRequiredMixin, RedirectView):
def get_redirect_url(self,*args, **kwargs):
urlpath = '/management/consumers/{}'.format(kwargs['consumer_id'])
payload = {'enabled': self.enabled}
result = api_put(self.request, urlpath, payload)
result = api.put(self.request, urlpath, payload)
if 'error' in result:
messages.error(self.request, result['error'])
else:

View File

@ -10,7 +10,7 @@ from django.views.generic import RedirectView
from requests_oauthlib import OAuth1Session
from base.utils import api_get
from base.api import api
class InitiateView(RedirectView):
@ -48,7 +48,7 @@ class InitiateView(RedirectView):
class AuthorizeView(RedirectView):
def login_to_django(self):
# Kind of faking it to establish if a user is authenticated later on
data = api_get(self.request, '/users/current')
data = api.get(self.request, '/users/current')
userid = data['user_id'] or data['email']
username = hashlib.sha256(userid.encode('utf-8')).hexdigest()
password = username

View File

@ -12,7 +12,7 @@ from django.urls import reverse
from django.views.generic import TemplateView, RedirectView, View
from base.filters import BaseFilter
from base.utils import api_get, api_post, api_delete
from base.api import api
class FilterRoleName(BaseFilter):
@ -32,7 +32,7 @@ class IndexView(LoginRequiredMixin, TemplateView):
role_names = []
filtered = []
urlpath = '/users'
users = api_get(self.request, urlpath)
users = api.get(self.request, urlpath)
if not isinstance(users, dict):
messages.error(self.request, users)
@ -67,14 +67,14 @@ class DetailView(LoginRequiredMixin, TemplateView):
# NOTE: assuming there is just one user with that email address
# The API actually needs a 'get user by id'
urlpath = '/users/{}'.format(kwargs['user_email'])
users = api_get(self.request, urlpath)
users = api.get(self.request, urlpath)
user = {}
if 'error' in users:
messages.error(self.request, users['error'])
elif len(users['users']) > 0:
user = users['users'][0]
urlpath = '/users/{}/entitlements'.format(user['user_id'])
entitlements = api_get(self.request, urlpath)
entitlements = api.get(self.request, urlpath)
if 'error' in entitlements:
messages.error(self.request, entitlements['error'])
else:
@ -93,7 +93,7 @@ class AddEntitlementView(LoginRequiredMixin, View):
'bank_id': request.POST['bank_id'],
'role_name': request.POST['role_name'],
}
entitlement = api_post(request, urlpath, payload=payload)
entitlement = api.post(request, urlpath, payload=payload)
if not isinstance(entitlement, dict):
messages.error(request, entitlement)
elif 'error' in entitlement:
@ -113,7 +113,7 @@ class DeleteEntitlementView(LoginRequiredMixin, View):
def post(self, request, *args, **kwargs):
urlpath = '/users/{}/entitlement/{}'.format(
kwargs['user_id'], kwargs['entitlement_id'])
result = api_delete(request, urlpath)
result = api.delete(request, urlpath)
if 'error' in result:
messages.error(request, result['error'])
else: