diff --git a/README.md b/README.md index 0a34de6..31aad70 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ or maybe upgrade dependency version, If still facing issue to run **pip install ├── static-collected └── venv ``` -6. Then, update information in local_setting.py file, the example is below for updating information. For this file, required **OAUTH_CONSUMER_KEY** and **OAUTH_CONSUMER_SECRET** to run this app. For this purpose, must be OBP-API running locally. Follow these steps to run [OBP-API Local](https://github.com/OpenBankProject/OBP-API). +6. Then, update information in local_setting.py file, the example is below for updating information. For this file, required **OAUTH_CONSUMER_KEY** and **OAUTH_CONSUMER_SECRET** to run this app. For this purpose, must be OBP-API running locally. Follow these steps to run [OBP-API Local](https://github.com/OpenBankProject/OBP-API). ```python @@ -137,6 +137,13 @@ DATABASE = { "PORT": "5432", } } + +# This is an optional setting. +# CALLBACK_BASE_URL can be used to explicitly set the redirect base url that API Manager uses during OAuth authentication. +# If CALLBACK_BASE_URL is not set, API Manager (this applicaiton) in the function "get_redirect_url" will use the Django HTTP_HOST environ field (see here: https://docs.djangoproject.com/en/4.1/ref/request-response/). Note, this might be modified by NGINX via the directive: proxy_set_header Host $http_host; +# In order to be explicit you can set it here e.g. +# CALLBACK_BASE_URL="https://apimanager.example.com" + ``` @@ -220,9 +227,9 @@ EXCLUDE_URL_PATTERN = [] API_EXPLORER_APP_NAME = 'xxx' #Map Java: yyyy-MM-dd'T'HH:mm'Z' -API_DATETIMEFORMAT = '%Y-%m-%dT%H:%M:%SZ' +API_DATE_TIME_FORMAT = '%Y-%m-%dT%H:%M:%SZ' #Map Java: yyyy-MM-dd'T'HH:mm:ss.SSS'Z' -API_DATEFORMAT = '%Y-%m-%dT%H:%M:%S.000Z' +API_DATE_FORMAT = '%Y-%m-%dT%H:%M:%S.000Z' ``` diff --git a/apimanager/accountlist/__init__.py b/apimanager/accountlist/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apimanager/accountlist/admin.py b/apimanager/accountlist/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/apimanager/accountlist/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/apimanager/accountlist/apps.py b/apimanager/accountlist/apps.py new file mode 100644 index 0000000..50a7695 --- /dev/null +++ b/apimanager/accountlist/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class AccountConfig(AppConfig): + name = 'account-list' diff --git a/apimanager/accountlist/forms.py b/apimanager/accountlist/forms.py new file mode 100644 index 0000000..e69de29 diff --git a/apimanager/accountlist/models.py b/apimanager/accountlist/models.py new file mode 100644 index 0000000..3b5ea8d --- /dev/null +++ b/apimanager/accountlist/models.py @@ -0,0 +1,4 @@ +from django.db import models + +# Create your models here. +# -*- coding: utf-8 -*- diff --git a/apimanager/accountlist/static/accountlist/css/accountlist.css b/apimanager/accountlist/static/accountlist/css/accountlist.css new file mode 100644 index 0000000..5e85ae8 --- /dev/null +++ b/apimanager/accountlist/static/accountlist/css/accountlist.css @@ -0,0 +1,18 @@ +#accounts_list div { + margin: 5px 0; +} + +/* The actual popup (appears on top) */ +.popuptext { + width: 250px; + background-color: #555; + color: #fff; + text-align: left; + border-radius: 6px; + padding: 8px 0; + z-index: 1; + /*bottom: 125%;*/ + top:100% + left: 50%; + margin-left: -80px; +} diff --git a/apimanager/accountlist/static/accountlist/js/accountlist.js b/apimanager/accountlist/static/accountlist/js/accountlist.js new file mode 100644 index 0000000..e69de29 diff --git a/apimanager/accountlist/templates/accountlist/accountlist.html b/apimanager/accountlist/templates/accountlist/accountlist.html new file mode 100644 index 0000000..99cc0d7 --- /dev/null +++ b/apimanager/accountlist/templates/accountlist/accountlist.html @@ -0,0 +1,43 @@ +{% extends 'base.html' %} {% load static %} {% load i18n %} +{% block page_title %} {{ block.super }} / {% trans "Account List" %}{% endblock page_title %} {% block content %} +
+

{% trans "Account List" %}

+
+ +
+
+ + + + + + + + + {% for account in accounts_list %} + {% url 'account_update' account.id account.bank_id as url_account_update %} + + + + + + + + {% endfor %} + + +
{% trans "Account Id" %}{% trans "Bank Id" %}{% trans "Label" %}{% trans "More info" %}
{{ account.id }}{{ account.bank_id }}{{ account.label }} +
+
    +
  • {% trans "Other Info" %}: +
      +
    • {{account.account_type}}
    • +
    +
  • +
+
+
{% trans "View" %}
+
+
+{% endblock %} {% block extrajs %} {% endblock extrajs %} {% block extracss %} + {% endblock extracss %} \ No newline at end of file diff --git a/apimanager/accountlist/tests.py b/apimanager/accountlist/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/apimanager/accountlist/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/apimanager/accountlist/urls.py b/apimanager/accountlist/urls.py new file mode 100644 index 0000000..66d4b9a --- /dev/null +++ b/apimanager/accountlist/urls.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +""" +URLs for Account list app +""" + +from django.conf.urls import url +from .views import AccountListView, ExportCsvView + +urlpatterns = [ + url(r'^$', + AccountListView.as_view(), + name='account-list'), + url(r'^export_csv$', + ExportCsvView.as_view(), + name='export-csv-account') +] diff --git a/apimanager/accountlist/views.py b/apimanager/accountlist/views.py new file mode 100644 index 0000000..156c905 --- /dev/null +++ b/apimanager/accountlist/views.py @@ -0,0 +1,75 @@ +from django.shortcuts import render + +# Create your views here. +# -*- coding: utf-8 -*- +""" +Views of Account List app +""" +import datetime +from django.contrib import messages +from django.contrib.auth.mixins import LoginRequiredMixin +import json +from django.urls import reverse_lazy +from django.http import HttpResponse +from django.views.generic import FormView,TemplateView, View +from accounts.views import IndexAccountsView +from obp.api import API, APIError +from base.views import get_banks +import csv + +class AccountListView(IndexAccountsView, LoginRequiredMixin, FormView ): + template_name = "accountlist/accountlist.html" + success_url = '/accounts/list' + + def get_accountlist(self, context): + api = API(self.request.session.get('obp')) + try: + #self.bankids = self.get_banks() + accounts_list = [] + #for bank_id in self.bankids: + urlpath = '/my/accounts' + result = api.get(urlpath) + if 'accounts' in result: + accounts_list.extend(result['accounts']) + except APIError as err: + messages.error(self.request, err) + return [] + except Exception as inst: + messages.error(self.request, "Unknown Error {}".format(type(inst).__name__)) + return [] + return accounts_list + def get_context_data(self, **kwargs): + context = super(IndexAccountsView, self).get_context_data(**kwargs) + accounts_list = self.get_accountlist(context) + context.update({ + 'accounts_list': accounts_list, + #'bankids': bankids + }) + return context +class ExportCsvView(LoginRequiredMixin, View): + """View to export the user to csv""" + + def get(self, request, *args, **kwargs): + api = API(self.request.session.get('obp')) + try: + self.bankids = get_banks(self.request) + accounts_list = [] + for bank_id in self.bankids: + urlpath = 'banks/{}/accounts'.format(bank_id) + result = api.get(urlpath) + if 'accounts' in result: + accounts_list.extend(result['accounts']) + except APIError as err: + messages.error(self.request, err) + except Exception as inst: + messages.error(self.request, "Unknown Error {}".format(type(inst).__name__)) + response = HttpResponse(content_type = 'text/csv') + response['Content-Disposition'] = 'attachment;filename= Account'+ str(datetime.datetime.now())+'.csv' + writer = csv.writer(response) + writer.writerow(["id","label","bank_id","account_type","scheme","address","id", "short_name", "description", "is_public"]) + for user in accounts_list: + writer.writerow([user['id'],user['label'], user['bank_id'], user["account_type"], user["scheme"], user["address"], user["views"]['id'], + user["views"]['short_name'], user["views"]['description'], user["views"]['is_public']]) + return response + + diff --git a/apimanager/apicollectionlist/__init__.py b/apimanager/apicollectionlist/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apimanager/apicollectionlist/apps.py b/apimanager/apicollectionlist/apps.py new file mode 100644 index 0000000..3ebc4d0 --- /dev/null +++ b/apimanager/apicollectionlist/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class CustomersConfig(AppConfig): + name = 'customers_list' diff --git a/apimanager/apicollectionlist/forms.py b/apimanager/apicollectionlist/forms.py new file mode 100644 index 0000000..e69de29 diff --git a/apimanager/apicollectionlist/static/apicollectionlist/css/apicollectionlist.css b/apimanager/apicollectionlist/static/apicollectionlist/css/apicollectionlist.css new file mode 100644 index 0000000..38c1c62 --- /dev/null +++ b/apimanager/apicollectionlist/static/apicollectionlist/css/apicollectionlist.css @@ -0,0 +1,18 @@ +#apicollectionlist div { + margin: 5px 0; +} + +/* The actual popup (appears on top) */ +.popuptext { + width: 250px; + background-color: #555; + color: #fff; + text-align: left; + border-radius: 6px; + padding: 8px 0; + z-index: 1; + /*bottom: 125%;*/ + top:100% + left: 50%; + margin-left: -80px; +} diff --git a/apimanager/apicollectionlist/static/apicollectionlist/js/apicollectionlist.js b/apimanager/apicollectionlist/static/apicollectionlist/js/apicollectionlist.js new file mode 100644 index 0000000..e69de29 diff --git a/apimanager/apicollectionlist/templates/apicollectionlist/apicollectionlist.html b/apimanager/apicollectionlist/templates/apicollectionlist/apicollectionlist.html new file mode 100644 index 0000000..45be365 --- /dev/null +++ b/apimanager/apicollectionlist/templates/apicollectionlist/apicollectionlist.html @@ -0,0 +1,49 @@ +{% extends 'base.html' %} {% load static %} {% load i18n %} +{% block page_title %} {{ block.super }} / {% trans "Customer List" %}{% endblock page_title %} {% block content %} +
+

{% trans " All API Collections" %}

+
+ +
+
+ + + + + + + + + {% for apicollection in apicollections_list %} + + {% url 'my-api-collection-detail' apicollection.api_collection_id as url_collection_detail %} + + + + + + + + + {% endfor %} + +
{% trans "API Collection" %}{% trans "User Name" %}{% trans "API Collection Name" %}{% trans "More info" %}
{% if apicollection.api_collection_id %} + Try It + {% endif %}{{ apicollection.username }}{{ apicollection.api_collection_name }} +
+
    +
  • {% trans "Is Sharable" %}: +
      +
    • {{apicollection.is_sharable}}
    • +
    +
  • +
+
+
{% trans "View" %}
+
+
+{% endblock %} +{% block extrajs %} + +{% endblock extrajs %} {% block extracss %} + {% endblock extracss %} \ No newline at end of file diff --git a/apimanager/apicollectionlist/urls.py b/apimanager/apicollectionlist/urls.py new file mode 100644 index 0000000..2b0e83c --- /dev/null +++ b/apimanager/apicollectionlist/urls.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +""" +URLs for Api Collection list app +""" + +from django.conf.urls import url +from .views import ApiCollectionListView, ExportCsvView + +urlpatterns = [ + url(r'^$', + ApiCollectionListView.as_view(), + name='apicollection-list'), + url(r'^export_csv$', + ExportCsvView.as_view(), + name='export-csv-apicollection') +] diff --git a/apimanager/apicollectionlist/views.py b/apimanager/apicollectionlist/views.py new file mode 100644 index 0000000..3c6b125 --- /dev/null +++ b/apimanager/apicollectionlist/views.py @@ -0,0 +1,93 @@ +from django.shortcuts import render + +# Create your views here. +# -*- coding: utf-8 -*- +""" +Views of Api Collection list app +""" +import datetime +from django.contrib import messages +from django.contrib.auth.mixins import LoginRequiredMixin +import json +from django.urls import reverse_lazy +from django.http import HttpResponse +from django.views.generic import FormView,TemplateView, View +from apicollections.views import IndexView +from obp.api import API, APIError +from django.conf import settings +import csv + + + +class ApiCollectionListView(IndexView, LoginRequiredMixin, FormView ): + template_name = "apicollectionlist/apicollectionlist.html" + success_url = '/apicollections/list' + + def get_apicollections(self, context): + """Get All user """ + api = API(self.request.session.get('obp')) + try: + apicollections_list = [] + #TODO: NOTE- THIS RETURNS ALL USER. THIS IS A POTENTIAL PERFORMANCE ISSUE. WE NEED ENDPOINT FOR COLLECTION. + #Endpoint will return users. + get_all_users_url_path = '/users' + + user = api.get(get_all_users_url_path) + for i in user["users"]: + # Returns the APIs collections for a user. + api_collections_for_user_url_path = '/users/{}/api-collections'.format(i["user_id"]) + api_collections_for_user = api.get(api_collections_for_user_url_path) + if 'api_collections' in api_collections_for_user: + apicollections_list.extend(api_collections_for_user['api_collections']) + for ac in apicollections_list: + ac["collection_on_api_explorer_url"] = f"{settings.API_EXPLORER_HOST}/?api-collection-id={ac['api_collection_id']}" + except APIError as err: + messages.error(self.request, err) + return [] + except Exception as err: + messages.error(self.request, err) + return [] + + return apicollections_list + + def get_context_data(self, **kwargs): + api = API(self.request.session.get('obp')) + context = super(IndexView, self).get_context_data(**kwargs) + apicollections_list = self.get_apicollections(context) + try: + for final_collection_list in apicollections_list: + url_path = "/users/user_id/{}".format(final_collection_list["user_id"]) + result = api.get(url_path) + final_collection_list["username"] = result["username"] + except Exception as err: + messages.error(self.request, err) + context.update({ + 'apicollections_list': apicollections_list, + }) + return context + +class ExportCsvView(LoginRequiredMixin, View): + """View to export the user to csv""" + + def get(self, request, *args, **kwargs): + api = API(self.request.session.get('obp')) + try: + apicollections_list = [] + urlpath = '/my/api-collections' + result = api.get(urlpath) + if 'api_collections' in result: + apicollections_list.extend(result['api_collections']) + except APIError as err: + messages.error(self.request, err) + except Exception as inst: + messages.error(self.request, "Unknown Error {}".format(type(inst).__name__)) + response = HttpResponse(content_type = 'text/csv') + response['Content-Disposition'] = 'attachment;filename= ApiCollections'+ str(datetime.datetime.now())+'.csv' + writer = csv.writer(response) + writer.writerow(["api_collection_id","user_id","api_collection_name","is_sharable","description"]) + for user in apicollections_list: + writer.writerow([user['api_collection_id'],user['user_id'], user['api_collection_name'], user["is_sharable"], + user["description"]]) + return response + + diff --git a/apimanager/apicollections/static/apicollections/js/apicollections.js b/apimanager/apicollections/static/apicollections/js/apicollections.js index d0d9d94..fd2c578 100644 --- a/apimanager/apicollections/static/apicollections/js/apicollections.js +++ b/apimanager/apicollections/static/apicollections/js/apicollections.js @@ -1,12 +1,11 @@ $(document).ready(function($) { $('.runner button.forSave').click(function(e) { e.preventDefault(); - var t = $(this); - var runner = t.parent().parent().parent(); - var api_collection_name = $(runner).find('.api_collection_name').val(); - var api_collection_is_sharable = $(runner).find('.api_collection_is_sharable').val(); - var api_collection_description = $(runner).find('.api_collection_description').val(); - + let runner = $(this).parent().parent().parent(); + let api_collection_name = $(runner).find('.api_collection_name').val(); + let api_collection_is_sharable = $(runner).find('.api_collection_is_sharable').val(); + let api_collection_description = $(runner).find('.api_collection_description').val(); + $('.runner button.forUpdate').attr("disabled","disabled"); $('.runner button.forSave').attr("disabled","disabled"); $('.runner button.forDelete').attr("disabled","disabled"); $.post('save/apicollection', { @@ -17,12 +16,31 @@ $(document).ready(function($) { location.reload(); }); }); + $('.runner button.forUpdate').click(function(e) { + e.preventDefault(); + let runner = $(this).parent().parent().parent(); + let api_collection_id = $(runner).find('.api_collection_id').attr("value"); + let api_collection_name = $(runner).find('.api_collection_name').val(); + let api_collection_is_sharable = $(runner).find('.api_collection_is_sharable').val(); + let api_collection_description = $(runner).find('.api_collection_description').val(); + $('.runner button.forUpdate').attr("disabled","disabled"); + $('.runner button.forSave').attr("disabled","disabled"); + $('.runner button.forDelete').attr("disabled","disabled"); + $.post('update/apicollection', { + 'api_collection_id': api_collection_id, + 'api_collection_name': api_collection_name, + 'api_collection_is_sharable': api_collection_is_sharable, + 'api_collection_description': api_collection_description, + }, function (response) { + location.reload(); + }); + }); $('.runner button.forDelete').click(function(e) { e.preventDefault(); - var t = $(this); - var runner = t.parent().parent().parent(); - var api_collection_id = $(runner).find('.api_collection_id').html(); + let runner = $(this).parent().parent().parent(); + let api_collection_id = $(runner).find('.api_collection_id').attr("value"); + $('.runner button.forUpdate').attr("disabled","disabled"); $('.runner button.forSave').attr("disabled","disabled"); $('.runner button.forDelete').attr("disabled","disabled"); $.post('delete/apicollection', { diff --git a/apimanager/apicollections/templates/apicollections/index.html b/apimanager/apicollections/templates/apicollections/index.html index 05d0a46..ba3f2cd 100644 --- a/apimanager/apicollections/templates/apicollections/index.html +++ b/apimanager/apicollections/templates/apicollections/index.html @@ -3,7 +3,7 @@ {% block page_title %}{{ block.super }} / API Collections{% endblock page_title %} {% block content %} -

{% trans "API Collections" %}

+

{% trans "My API Collections" %}


@@ -26,20 +26,32 @@
+ + {% if api_collection.api_collection_id %} + Try It + {% endif %} +
{% if api_collection.api_collection_id %}
-
{{ api_collection.api_collection_name }}
+
+ +
+
-
{{ api_collection.is_sharable }}
+
+
-
-
{{api_collection.description}}
+
+
{% else %}
@@ -55,19 +67,29 @@
-
- +
+
{% endif %} {% if forloop.counter0 == 0 %} -
+
{% endif %} {% if forloop.counter0 > 0 %} -
+ +
+
+ +
+
+
@@ -82,4 +104,5 @@ {% block extrajs %} + {% endblock extrajs %} diff --git a/apimanager/apicollections/urls.py b/apimanager/apicollections/urls.py index 84fbe65..b3b6851 100644 --- a/apimanager/apicollections/urls.py +++ b/apimanager/apicollections/urls.py @@ -6,7 +6,7 @@ URLs for config app from django.conf.urls import url from apicollections.views import IndexView, apicollections_save, \ - apicollections_delete, DetailView, DeleteCollectionEndpointView + apicollections_delete, DetailView, DeleteCollectionEndpointView, apicollections_update urlpatterns = [ url(r'^$', @@ -14,6 +14,8 @@ urlpatterns = [ name='apicollections-index'), url(r'save/apicollection', apicollections_save, name='apicollection-save'), + url(r'update/apicollection', apicollections_update, + name='apicollection-update'), url(r'delete/apicollection', apicollections_delete, name='apicollection-delete'), url(r'^my-api-collection-ids/(?P[\w\@\.\+-]+)$', diff --git a/apimanager/apicollections/views.py b/apimanager/apicollections/views.py index 665a31c..42ce06c 100644 --- a/apimanager/apicollections/views.py +++ b/apimanager/apicollections/views.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ -Views of config app +Views of API Collection app """ import json @@ -13,10 +13,10 @@ from django.urls import reverse, reverse_lazy from base.utils import exception_handle, error_once_only from .forms import ApiCollectionsForm, ApiCollectionEndpointsForm from django.views.decorators.csrf import csrf_exempt - +from django.conf import settings class IndexView(LoginRequiredMixin, FormView): - """Index view for config""" + """Index view for API Collection""" template_name = "apicollections/index.html" form_class = ApiCollectionsForm success_url = reverse_lazy('apicollections-index') @@ -32,10 +32,12 @@ class IndexView(LoginRequiredMixin, FormView): error_once_only(self.request, response['message']) else: api_collections=response['api_collections'] + for ac in api_collections: + ac["collection_on_api_explorer_url"] = f"{settings.API_EXPLORER_HOST}/?api-collection-id={ac['api_collection_id']}" except APIError as err: messages.error(self.request, err) - except BaseException as err: - error_once_only(self.request, (Exception("Unknown Error. Details:" + str(err)))) + except Exception as err: + error_once_only(self.request, err) else: # set the default endpoint there, the first item will be the new endpoint. default_api_endpoint = { @@ -71,8 +73,8 @@ class DetailView(LoginRequiredMixin, FormView): except APIError as err: messages.error(self.request, err) return super(DetailView, self).form_invalid(form) - except: - messages.error(self.request, 'Unknown Error') + except Exception as err: + error_once_only(self.request, err) return super(DetailView, self).form_invalid(form) if 'code' in api_collection_endpoint and api_collection_endpoint['code']>=400: messages.error(self.request, api_collection_endpoint['message']) @@ -97,11 +99,9 @@ class DetailView(LoginRequiredMixin, FormView): else: api_collection_endpoints=response['api_collection_endpoints'] except APIError as err: - error_once_only(self.request, Exception("OBP-API server is not running or do not response properly. " - "Please check OBP-API server. " - "Details: " + str(err))) - except BaseException as err: - error_once_only(self.request, (Exception("Unknown Error. Details:" + str(err)))) + messages.error(self.request, result['message']) + except Exception as err: + error_once_only(self.request, err) else: context.update({ 'api_collection_endpoints': api_collection_endpoints, @@ -115,8 +115,9 @@ class DeleteCollectionEndpointView(LoginRequiredMixin, FormView): """Deletes api collection endpoint from API""" api = API(self.request.session.get('obp')) try: - urlpath = '/my/api-collections-ids/{}/api-collection-endpoints/{}'\ - .format(kwargs['api_collection_id'],kwargs['operation_id']) + get_api_collection_by_id_url = "/my/api-collections/{}".format(kwargs["api_collection_id"]) + result = api.get(get_api_collection_by_id_url) + urlpath = '/my/api-collections/{}/api-collection-endpoints/{}'.format(kwargs['api_collection_name'],kwargs['operation_id']) result = api.delete(urlpath) if result is not None and 'code' in result and result['code']>=400: messages.error(request, result['message']) @@ -125,9 +126,8 @@ class DeleteCollectionEndpointView(LoginRequiredMixin, FormView): messages.success(request, msg) except APIError as err: messages.error(request, err) - except: - messages.error(self.request, 'Unknown Error') - + except Exception as err: + messages.error(self.request, 'Unknown Error', err) redirect_url = reverse('my-api-collection-detail',kwargs={"api_collection_id":kwargs['api_collection_id']}) return HttpResponseRedirect(redirect_url) @@ -144,6 +144,21 @@ def apicollections_save(request): result = api.post(urlpath, payload = payload) return result +@exception_handle +@csrf_exempt +def apicollections_update(request): + connector_method_id = request.POST.get('api_collection_id').strip() + urlpath = '/my/api-collections/{}'.format(connector_method_id) + api = API(request.session.get('obp')) + payload = { + 'api_collection_name': request.POST.get('api_collection_name').strip(), + 'is_sharable': True if request.POST.get('api_collection_is_sharable').strip().lower() == "true" else False, + 'description': request.POST.get('api_collection_description').strip() + } + result = api.put(urlpath, payload=payload) + return result + + @exception_handle @csrf_exempt diff --git a/apimanager/apimanager/settings.py b/apimanager/apimanager/settings.py index d9f1922..9c918ae 100644 --- a/apimanager/apimanager/settings.py +++ b/apimanager/apimanager/settings.py @@ -27,7 +27,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) SECRET_KEY = None # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True +DEBUG = False @@ -52,6 +52,7 @@ INSTALLED_APPS = [ 'obp', 'consumers', 'accounts', + 'accountlist', 'systemviews', 'users', 'branches', @@ -68,7 +69,8 @@ INSTALLED_APPS = [ 'methodrouting', 'connectormethod', 'dynamicendpoints', - 'apicollections' + 'apicollections', + 'apicollectionlist' ] MIDDLEWARE = [ @@ -242,15 +244,16 @@ LOGGING = { LOGIN_URL = reverse_lazy('home') #Map Java: yyyy-MM-dd'T'HH:mm'Z' -API_DATETIMEFORMAT = '%Y-%m-%dT%H:%M:%SZ' +API_DATE_TIME_FORMAT = '%Y-%m-%dT%H:%M:%SZ' #Map Java: yyyy-MM-dd'T'HH:mm:ss.SSS'Z' -API_DATEFORMAT = '%Y-%m-%dT%H:%M:%S.%fZ' +API_DATE_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ' # the API_Manager the web form date format, eg: 2020-10-11 API_MANAGER_DATE_FORMAT= '%Y-%m-%d' API_HOST = 'http://127.0.0.1:8080' +API_EXPLORER_HOST = 'http://127.0.0.1:8082' # Only override this if you have a separate portal instance API_PORTAL = API_HOST API_BASE_PATH = '/obp/v' @@ -299,13 +302,17 @@ LOGO_URL = 'https://static.openbankproject.com/images/OBP/favicon.png' OVERRIDE_CSS_URL = None VERIFY = True +CALLBACK_BASE_URL = "" -# Local settings can override anything in here +# Global +UNDEFINED = "" + +# Local settings can replace any value ABOVE try: from apimanager.local_settings import * # noqa except ImportError: pass -# EVERYTHING BELOW HERE WILL NOT BE OVERWRITTEN BY LOCALSETTINGS! +# EVERYTHING BELOW HERE WILL *NOT* BE OVERWRITTEN BY LOCALSETTINGS! # DO NOT TRY TO DO SO YOU WILL BE IGNORED! # Settings here might use parts overwritten in local settings diff --git a/apimanager/apimanager/urls.py b/apimanager/apimanager/urls.py index 8e84678..419fb3a 100644 --- a/apimanager/apimanager/urls.py +++ b/apimanager/apimanager/urls.py @@ -36,6 +36,7 @@ urlpatterns += i18n_patterns( LogoutView.as_view(), name='oauth-logout'), url(r'^systemviews/', include('systemviews.urls')), url(r'^accounts/', include('accounts.urls')), + url(r'^account/list', include('accountlist.urls')), url(r'^consumers/', include('consumers.urls')), url(r'^entitlementrequests/', include('entitlementrequests.urls')), url(r'^users/', include('users.urls')), @@ -53,6 +54,7 @@ urlpatterns += i18n_patterns( url(r'^connectormethod/', include('connectormethod.urls')), url(r'^dynamicendpoints/', include('dynamicendpoints.urls')), url(r'^apicollections/', include('apicollections.urls')), + url(r'^apicollections-list', include('apicollectionlist.urls')), ) #prefix_default_language=False, #)+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \ No newline at end of file diff --git a/apimanager/atms/views.py b/apimanager/atms/views.py index e8d5154..b63f48d 100644 --- a/apimanager/atms/views.py +++ b/apimanager/atms/views.py @@ -15,6 +15,8 @@ from obp.api import API, APIError from .forms import CreateAtmForm from django.utils.translation import ugettext_lazy as _ +CHOOSE = "Choose..." + class IndexAtmsView(LoginRequiredMixin, FormView): """Index view for ATMs""" @@ -33,12 +35,12 @@ class IndexAtmsView(LoginRequiredMixin, FormView): fields = form.fields try: fields['bank_id'].choices = self.api.get_bank_id_choices() - fields['is_accessible'].choices = [('',_('Choose...')),(True, True), (False, False)] - fields['has_deposit_capability'].choices = [('',_('Choose...')),(True, True), (False, False)] - fields['supported_languages'].choices = [('',_('Choose...')),("en", "en"), ("fr", "fr"), ("de", "de")] - fields['notes'].choices = [('',_('Choose...')),("String1", "String1"), ("String2", "String2")] - fields['supported_currencies'].choices = [('',_('Choose...')),("EUR", "EUR"), ("MXN", "MXN"), ("USD", "USD")] - fields['location_categories'].choices = [('',_('Choose...')),("ATBI", "ATBI"), ("ATBE", "ATBE")] + fields['is_accessible'].choices = [('',_(CHOOSE)),(True, True), (False, False)] + fields['has_deposit_capability'].choices = [('',_(CHOOSE)),(True, True), (False, False)] + fields['supported_languages'].choices = [('',_(CHOOSE)),("en", "en"), ("fr", "fr"), ("de", "de")] + fields['notes'].choices = [('',_(CHOOSE)),("String1", "String1"), ("String2", "String2")] + fields['supported_currencies'].choices = [('',_(CHOOSE)),("EUR", "EUR"), ("MXN", "MXN"), ("USD", "USD")] + fields['location_categories'].choices = [('',_(CHOOSE)),("ATBI", "ATBI"), ("ATBE", "ATBE")] fields['lobby'].initial = json.dumps({ "monday": [ { @@ -111,16 +113,8 @@ class IndexAtmsView(LoginRequiredMixin, FormView): "bank_id": data["bank_id"], "name": data["name"], "address": json.loads(data['address']), - "location": { - "latitude": float(data["location_latitude"]) if data["location_latitude"] is not None else "", - "longitude": float(data["location_longitude"]) if data["location_longitude"] is not None else "" - }, - "meta": { - "license": { - "id": "ODbL-1.0", - "name": data["meta_license_name"] if data["meta_license_name"]!="" else "license name" - } - }, + "location": self._location(data), + "meta": self._meta(data), "monday": { "opening_time": "", "closing_time": "" @@ -149,30 +143,22 @@ class IndexAtmsView(LoginRequiredMixin, FormView): "opening_time": "", "closing_time": "" }, - "is_accessible": data["is_accessible"] if data["is_accessible"]!="" else "false", - "located_at": data["located_at"] if data["located_at"]!="no-example-provided" else " ", - "more_info": data["more_info"] if data["more_info"]!="" else "false", - "has_deposit_capability": data["has_deposit_capability"] if data["has_deposit_capability"]!="" else "false", "supported_languages":[data["supported_languages"]], "services":[data["services"]], "accessibility_features":[data["accessibility_features"]], "supported_currencies":[data["supported_currencies"]], "notes":[data["notes"]], "location_categories":[data["location_categories"]], - "minimum_withdrawal": data["minimum_withdrawal"] if data["minimum_withdrawal"]!="" else "false", - "branch_identification": data["branch_identification"] if data["branch_identification"]!="" else "false", - "site_identification": data["site_identification"] if data["site_identification"]!="" else "false", - "site_name": data["site_name"] if data["site_name"]!="" else "false", - "cash_withdrawal_national_fee": data["cash_withdrawal_national_fee"] if data["cash_withdrawal_national_fee"]!="" else "false", - "cash_withdrawal_international_fee": data["cash_withdrawal_international_fee"] if data["cash_withdrawal_international_fee"]!="" else "false", - "balance_inquiry_fee": data["balance_inquiry_fee"] if data["balance_inquiry_fee"]!="" else "false", + **self._boolean_payload1(data), + **self._boolean_payload2(data), + } result = self.api.post(urlpath, payload=payload) except APIError as err: - messages.error(self.request, "Unknown Error") + messages.error(self.request, err) return super(IndexAtmsView, self).form_invalid(form) except Exception as err: - messages.error(self.request, "Unknown Error") + messages.error(self.request, err) return super(IndexAtmsView, self).form_invalid(form) if 'code' in result and result['code']>=400: messages.error(self.request, result['message']) @@ -181,6 +167,39 @@ class IndexAtmsView(LoginRequiredMixin, FormView): messages.success(self.request, msg) return super(IndexAtmsView, self).form_valid(form) + def _location(self, data): + return { + "latitude": float(data["location_latitude"]) if data["location_latitude"] is not None else "", + "longitude": float(data["location_longitude"]) if data["location_longitude"] is not None else "" + } + + def _meta(self, data): + return { + "license": { + "id": "ODbL-1.0", + "name": data["meta_license_name"] if data["meta_license_name"]!="" else "license name" + } + } + + def _boolean_payload1(self, data): + return { + "is_accessible": data["is_accessible"] if data["is_accessible"]!="" else "false", + "located_at": data["located_at"] if data["located_at"]!="no-example-provided" else " ", + "more_info": data["more_info"] if data["more_info"]!="" else "false", + "has_deposit_capability": data["has_deposit_capability"] if data["has_deposit_capability"]!="" else "false", + "minimum_withdrawal": data["minimum_withdrawal"] if data["minimum_withdrawal"]!="" else "false" + } + + def _boolean_payload2(self, data): + return { + "branch_identification": data["branch_identification"] if data["branch_identification"]!="" else "false", + "site_identification": data["site_identification"] if data["site_identification"]!="" else "false", + "site_name": data["site_name"] if data["site_name"]!="" else "false", + "cash_withdrawal_national_fee": data["cash_withdrawal_national_fee"] if data["cash_withdrawal_national_fee"]!="" else "false", + "cash_withdrawal_international_fee": data["cash_withdrawal_international_fee"] if data["cash_withdrawal_international_fee"]!="" else "false", + "balance_inquiry_fee": data["balance_inquiry_fee"] if data["balance_inquiry_fee"]!="" else "false" + } + class UpdateAtmsView(LoginRequiredMixin, FormView): template_name = "atms/update.html" success_url = '/atms/list' @@ -200,8 +219,8 @@ class UpdateAtmsView(LoginRequiredMixin, FormView): fields['bank_id'].choices = self.api.get_bank_id_choices() except APIError as err: messages.error(self.request, err) - except: - messages.error(self.request, "Unknown Error") + except Exception as err: + messages.error(self.request, err) try: result = self.api.get(urlpath) fields['bank_id'].initial = self.kwargs['bank_id'] @@ -214,14 +233,6 @@ class UpdateAtmsView(LoginRequiredMixin, FormView): fields['meta_license_name'].initial = result['meta']['license']['name'] fields['minimum_withdrawal'].initial = result['minimum_withdrawal'] fields['branch_identification'].initial = result['branch_identification'] - if result['is_accessible'].lower()=='true': - fields['is_accessible'].choices = [(True, True), (False, False)] - else: - fields['is_accessible'].choices = [(False, False), (True, True)] - if result['has_deposit_capability'].lower()=='true': - fields['has_deposit_capability'].choices = [(True, True), (False, False)] - else: - fields['has_deposit_capability'].choices = [(False, False), (True, True)] fields['has_deposit_capability'].initial = result['accessibility_features'] fields['site_identification'].initial = result['site_identification'] fields['site_name'].initial = result['site_name'] @@ -232,35 +243,53 @@ class UpdateAtmsView(LoginRequiredMixin, FormView): fields['located_at'].initial = result['located_at'] fields['more_info'].initial = result['more_info'] fields['located_at'].initial = result['located_at'] - if result['supported_languages'][0].lower()=='en': - fields['supported_languages'].choices = [("en", "en"), ("fr", "fr"), ("de", "de")] - elif result['supported_languages'][0].lower()=='fr': - fields['supported_languages'].choices = [("fr", "fr"), ("en", "en"), ("de", "de")] - else: - fields['supported_languages'].choices = [("de", "de"),("fr", "fr"), ("en", "en")] - fields['supported_languages'].initial = result['supported_languages'] - if result['supported_currencies'][0].lower()=='EUR': - fields['supported_currencies'].choices = [("EUR", "EUR"), ("MXN", "MXN"), ("USD", "USD")] - elif result['supported_currencies'][0].lower()=='MXN': - fields['supported_currencies'].choices = [("MXN", "MXN"), ("EUR", "EUR"), ("USD", "USD")] - else: - fields['supported_currencies'].choices = [("USD", "USD"),("MXN", "MXN"), ("EUR", "EUR")] - fields['supported_currencies'].initial = result['supported_currencies'] - if result['notes'][0].lower()=='string1': - fields['notes'].choices = [("String1", "String1"),("String2", "String2")] - else: - fields['notes'].choices = [("String2", "String2"),("String1", "String1")] - fields['notes'].initial = result['notes'] - if result['location_categories'][0].lower()=='atbi': - fields['location_categories'].choices = [("ATBI", "ATBI"),("ATBE", "ATBE")] - else: - fields['location_categories'].choices = [("ATBE", "ATBE"),("ATBI", "ATBI")] - fields['location_categories'].initial = result['location_categories'] + self._paylod_choices(result, fields) + self._paylod_languages_and_currencies(result, fields) + self._paylod_notes_and_categories(result, fields) except APIError as err: messages.error(self.request, err) except Exception as err: messages.error(self.request, "Unknown Error {}".format(err)) return form + + def _paylod_choices(self, result, fields): + if result['is_accessible'].lower()=='true': + fields['is_accessible'].choices = [(True, True), (False, False)] + else: + fields['is_accessible'].choices = [(False, False), (True, True)] + if result['has_deposit_capability'].lower()=='true': + fields['has_deposit_capability'].choices = [(True, True), (False, False)] + else: + fields['has_deposit_capability'].choices = [(False, False), (True, True)] + + def _paylod_languages_and_currencies(self, result, fields): + if result['supported_languages'][0].lower()=='en': + fields['supported_languages'].choices = [("en", "en"), ("fr", "fr"), ("de", "de")] + elif result['supported_languages'][0].lower()=='fr': + fields['supported_languages'].choices = [("fr", "fr"), ("en", "en"), ("de", "de")] + else: + fields['supported_languages'].choices = [("de", "de"),("fr", "fr"), ("en", "en")] + fields['supported_languages'].initial = result['supported_languages'] + if result['supported_currencies'][0].lower()=='EUR': + fields['supported_currencies'].choices = [("EUR", "EUR"), ("MXN", "MXN"), ("USD", "USD")] + elif result['supported_currencies'][0].lower()=='MXN': + fields['supported_currencies'].choices = [("MXN", "MXN"), ("EUR", "EUR"), ("USD", "USD")] + else: + fields['supported_currencies'].choices = [("USD", "USD"),("MXN", "MXN"), ("EUR", "EUR")] + fields['supported_currencies'].initial = result['supported_currencies'] + + def _paylod_notes_and_categories(self, result, fields): + if result['notes'][0].lower()=='string1': + fields['notes'].choices = [("String1", "String1"),("String2", "String2")] + else: + fields['notes'].choices = [("String2", "String2"),("String1", "String1")] + fields['notes'].initial = result['notes'] + if result['location_categories'][0].lower()=='atbi': + fields['location_categories'].choices = [("ATBI", "ATBI"),("ATBE", "ATBE")] + else: + fields['location_categories'].choices = [("ATBE", "ATBE"),("ATBI", "ATBI")] + fields['location_categories'].initial = result['location_categories'] + def form_valid(self, form): data = form.cleaned_data urlpath = '/banks/{}/atms/{}'.format(data["bank_id"],data["atm_id"]) @@ -307,23 +336,14 @@ class UpdateAtmsView(LoginRequiredMixin, FormView): "opening_time": " ", "closing_time": " " }, - "is_accessible": data["is_accessible"] if data["is_accessible"]!="" else "false", - "located_at": data["located_at"] if data["located_at"]!="no-example-provided" else " ", - "more_info": data["more_info"] if data["more_info"]!="" else "false", - "has_deposit_capability": data["has_deposit_capability"] if data["has_deposit_capability"]!="" else "false", "supported_languages":[data["supported_languages"]], "services":[data["services"]], "accessibility_features":[data["accessibility_features"]], "supported_currencies":[data["supported_currencies"]], "notes":[data["notes"]], "location_categories":[data["location_categories"]], - "minimum_withdrawal": data["minimum_withdrawal"] if data["minimum_withdrawal"]!="" else "false", - "branch_identification": data["branch_identification"] if data["branch_identification"]!="" else "false", - "site_identification": data["site_identification"] if data["site_identification"]!="" else "false", - "site_name": data["site_name"] if data["site_name"]!="" else "false", - "cash_withdrawal_national_fee": data["cash_withdrawal_national_fee"] if data["cash_withdrawal_national_fee"]!="" else "false", - "cash_withdrawal_international_fee": data["cash_withdrawal_international_fee"] if data["cash_withdrawal_international_fee"]!="" else "false", - "balance_inquiry_fee": data["balance_inquiry_fee"] if data["balance_inquiry_fee"]!="" else "false", + **self._update_boolean_payload1(data), + **self._update_boolean_payload2(data) } try: result = self.api.put(urlpath, payload=payload) @@ -341,6 +361,25 @@ class UpdateAtmsView(LoginRequiredMixin, FormView): messages.success(self.request, msg) return super(UpdateAtmsView, self).form_valid(form) + def _update_boolean_payload1(self, data): + return { + "is_accessible": data["is_accessible"] if data["is_accessible"]!="" else "false", + "located_at": data["located_at"] if data["located_at"]!="no-example-provided" else " ", + "more_info": data["more_info"] if data["more_info"]!="" else "false", + "has_deposit_capability": data["has_deposit_capability"] if data["has_deposit_capability"]!="" else "false", + "minimum_withdrawal": data["minimum_withdrawal"] if data["minimum_withdrawal"]!="" else "false" + } + + def _update_boolean_payload2(self, data): + return { + "branch_identification": data["branch_identification"] if data["branch_identification"]!="" else "false", + "site_identification": data["site_identification"] if data["site_identification"]!="" else "false", + "site_name": data["site_name"] if data["site_name"]!="" else "false", + "cash_withdrawal_national_fee": data["cash_withdrawal_national_fee"] if data["cash_withdrawal_national_fee"]!="" else "false", + "cash_withdrawal_international_fee": data["cash_withdrawal_international_fee"] if data["cash_withdrawal_international_fee"]!="" else "false", + "balance_inquiry_fee": data["balance_inquiry_fee"] if data["balance_inquiry_fee"]!="" else "false" + } + def get_context_data(self, **kwargs): context = super(UpdateAtmsView, self).get_context_data(**kwargs) self.bank_id = self.kwargs['bank_id'] diff --git a/apimanager/base/context_processors.py b/apimanager/base/context_processors.py index 89e2328..1169fdc 100644 --- a/apimanager/base/context_processors.py +++ b/apimanager/base/context_processors.py @@ -9,6 +9,7 @@ from django.contrib import messages from obp.api import API, APIError, LOGGER from django.core.cache import cache +USER_CURRENT = "/users/current" def api_root(request): """Returns the configured API_ROOT""" @@ -36,7 +37,7 @@ def override_css_url(request): def api_username(request): """Returns the API username/email of the logged-in user""" nametodisplay = 'not authenticated' - get_current_user_api_url = '/users/current' + get_current_user_api_url = USER_CURRENT #Here we can not get the user from obp-api side, so we use the django auth user id here. cache_key_django_user_id = request.session._session.get('_auth_user_id') cache_key = '{},{},{}'.format('api_username',get_current_user_api_url, cache_key_django_user_id) @@ -45,38 +46,42 @@ def api_username(request): apicaches=cache.get(cache_key) except Exception as err: apicaches=None + messages.error(request, err) if not apicaches is None: return apicaches else: if request.user.is_authenticated: - try: - api = API(request.session.get('obp')) - data = api.get(get_current_user_api_url) - username = data['username'] - email = data['email'] - provider = data['provider'] - if "google" in provider: - nametodisplay = email - elif "yahoo" in provider: - nametodisplay = email - elif "microsoft" in provider: - nametodisplay = email - else: - nametodisplay = username - apicaches=cache.set(cache_key, {'API_USERNAME': nametodisplay}) - LOGGER.warning('The cache is setting try to api_user_name:') - LOGGER.warning('The cache is setting key is: {}'.format(cache_key)) - except APIError as err: - messages.error(request, err) - except Exception as err: - messages.error(request, err) + nametodisplay = authenticated_name(request, get_current_user_api_url) + apicaches=cache.set(cache_key, {'API_USERNAME': nametodisplay}) + LOGGER.warning('The cache setting api_user_name is: {}'.format(nametodisplay)) + LOGGER.warning('The cache setting key is: {}'.format(cache_key)) return {'API_USERNAME': nametodisplay} +def authenticated_name(request, get_current_user_api_url): + try: + api = API(request.session.get('obp')) + data = api.get(get_current_user_api_url) + username = data['username'] + email = data['email'] + provider = data['provider'] + if "google" in provider: + nametodisplay = email + elif "yahoo" in provider: + nametodisplay = email + elif "microsoft" in provider: + nametodisplay = email + else: + nametodisplay = username + return nametodisplay + except APIError as err: + messages.error(request, err) + except Exception as err: + messages.error(request, err) def api_user_id(request): """Returns the API user id of the logged-in user""" user_id = 'not authenticated' - get_current_user_api_url = '/users/current' + get_current_user_api_url = USER_CURRENT #Here we can not get the user from obp-api side, so we use the django auth user id here. cache_key_django_user_id = request.session._session.get('_auth_user_id') cache_key = '{},{},{}'.format('api_user_id',get_current_user_api_url, cache_key_django_user_id) @@ -91,7 +96,7 @@ def api_user_id(request): if request.user.is_authenticated: try: api = API(request.session.get('obp')) - data = api.get('/users/current') + data = api.get(USER_CURRENT) user_id = data['user_id'] apicaches=cache.set(cache_key, {'API_USER_ID': user_id}) LOGGER.warning('The cache is setting try to api_user_id:') diff --git a/apimanager/base/filters.py b/apimanager/base/filters.py index e6d7743..a0f74c2 100644 --- a/apimanager/base/filters.py +++ b/apimanager/base/filters.py @@ -77,7 +77,7 @@ class FilterTime(BaseFilter): print(filtered) for item in data: item_date = datetime.strptime( - item[self.time_fieldname], settings.API_DATETIMEFORMAT) + item[self.time_fieldname], settings.API_DATE_TIME_FORMAT) if now - item_date <= delta: filtered.append(item) return filtered diff --git a/apimanager/base/static/css/base.css b/apimanager/base/static/css/base.css index b887c71..1a65793 100644 --- a/apimanager/base/static/css/base.css +++ b/apimanager/base/static/css/base.css @@ -208,13 +208,17 @@ table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSo } .language-select { - text-decoration: none; - color:#fff; margin-left:5rem; + text-decoration: none !important; } #uk { cursor:pointer; } #es { cursor:pointer; -}1 \ No newline at end of file +} +.language_underline_format > a > span:hover + { + text-decoration: underline; + font-weight: bold !important; +} diff --git a/apimanager/base/static/js/base.js b/apimanager/base/static/js/base.js index cb2ee98..212322a 100644 --- a/apimanager/base/static/js/base.js +++ b/apimanager/base/static/js/base.js @@ -1,8 +1,33 @@ $(document).ready(function($) { + // Select a language from navbar which want to change. + var currentURL = window.location.href; + const element = document.getElementById('gb') + element.addEventListener("click", () => { + if (currentURL.includes("/es/")) { + location.href = currentURL.split("/es/")[0] + "/en/" + currentURL.split("/es/")[1] + } + }); + const element1 = document.getElementById('es') + element1.addEventListener("click", () => { + if (currentURL.includes("/en/")) { + location.href = currentURL.split("/en/")[0] + "/es/" + currentURL.split("/en/")[1] + } + }); $('table.tablesorter').tablesorter(); $('#authentication-select').change(function() { $('.authentication-method').hide(); - var method = $(this).val(); + let method = $(this).val(); $(`#authenticate-${method}`).show(); }); }); + +// Redirect to API-Explorer, just click on Try Ii button in API-Collection and Dynamic Endpoint after success response. +function redirect_api_explorer_url(api_explorer_url) { + var currentURL = window.location.href.split("/"); + if (currentURL[3] == "en") { + location.href = api_explorer_url + "&locale=en_GB"; + } + else { + location.href = api_explorer_url + "&locale=es_ES"; + } + } diff --git a/apimanager/base/templates/base.html b/apimanager/base/templates/base.html index f599dcf..aaa00f9 100644 --- a/apimanager/base/templates/base.html +++ b/apimanager/base/templates/base.html @@ -14,7 +14,6 @@ - {% block extracss %}{% endblock extracss %} @@ -59,23 +58,24 @@
  • {% trans "KPI Dashboard" %}
  • - {% url "system_view" as system_view_url %} {% url "accounts-create" as accounts_create_url %} {% url "branches_list" as branches_list_url %} {% url "customers-create" as customers_create_url %} {% url "customer-list" as customer_list_url %} {% url "atms_create" as atms_create_url %} {% url "atm-list" as atm_list_url %} {% url "product-list" as product_list_url %} {% url "products-create" as product_create_url %} + {% url "system_view" as system_view_url %} {% url "accounts-create" as accounts_create_url %} {% url "account-list" as accounts_list_url %} {% url "branches_list" as branches_list_url %} {% url "customers-create" as customers_create_url %} {% url "customer-list" as customer_list_url %} {% url "atms_create" as atms_create_url %} {% url "atm-list" as atm_list_url %} {% url "product-list" as product_list_url %} {% url "products-create" as product_create_url %} - {% url "config-index" as config_index_url %} {% url "webui-index" as webui_props_index_url %} {% url "methodrouting-index" as methodrouting_index_url %} {% url "connectormethod" as connectormethod_url %} {% url "dynamicendpoints-index" as dynamic_endpoints_index_url %} {% url "apicollections-index" as api_collections_index_url %} + {% url "config-index" as config_index_url %} {% url "webui-index" as webui_props_index_url %} {% url "methodrouting-index" as methodrouting_index_url %} {% url "connectormethod" as connectormethod_url %} {% url "dynamicendpoints-index" as dynamic_endpoints_index_url %} {% url "apicollections-index" as api_collections_index_url %} {% url "apicollection-list" as api_collections_list_url %} {% if SHOW_API_TESTER %} @@ -98,19 +100,16 @@ {% trans "API Tester" %} {% endif %} -
  • {% if user.is_authenticated %} {% endif %}
  • - -
  • Language - EN +
  • Language + EN | ES
  • -
    @@ -130,27 +129,12 @@
    - diff --git a/apimanager/base/templates/home.html b/apimanager/base/templates/home.html index 3903534..a9351eb 100644 --- a/apimanager/base/templates/home.html +++ b/apimanager/base/templates/home.html @@ -46,10 +46,6 @@ {{ directlogin_form.password }}
    -
    diff --git a/apimanager/base/utils.py b/apimanager/base/utils.py index e904df6..a1418b5 100644 --- a/apimanager/base/utils.py +++ b/apimanager/base/utils.py @@ -4,7 +4,7 @@ Base utilities """ from django.contrib.humanize.templatetags.humanize import naturaltime from datetime import datetime, timedelta -from apimanager.settings import API_DATEFORMAT, API_MANAGER_DATE_FORMAT +from apimanager.settings import API_DATE_FORMAT, API_MANAGER_DATE_FORMAT from base import context_processors from django.contrib import messages import functools @@ -24,7 +24,6 @@ def get_cache_key_for_current_call(request, urlpath): """we will generate the cache key by login username+urlpath url path may contain lots of special characters, here we use the hash method first. """ - #TODO, we need the obp user.provide there. return context_processors.api_username(request).get('API_USERNAME') + str(hash(urlpath)) @@ -62,7 +61,7 @@ def convert_form_date_to_obpapi_datetime_format(form_to_date_string): """ convert the String 2020-10-22 to 2020-10-22T00:00:00.000000Z """ - return datetime.strptime(form_to_date_string, API_MANAGER_DATE_FORMAT).strftime(API_DATEFORMAT) + return datetime.strptime(form_to_date_string, API_MANAGER_DATE_FORMAT).strftime(API_DATE_FORMAT) def return_to_days_ago(date, days): """ @@ -71,4 +70,4 @@ def return_to_days_ago(date, days): days =1 return 2020-10-21T00:00:00.000000Z """ - return (datetime.strptime(date, API_DATEFORMAT) - timedelta(days)).strftime(API_DATEFORMAT) \ No newline at end of file + return (datetime.strptime(date, API_DATE_FORMAT) - timedelta(days)).strftime(API_DATE_FORMAT) \ No newline at end of file diff --git a/apimanager/branches/views.py b/apimanager/branches/views.py index 1a27401..dc42752 100644 --- a/apimanager/branches/views.py +++ b/apimanager/branches/views.py @@ -15,6 +15,8 @@ from obp.api import API, APIError from .forms import CreateBranchForm from base.views import get_banks +LICENSE_NAME = "license name" + class IndexBranchesView(LoginRequiredMixin, FormView): """Index view for branches""" template_name = "branches/index.html" @@ -122,8 +124,8 @@ class IndexBranchesView(LoginRequiredMixin, FormView): except APIError as err: messages.error(self.request, err) - except: - messages.error(self.request, "Unknown Error") + except Exception as err: + messages.error(self.request, err) return form @@ -143,14 +145,14 @@ class IndexBranchesView(LoginRequiredMixin, FormView): "meta": { "license": { "id": "PDDL", - "name": data["meta_license_name"] if data["meta_license_name"]!="" else "license name" + "name": data["meta_license_name"] if data["meta_license_name"]!="" else LICENSE_NAME } }, "lobby": json.loads(data['lobby']), "drive_up": json.loads(data["drive_up"]), "branch_routing": { - "scheme": data["branch_routing_scheme"] if data["branch_routing_scheme"]!="" else "license name", - "address": data["branch_routing_address"] if data["branch_routing_address"]!="" else "license name" + "scheme": data["branch_routing_scheme"] if data["branch_routing_scheme"]!="" else LICENSE_NAME, + "address": data["branch_routing_address"] if data["branch_routing_address"]!="" else LICENSE_NAME }, "is_accessible": data["is_accessible"] if data["is_accessible"]!="" else "false", "accessibleFeatures": data["accessibleFeatures"] if data["accessibleFeatures"]!="" else "accessible features name", @@ -163,7 +165,7 @@ class IndexBranchesView(LoginRequiredMixin, FormView): error_once_only(self.request, err) return super(IndexBranchesView, self).form_invalid(form) except Exception as err: - error_once_only(self.request, "Unknown Error") + error_once_only(self.request, err) return super(IndexBranchesView, self).form_invalid(form) if 'code' in result and result['code']>=400: error_once_only(self.request, result['message']) @@ -222,8 +224,8 @@ class UpdateBranchesView(LoginRequiredMixin, FormView): fields['bank_id'].choices = self.api.get_bank_id_choices() except APIError as err: messages.error(self.request, err) - except: - messages.error(self.request, "Unknown Error") + except Exception as err: + messages.error(self.request, err) try: result = self.api.get(urlpath) fields['bank_id'].initial = self.kwargs['bank_id'] @@ -272,8 +274,8 @@ class UpdateBranchesView(LoginRequiredMixin, FormView): "lobby": json.loads(data["lobby"]), "drive_up": json.loads(data["drive_up"]), "branch_routing": { - "scheme": data["branch_routing_scheme"] if data["branch_routing_scheme"] != "" else "license name", - "address": data["branch_routing_address"] if data["branch_routing_address"] != "" else "license name" + "scheme": data["branch_routing_scheme"] if data["branch_routing_scheme"] != "" else LICENSE_NAME, + "address": data["branch_routing_address"] if data["branch_routing_address"] != "" else LICENSE_NAME }, "is_accessible": data["is_accessible"], "accessibleFeatures": data["accessibleFeatures"], @@ -289,8 +291,8 @@ class UpdateBranchesView(LoginRequiredMixin, FormView): except APIError as err: messages.error(self.request, err) return super(UpdateBranchesView, self).form_invalid(form) - except: - messages.error(self.request, "Unknown Error") + except Exception as err: + messages.error(self.request, err) return super(UpdateBranchesView, self).form_invalid(form) msg = 'Branch {} for Bank {} has been created successfully!'.format( # noqa data["branch_id"], data["bank_id"]) diff --git a/apimanager/config/static/config/js/config.js b/apimanager/config/static/config/js/config.js index fb0ea03..590d540 100644 --- a/apimanager/config/static/config/js/config.js +++ b/apimanager/config/static/config/js/config.js @@ -5,7 +5,7 @@ $(document).ready(function($) { } json = json.replace(/&/g, '&').replace(//g, '>'); return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) { - var cls = 'number'; + let cls = 'number'; if (/^"/.test(match)) { if (/:$/.test(match)) { cls = 'key'; diff --git a/apimanager/config/views.py b/apimanager/config/views.py index cd4af7e..3c13bfd 100644 --- a/apimanager/config/views.py +++ b/apimanager/config/views.py @@ -25,8 +25,8 @@ class IndexView(LoginRequiredMixin, TemplateView): except APIError as err: messages.error(self.request, err) config = {} - except: - messages.error(self.request, "Unknown Error") + except Exception as err: + messages.error(self.request, err) config = {} context.update({ diff --git a/apimanager/connectormethod/static/connectormethod/js/connectormethod.js b/apimanager/connectormethod/static/connectormethod/js/connectormethod.js index ddd25a2..9b9cc63 100644 --- a/apimanager/connectormethod/static/connectormethod/js/connectormethod.js +++ b/apimanager/connectormethod/static/connectormethod/js/connectormethod.js @@ -1,11 +1,10 @@ $(document).ready(function($) { $('.runner button.forSave').click(function(e) { e.preventDefault(); - var t = $(this); - var runner = t.parent().parent().parent(); - var connector_method_name = $(runner).find('.connector_method_name').val(); - var connector_method_programming_lang = $(runner).find('.connector_method_programming_lang').val(); - var connector_method_body = $(runner).find('.connector_method_body').val(); + let runner = $(this).parent().parent().parent(); + let connector_method_name = $(runner).find('.connector_method_name').val(); + let connector_method_programming_lang = $(runner).find('.connector_method_programming_lang').val(); + let connector_method_body = $(runner).find('.connector_method_body').val(); $('.runner button.forSave').attr("disabled", "disabled"); $('.runner button.forDelete').attr("disabled", "disabled"); @@ -20,11 +19,10 @@ $(document).ready(function($) { $('.runner button.forUpdate').click(function(e) { e.preventDefault(); - var t = $(this); - var runner = t.parent().parent().parent(); - var connector_method_id = $(runner).find('.connector_method_id').html(); - var connector_method_programming_lang_update = $(runner).find('.connector_method_programming_lang_update').val(); - var connector_method_body_update = $(runner).find('.connector_method_body_update').val(); + let runner = $(this).parent().parent().parent(); + let connector_method_id = $(runner).find('.connector_method_id').html(); + let connector_method_programming_lang_update = $(runner).find('.connector_method_programming_lang_update').val(); + let connector_method_body_update = $(runner).find('.connector_method_body_update').val(); $('.runner button.forSave').attr("disabled", "disabled"); $('.runner button.forUpdate').attr("disabled", "disabled"); diff --git a/apimanager/connectormethod/views.py b/apimanager/connectormethod/views.py index 7fa0fa1..f965b25 100644 --- a/apimanager/connectormethod/views.py +++ b/apimanager/connectormethod/views.py @@ -34,8 +34,8 @@ class IndexView(LoginRequiredMixin, FormView): connectormethod=response['connector_methods'] except APIError as err: messages.error(self.request, err) - except BaseException as err: - error_once_only(self.request, (Exception("Unknown Error. Details:" + str(err)))) + except Exception as err: + error_once_only(self.request, err) else: default_connector_method_endpoint = { "connector_method_name": "Method Name", @@ -73,6 +73,5 @@ def connectormethod_update(request): 'programming_lang': request.POST.get('connector_method_programming_lang_update'), 'method_body': request.POST.get('connector_method_body_update').strip() } - result = HttpResponse(content_type = 'application/json') result = api.put(urlpath, payload=payload) return result diff --git a/apimanager/consumers/views.py b/apimanager/consumers/views.py index 5ca2f48..ecfdb93 100644 --- a/apimanager/consumers/views.py +++ b/apimanager/consumers/views.py @@ -16,9 +16,6 @@ from base.filters import BaseFilter, FilterTime from .forms import ApiConsumersForm -# import logging -# logger = logging.getLogger(__name__) - class FilterAppType(BaseFilter): """Filter consumers by application type""" @@ -47,7 +44,7 @@ class IndexView(LoginRequiredMixin, TemplateView): """Scrubs data in the given consumers to adher to certain formats""" for consumer in consumers: consumer['created'] = datetime.strptime( - consumer['created'], settings.API_DATETIMEFORMAT) + consumer['created'], settings.API_DATE_TIME_FORMAT) return consumers def compile_statistics(self, consumers): @@ -129,7 +126,6 @@ class DetailView(LoginRequiredMixin, FormView): 'per_week_call_limit': data['per_week_call_limit'], 'per_month_call_limit': data['per_month_call_limit'] } - user = self.api.put(urlpath, payload=payload) except APIError as err: messages.error(self.request, err) return super(DetailView, self).form_invalid(api_consumers_form) @@ -150,7 +146,7 @@ class DetailView(LoginRequiredMixin, FormView): urlpath = '/management/consumers/{}'.format(self.kwargs['consumer_id']) consumer = api.get(urlpath) consumer['created'] = datetime.strptime( - consumer['created'], settings.API_DATETIMEFORMAT) + consumer['created'], settings.API_DATE_TIME_FORMAT) call_limits_urlpath = '/management/consumers/{}/consumer/call-limits'.format(self.kwargs['consumer_id']) consumer_call_limtis = api.get(call_limits_urlpath) @@ -191,8 +187,8 @@ class EnableDisableView(LoginRequiredMixin, RedirectView): messages.success(self.request, self.success) except APIError as err: messages.error(self.request, err) - except: - messages.error(self.request, "Unknown") + except APIError as err: + messages.error(self.request, err) urlpath = self.request.POST.get('next', reverse('consumers-index')) query = self.request.GET.urlencode() diff --git a/apimanager/customerlist/views.py b/apimanager/customerlist/views.py index 634b880..04e2569 100644 --- a/apimanager/customerlist/views.py +++ b/apimanager/customerlist/views.py @@ -17,8 +17,6 @@ from obp.api import API, APIError from base.views import get_banks import csv - - class CustomerListView(CreateView, LoginRequiredMixin, FormView ): template_name = "customerlist/customerlist.html" success_url = '/customers/list' @@ -28,9 +26,7 @@ class CustomerListView(CreateView, LoginRequiredMixin, FormView ): try: self.bankids = get_banks(self.request) customers_list = [] - #for bank_id in self.bankids: urlpath = '/customers' - #urlpath = 'http://127.0.0.1:8080/obp/v4.0.0/my/customers' result = api.get(urlpath) if 'customers' in result: customers_list.extend(result['customers']) diff --git a/apimanager/customers/forms.py b/apimanager/customers/forms.py index 0addee0..925375e 100644 --- a/apimanager/customers/forms.py +++ b/apimanager/customers/forms.py @@ -9,6 +9,7 @@ from django.utils.translation import ugettext_lazy as _ from obp.api import APIError +PLACEHOLDER = "2013-01-22T00:08:00Z" class CreateCustomerForm(forms.Form): bank_id = forms.ChoiceField( @@ -80,10 +81,10 @@ class CreateCustomerForm(forms.Form): ) face_image_date = forms.DateTimeField( label=_('Face Image Date'), - input_formats=[settings.API_DATETIMEFORMAT], + input_formats=[settings.API_DATE_TIME_FORMAT], widget=forms.DateTimeInput( attrs={ - 'placeholder': '2013-01-22T00:08:00Z', + 'placeholder': PLACEHOLDER, 'class': 'form-control', } ), @@ -91,10 +92,10 @@ class CreateCustomerForm(forms.Form): ) date_of_birth = forms.DateTimeField( label=_('Date of Birth'), - input_formats=[settings.API_DATETIMEFORMAT], + input_formats=[settings.API_DATE_TIME_FORMAT], widget=forms.DateTimeInput( attrs={ - 'placeholder': '2013-01-22T00:08:00Z', + 'placeholder': PLACEHOLDER, 'class': 'form-control', } ), @@ -125,7 +126,7 @@ class CreateCustomerForm(forms.Form): label=_('Date of Birth of Dependants'), widget=forms.TextInput( attrs={ - 'placeholder': '2013-01-22T00:08:00Z, 2010-01-22T00:08:00Z', + 'placeholder': f'{PLACEHOLDER}, 2010-01-22T00:08:00Z', 'class': 'form-control', } ), @@ -203,10 +204,10 @@ class CreateCustomerForm(forms.Form): ) last_ok_date = forms.DateTimeField( label=_('Last OK Date'), - input_formats=[settings.API_DATETIMEFORMAT], + input_formats=[settings.API_DATE_TIME_FORMAT], widget=forms.DateTimeInput( attrs={ - 'placeholder': '2013-01-22T00:08:00Z', + 'placeholder': PLACEHOLDER, 'class': 'form-control', } ), @@ -220,14 +221,14 @@ class CreateCustomerForm(forms.Form): def clean_face_image_date(self): data = self.cleaned_data['face_image_date'] if data: - return data.strftime(settings.API_DATETIMEFORMAT) + return data.strftime(settings.API_DATE_TIME_FORMAT) else: return None def clean_date_of_birth(self): data = self.cleaned_data['date_of_birth'] if data: - return data.strftime(settings.API_DATETIMEFORMAT) + return data.strftime(settings.API_DATE_TIME_FORMAT) else: return None diff --git a/apimanager/customers/views.py b/apimanager/customers/views.py index e942d45..ca4ad3f 100644 --- a/apimanager/customers/views.py +++ b/apimanager/customers/views.py @@ -35,10 +35,10 @@ class CreateView(LoginRequiredMixin, FormView): fields['bank_id'].choices = self.api.get_bank_id_choices() except APIError as err: messages.error(self.request, err) - except: - messages.error(self.request, "Unknown Error") + except Exception as err: + messages.error(self.request, err) fields['last_ok_date'].initial =\ - datetime.datetime.now().strftime(settings.API_DATETIMEFORMAT) + datetime.datetime.now().strftime(settings.API_DATE_TIME_FORMAT) return form def form_valid(self, form): @@ -71,15 +71,15 @@ class CreateView(LoginRequiredMixin, FormView): 'employment_status': data['employment_status'], 'kyc_status': data['kyc_status'], 'last_ok_date': - data['last_ok_date'].strftime(settings.API_DATETIMEFORMAT), + data['last_ok_date'].strftime(settings.API_DATE_TIME_FORMAT), } try: result = self.api.post(urlpath, payload=payload) except APIError as err: messages.error(self.request, err) return super(CreateView, self).form_invalid(form) - except: - messages.error(self.request, "Unknown Error") + except Exception as err: + messages.error(self.request, err) return super(CreateView, self).form_invalid(form) msg = 'Customer number {} for user {} has been created successfully!'.format( # noqa result['customer_number'], data['username']) diff --git a/apimanager/dynamicendpoints/static/dynamicendpoints/js/dynamicendpoints.js b/apimanager/dynamicendpoints/static/dynamicendpoints/js/dynamicendpoints.js index 59c06bd..0bf07ce 100644 --- a/apimanager/dynamicendpoints/static/dynamicendpoints/js/dynamicendpoints.js +++ b/apimanager/dynamicendpoints/static/dynamicendpoints/js/dynamicendpoints.js @@ -7,14 +7,14 @@ $(document).ready(function($) { //each dynamic_endpoint will have each own json_editor, and will put data into it when click `parameter` box //and will use the data from click `save` button. - var json_editors = [] + let json_editors = [] $('.parameters').click(function() { - var runner = $(this).parent().parent().parent(); - var json_editor_id= $(runner).find('.jsoneditor_div')[0].id; - var json_editor_number = json_editor_id.replace("jsoneditor",""); - var container = $("#"+json_editor_id); - parameters = JSON.parse($(runner).find('textarea[name="parameters"]').text()); - var jsoneditor_div = $(runner).find('.jsoneditor_div'); + let runner = $(this).parent().parent().parent(); + let json_editor_id= $(runner).find('.jsoneditor_div')[0].id; + let json_editor_number = json_editor_id.replace("jsoneditor",""); + let container = $("#"+json_editor_id); + let parameters = JSON.parse($(runner).find('textarea[name="parameters"]').text()); + let jsoneditor_div = $(runner).find('.jsoneditor_div'); //make sure only create one jsoneditor_div block if(!(jsoneditor_div.css("display") ==="block")){ json_editors[json_editor_number] = new JSONEditor(container[0], options, parameters); @@ -27,11 +27,10 @@ $(document).ready(function($) { }); $('.runner button.forSave').click(function() { - var t = $(this); - var runner = $(this).parent().parent().parent(); - var jsoneditor_id= $(runner).find('.jsoneditor_div')[0].id - var json_editor_number = jsoneditor_id.replace("jsoneditor","") - parameters_Json_editor = JSON.stringify(json_editors[json_editor_number].get()); + let runner = $(this).parent().parent().parent(); + let jsoneditor_id= $(runner).find('.jsoneditor_div')[0].id + let json_editor_number = jsoneditor_id.replace("jsoneditor","") + let parameters_Json_editor = JSON.stringify(json_editors[json_editor_number].get()); console.log("parameters_Json_editor:"+parameters_Json_editor) $('.runner button.forSave').attr("disabled","disabled"); $('.runner button.forDelete').attr("disabled","disabled"); @@ -45,9 +44,8 @@ $(document).ready(function($) { }); $('.runner button.forDelete').click(function() { - var t = $(this); - var runner = $(this).parent().parent().parent(); - dynamic_endpoint_id = $(runner).find('.dynamic_endpoint_id').text(); + let runner = $(this).parent().parent().parent(); + let dynamic_endpoint_id = $(runner).find('.dynamic_endpoint_id').text(); $('.runner button.forSave').attr("disabled","disabled"); $('.runner button.forDelete').attr("disabled","disabled"); $.post('dynamicendpoints/delete/dynamicendpoint', { diff --git a/apimanager/dynamicendpoints/templates/dynamicendpoints/index.html b/apimanager/dynamicendpoints/templates/dynamicendpoints/index.html index 35f0238..178d581 100644 --- a/apimanager/dynamicendpoints/templates/dynamicendpoints/index.html +++ b/apimanager/dynamicendpoints/templates/dynamicendpoints/index.html @@ -4,53 +4,60 @@ {% block page_title %}{{ block.super }} / Dynamic Endpoints{% endblock page_title %} {% block content %} -

    {% trans "Dynamic Endpoints" %}

    -
    -
    -
    -
    -
    -
    -
    +

    {% trans "Dynamic Endpoints" %}

    +
    +
    +
    -
    - {% csrf_token %} - {% for dynamic_endpoint in dynamic_endpoints %} -
    -
    -
    -
    -
    {{ dynamic_endpoint.dynamic_endpoint_id }}
    -
    - -
    - -
    - {% if forloop.counter0 == 0 %} -
    -
    - {% trans "saved." %} -
    -
    - {% endif %} - {% if forloop.counter0 > 0 %} -
    -
    - -
    -
    - {% endif %} -
    - +
    +
    +
    +
    + + {% csrf_token %} + {% for dynamic_endpoint in dynamic_endpoints %} +
    +
    +
    +
    + + {% if dynamic_endpoint.dynamicendpoint_on_api_explorer_url %} + Try It + {% else %} + {{dynamic_endpoint.dynamic_endpoint_id}} + {% endif %}
    +
    + +
    + {% if forloop.counter0 == 0 %} +
    +
    + {% trans "saved." %} +
    +
    + {% endif %} + {% if forloop.counter0 > 0 %} +
    +
    + +
    +
    + {% endif %} +
    + +
    +
    {% endfor %} - + {% endblock %} {% block extrajs %} - -{% endblock extrajs %} + + + +{% endblock extrajs %} \ No newline at end of file diff --git a/apimanager/dynamicendpoints/views.py b/apimanager/dynamicendpoints/views.py index e8179f4..5084211 100644 --- a/apimanager/dynamicendpoints/views.py +++ b/apimanager/dynamicendpoints/views.py @@ -4,6 +4,7 @@ Views of config app """ import json +from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic import FormView from obp.api import API, APIError @@ -11,7 +12,12 @@ from base.utils import exception_handle, error_once_only from .forms import DynamicEndpointsForm from django.urls import reverse_lazy from django.views.decorators.csrf import csrf_exempt +from django.conf import settings +DEFINITIONS_USER = "#/definitions/user" +UNEXPECTED_ERROR = "unexpected error" +RESPONSES_UNEXPECTED_ERROR = "#/responses/unexpectedError" +DEFINITIONS_API_ERROR = "#/definitions/APIError" class IndexView(LoginRequiredMixin, FormView): """Index view for config""" @@ -30,10 +36,13 @@ class IndexView(LoginRequiredMixin, FormView): error_once_only(self.request, response['message']) else: dynamic_endpoints=response['dynamic_endpoints'] + #Accessing API-Explorer URL, parameters API-Collection Id and selected Language eg. locale=en_GB (for English) + for de in dynamic_endpoints: + de["dynamicendpoint_on_api_explorer_url"] = f"{settings.API_EXPLORER_HOST}/?api-dynamic_endpoint-id={de['dynamic_endpoint_id']}" except APIError as err: messages.error(self.request, err) - except BaseException as err: - error_once_only(self.request, (Exception("Unknown Error. Details:" + str(err)))) + except Exception as err: + error_once_only(self.request, err) else: # set the default endpoint there, the first item will be the new endpoint. default_dynamic_endpoint = { @@ -63,20 +72,20 @@ class IndexView(LoginRequiredMixin, FormView): "in":"body", "required":True, "schema":{ - "$ref":"#/definitions/user" + "$ref":DEFINITIONS_USER } }], "responses":{ "201":{ "description":"create user successful and return created user object", "schema":{ - "$ref":"#/definitions/user" + "$ref": DEFINITIONS_USER } }, "500":{ - "description":"unexpected error", + "description":UNEXPECTED_ERROR, "schema":{ - "$ref":"#/responses/unexpectedError" + "$ref":RESPONSES_UNEXPECTED_ERROR } } } @@ -93,7 +102,7 @@ class IndexView(LoginRequiredMixin, FormView): "200":{ "description":"the successful get requested user by user ID", "schema":{ - "$ref":"#/definitions/user" + "$ref":DEFINITIONS_USER } }, "400":{ @@ -105,13 +114,13 @@ class IndexView(LoginRequiredMixin, FormView): "404":{ "description":"user not found", "schema":{ - "$ref":"#/definitions/APIError" + "$ref":DEFINITIONS_API_ERROR } }, "500":{ - "description":"unexpected error", + "description":UNEXPECTED_ERROR, "schema":{ - "$ref":"#/responses/unexpectedError" + "$ref":RESPONSES_UNEXPECTED_ERROR } } } @@ -125,13 +134,13 @@ class IndexView(LoginRequiredMixin, FormView): "200":{ "description":"get all users", "schema":{ - "$ref":"#/definitions/users" + "$ref":DEFINITIONS_USER } }, "404":{ "description":"user not found", "schema":{ - "$ref":"#/definitions/APIError" + "$ref":DEFINITIONS_API_ERROR } } } @@ -144,20 +153,20 @@ class IndexView(LoginRequiredMixin, FormView): "in":"body", "required":True, "schema":{ - "$ref":"#/definitions/user" + "$ref":DEFINITIONS_USER } }], "responses":{ "200":{ "description":"create user successful and return created user object", "schema":{ - "$ref":"#/definitions/user" + "$ref":DEFINITIONS_USER } }, "500":{ - "description":"unexpected error", + "description":UNEXPECTED_ERROR, "schema":{ - "$ref":"#/responses/unexpectedError" + "$ref":RESPONSES_UNEXPECTED_ERROR } } } @@ -181,9 +190,9 @@ class IndexView(LoginRequiredMixin, FormView): } }, "500":{ - "description":"unexpected error", + "description":UNEXPECTED_ERROR, "schema":{ - "$ref":"#/responses/unexpectedError" + "$ref":RESPONSES_UNEXPECTED_ERROR } } } @@ -217,7 +226,7 @@ class IndexView(LoginRequiredMixin, FormView): "description":"array of users", "type":"array", "items":{ - "$ref":"#/definitions/user" + "$ref":DEFINITIONS_USER } }, "APIError":{ @@ -237,15 +246,15 @@ class IndexView(LoginRequiredMixin, FormView): }, "responses":{ "unexpectedError":{ - "description":"unexpected error", + "description":UNEXPECTED_ERROR, "schema":{ - "$ref":"#/definitions/APIError" + "$ref":DEFINITIONS_API_ERROR } }, "invalidRequest":{ "description":"invalid request", "schema":{ - "$ref":"#/definitions/APIError" + "$ref":DEFINITIONS_API_ERROR } } }, @@ -273,10 +282,10 @@ class IndexView(LoginRequiredMixin, FormView): @exception_handle @csrf_exempt def dynamicendpoints_save(request): - parameters_Json_editor = request.POST.get('parameters_Json_editor') + parameters_Json_editor_dynamic = request.POST.get('parameters_Json_editor') api = API(request.session.get('obp')) urlpath = '/management/dynamic-endpoints' - result = api.post(urlpath, payload=json.loads(parameters_Json_editor) ) + result = api.post(urlpath, payload=json.loads(parameters_Json_editor_dynamic) ) return result diff --git a/apimanager/entitlementrequests/views.py b/apimanager/entitlementrequests/views.py index 0282674..8662014 100644 --- a/apimanager/entitlementrequests/views.py +++ b/apimanager/entitlementrequests/views.py @@ -12,6 +12,7 @@ from datetime import datetime from django.conf import settings from django.urls import reverse from django.http import HttpResponseRedirect +from apimanager.settings import UNDEFINED @@ -23,7 +24,7 @@ class IndexView(LoginRequiredMixin, TemplateView): """Scrubs data in the given entitlement requests to adher to certain formats""" for entitlement_request in entitlement_requests: entitlement_request['created'] = datetime.strptime( - entitlement_request['created'], settings.API_DATETIMEFORMAT) + entitlement_request['created'], settings.API_DATE_TIME_FORMAT) return entitlement_requests def get_context_data(self, **kwargs): @@ -44,8 +45,8 @@ class IndexView(LoginRequiredMixin, TemplateView): entitlement_requests = sorted(entitlement_requests, key=lambda k: k['created'], reverse=True) except APIError as err: messages.error(self.request, err) - except: - messages.error(self.request, "Unknown Error") + except Exception as err: + messages.error(self.request, err) context.update({ 'entitlementrequests': entitlement_requests, @@ -66,12 +67,12 @@ class RejectEntitlementRequest(LoginRequiredMixin, View): messages.error(self.request, response['message']) else: msg = 'Entitlement Request with role {} has been deleted.'.format( - request.POST.get('role_name', '')) + request.POST.get('role_name', UNDEFINED)) messages.success(request, msg) except APIError as err: messages.error(request, err) - except: - messages.error(self.request, "Unknown Error") + except Exception as err: + messages.error(self.request, err) return HttpResponseRedirect(reverse('entitlementrequests-index')) @@ -86,32 +87,32 @@ class AcceptEntitlementRequest(LoginRequiredMixin, View): try: urlpath = '/users/{}/entitlements'.format(kwargs['user_id']) payload = { - 'bank_id': request.POST.get('bank_id', ''), - 'role_name': request.POST.get('role_name', ''), + 'bank_id': request.POST.get('bank_id', UNDEFINED), + 'role_name': request.POST.get('role_name', UNDEFINED), } response = api.post(urlpath, payload=payload) if 'code' in response and response['code'] >= 400: messages.error(self.request, response['message']) else: - msg = 'Entitlement with role {} has been added.'.format(request.POST.get('role_name', '')) + msg = 'Entitlement with role {} has been added.'.format(request.POST.get('role_name', UNDEFINED)) messages.success(request, msg) except APIError as err: messages.error(request, err) - except: - messages.error(self.request, "Unknown Error") + except Exception as err: + messages.error(self.request, err) try: - urlpath = '/entitlement-requests/{}'.format(request.POST.get('entitlement_request_id', '')) + urlpath = '/entitlement-requests/{}'.format(request.POST.get('entitlement_request_id', UNDEFINED)) response = api.delete(urlpath) if 'code' in response and response['code'] >= 400: messages.error(self.request, response['message']) else: msg = 'Entitlement Request with role {} has been deleted.'.format( - request.POST.get('role_name', '')) + request.POST.get('role_name', UNDEFINED)) messages.success(request, msg) except APIError as err: messages.error(request, err) - except: - messages.error(self.request, "Unknown Error") + except Exception as err: + messages.error(self.request, err) - return HttpResponseRedirect(reverse('entitlementrequests-index')) \ No newline at end of file + return HttpResponseRedirect(reverse('entitlementrequests-index')) diff --git a/apimanager/locale/deepl_translation_function.py b/apimanager/locale/deepl_translation_function.py index 5786433..b5792c3 100644 --- a/apimanager/locale/deepl_translation_function.py +++ b/apimanager/locale/deepl_translation_function.py @@ -1,7 +1,6 @@ import requests import os import dotenv -#from deepl_translation_fun import trasnlator BASE_DIR = os.getcwd() #method tells us the location of current working directory diff --git a/apimanager/locale/generatePo.py b/apimanager/locale/generatePo.py index 558101b..fa06fd1 100644 --- a/apimanager/locale/generatePo.py +++ b/apimanager/locale/generatePo.py @@ -7,29 +7,27 @@ languages=['de','es','fr','hi'] # Defining languages # This class is used for converting languages -class clsTranslate(): - def translateText(self, strString, strTolang): +class languageConverting(): + def parametersTextConverte(self, stString, prevlangToNewlang): """ This function translates one language into another language. It takes two parameters - 1. strString :=> String that you want to convert - 2. strTolang :=> Languages(fr,hi,es etc) + 1. prevStrToNewString :=> String that you want to convert + 2. prevlangToNewlang :=> Languages(fr,hi,es etc) """ - self.strString = strString - self.strTolang = strTolang - translator = translator(text=self.strString, language=self.strTolang) + self.prevStrToNewString = prevStrToNewString + self.prevlangToNewlang = prevlangToNewlang + translator = translator(text=self.prevStrToNewString, language=self.prevlangToNewlang) return (str(translator)) # This is method for writing file -def writeFile(language): - print(language,"Started") +def localeWriteFile(language): fileName=f'locale/{language}/LC_MESSAGES/django.po' # Openning a file try: with open(fileName,encoding='utf-8') as f: # Reading from the file a=[i.replace("\n","") for i in f.readlines()] # Reading everyline from a file and store it into a except Exception as e: # same like try block. - print(fileName, e) b=0 for i in range(len(a)): if 'msgid' in a[i] and a[i]!='msgid ""': @@ -37,29 +35,25 @@ def writeFile(language): break if b!=0: - trans=clsTranslate() # Creating object for translation class + trans=languageConverting() # Creating object for translation class for i in range(b-1,len(a)): try: if "msgid" in a[i]: msgid,msgstr=a[i],a[i+1] if msgstr == 'msgstr ""': ms=msgid[7:len(msgid)-1] - val=trans.translateText(ms,language) + val=trans.parametersTextConverte(ms,language) a[i+1]=f'msgstr "{val}"' - # print(a[i]) except: pass try: lock.acquire() with open(fileName,'w',encoding='utf-8') as f: for i in a: f.write(f"{i}\n") - print(language,"is completed") lock.release() except Exception as e: - print(e) lock.release() else: - print(language,"is completed") with tpe() as e: - e.map(writeFile,languages) + e.map(localeWriteFile,languages) diff --git a/apimanager/methodrouting/static/methodrouting/js/methodrouting.js b/apimanager/methodrouting/static/methodrouting/js/methodrouting.js index 955a278..912fc07 100644 --- a/apimanager/methodrouting/static/methodrouting/js/methodrouting.js +++ b/apimanager/methodrouting/static/methodrouting/js/methodrouting.js @@ -7,14 +7,14 @@ $(document).ready(function($) { //each method_routing will have each own json_editor, and will put data into it when click `parameter` box //and will use the data from click `save` button. - var json_editors = [] + let json_editors = [] $('.parameters').click(function() { - var runner = $(this).parent().parent().parent(); - var json_editor_id= $(runner).find('.jsoneditor_div')[0].id; - var json_editor_number = json_editor_id.replace("jsoneditor",""); - var container = $("#"+json_editor_id); - parameters = JSON.parse($(runner).find('textarea[name="parameters"]').text()); - var jsoneditor_div = $(runner).find('.jsoneditor_div'); + let runner = $(this).parent().parent().parent(); + let json_editor_id= $(runner).find('.jsoneditor_div')[0].id; + let json_editor_number = json_editor_id.replace("jsoneditor",""); + let container = $("#"+json_editor_id); + let parameters = JSON.parse($(runner).find('textarea[name="parameters"]').text()); + let jsoneditor_div = $(runner).find('.jsoneditor_div'); //make sure only create one jsoneditor_div block, click once to open and then close the block. if (typeof json_editors[json_editor_number] === 'undefined') { json_editors[json_editor_number] = new JSONEditor(container[0], options, parameters); @@ -30,21 +30,20 @@ $(document).ready(function($) { }); $('.runner button.forSave').click(function() { - var t = $(this); - var runner = $(this).parent().parent().parent(); - method_routing_id = $(runner).find('.method_routing_id').text(); - method_name = $(runner).find('.method_name').text(); - connector_name = $(runner).find('.connector_name').val(); - bank_id_pattern = $(runner).find('textarea[name="bank_id_pattern"]').val(); - is_bank_id_exact_match = $(runner).find('.is_bank_id_exact_match').val(); - parameters = $(runner).find('textarea[name="parameters"]').val(); - var jsoneditor_id= $(runner).find('.jsoneditor_div')[0].id; - var json_editor_number = jsoneditor_id.replace("jsoneditor",""); + let runner = $(this).parent().parent().parent(); + let method_routing_id = $(runner).find('.method_routing_id').text(); + let method_name = $(runner).find('.method_name').text(); + let connector_name = $(runner).find('.connector_name').val(); + let bank_id_pattern = $(runner).find('textarea[name="bank_id_pattern"]').val(); + let is_bank_id_exact_match = $(runner).find('.is_bank_id_exact_match').val(); + let parameters = $(runner).find('textarea[name="parameters"]').val(); + let jsoneditor_id= $(runner).find('.jsoneditor_div')[0].id; + let json_editor_number = jsoneditor_id.replace("jsoneditor",""); //if the user do not click the `parameters` box, then there is no json_editors here,so we use the parameters directly. if (typeof json_editors[json_editor_number] === 'undefined') { - parameters_Json_editor = parameters; + let parameters_Json_editor = parameters; } else { - parameters_Json_editor = JSON.stringify(json_editors[json_editor_number].get()); + let parameters_Json_editor = JSON.stringify(json_editors[json_editor_number].get()); } $('.runner button.forSave').attr("disabled","disabled"); $('.runner button.forDelete').attr("disabled","disabled"); @@ -63,9 +62,8 @@ $(document).ready(function($) { }); $('.runner button.forDelete').click(function() { - var t = $(this); - var runner = $(this).parent().parent().parent(); - method_routing_id = $(runner).find('.method_routing_id').text(); + let runner = $(this).parent().parent().parent(); + let method_routing_id = $(runner).find('.method_routing_id').text(); $('.runner button.forSave').attr("disabled","disabled"); $('.runner button.forDelete').attr("disabled","disabled"); $.post('methodrouting/delete/method', { diff --git a/apimanager/methodrouting/templates/methodrouting/index.html b/apimanager/methodrouting/templates/methodrouting/index.html index a586f7f..644124f 100644 --- a/apimanager/methodrouting/templates/methodrouting/index.html +++ b/apimanager/methodrouting/templates/methodrouting/index.html @@ -71,11 +71,11 @@ {% elif method_routing.connector_name == "rest_vMar2019" %} # This will be selected - - - - - + + + + + {% elif method_routing.connector_name == "kafka_vMay2019" %} # This will be selected @@ -99,7 +99,7 @@
    -
    +
    - -
    ` - - function systemCalls(){ - var checkbox = document.getElementById('include_system_calls_id'); - if (checkbox.checked == false) { - document.getElementById("obp_app_table").style.display = "none"; - }else{ - document.getElementById("obp_app_table").style.display = ""; - } -} \ No newline at end of file diff --git a/apimanager/metrics/static/metrics/js/metrics.js b/apimanager/metrics/static/metrics/js/metrics.js index 2718e81..621f8a1 100644 --- a/apimanager/metrics/static/metrics/js/metrics.js +++ b/apimanager/metrics/static/metrics/js/metrics.js @@ -1,5 +1,5 @@ $(document).ready(function($) { - var barChart = new Chart($("#barchart"), { + let barChart = new Chart($("#barchart"), { type: 'horizontalBar', data: { labels: BarchartData['labels'], diff --git a/apimanager/metrics/static/metrics/js/spinner.js b/apimanager/metrics/static/metrics/js/spinner.js new file mode 100644 index 0000000..461a7f2 --- /dev/null +++ b/apimanager/metrics/static/metrics/js/spinner.js @@ -0,0 +1,10 @@ +$(document).ready(function () { + $('.spinner').on('click', function() { + var e=this; + setTimeout(function() { + e.innerHTML=' Loading...'; + e.disabled=true; + },0); + return true; + }); +}); diff --git a/apimanager/metrics/templates/metrics/api.html b/apimanager/metrics/templates/metrics/api.html index 104c1c2..f6a6be4 100644 --- a/apimanager/metrics/templates/metrics/api.html +++ b/apimanager/metrics/templates/metrics/api.html @@ -120,7 +120,7 @@
    - +
    @@ -140,7 +140,7 @@ # - {% trans "Verb" %} + {% trans "Verb Select" %} {% trans "URL" %} {% trans "Date" %} {% trans "Duration(ms)" %} @@ -151,7 +151,7 @@ {% for metric in metrics %} {{ forloop.counter }} - {{ metric.verb }} + {{ metric.verb_selection }} {{ metric.url }} diff --git a/apimanager/metrics/templates/metrics/api_summary_partial_function.html b/apimanager/metrics/templates/metrics/api_summary_partial_function.html index fb2f312..733068c 100644 --- a/apimanager/metrics/templates/metrics/api_summary_partial_function.html +++ b/apimanager/metrics/templates/metrics/api_summary_partial_function.html @@ -4,7 +4,7 @@ {% block nav_tabs %}
  • {% trans "List" %}
  • -
  • {% trans "Summary by Partial Function" %}
  • +
  • {% trans "Summary by Partial Function" %}
  • {% endblock nav_tabs %} {% block tab_content %} diff --git a/apimanager/metrics/templates/metrics/connector.html b/apimanager/metrics/templates/metrics/connector.html index 3ef2dc9..cc67afc 100644 --- a/apimanager/metrics/templates/metrics/connector.html +++ b/apimanager/metrics/templates/metrics/connector.html @@ -21,28 +21,28 @@
    {% if form.from_date.errors %}
    {{ form.from_date.errors }}
    {% endif %}
    - {% trans "from_date" %} + {% trans "From Date" %} {{ form.from_date }}
    {% if form.to_date.errors %}
    {{ form.to_date.errors }}
    {% endif %}
    - {% trans "to_date" %} + {% trans "To Date" %} {{ form.to_date }}
    {% if form.limit.errors %}
    {{ form.limit.errors }}
    {% endif %}
    - {% trans "limit" %} + {% trans "Limit" %} {{ form.limit }}
    {% if form.offset.errors %}
    {{ form.offset.errors }}
    {% endif %}
    - {% trans "offset" %} + {% trans "Offset" %} {{ form.offset }}
    @@ -52,27 +52,27 @@
    {% if form.connector_name.errors %}
    {{ form.connector_name.errors }}
    {% endif %}
    - {% trans "connector_name" %} + {% trans "Connector Name" %} {{ form.connector_name }}
    {% if form.function_name.errors %}
    {{ form.function_name.errors }}
    {% endif %}
    - {% trans "function_name" %} + {% trans "Function Name" %} {{ form.function_name }}
    {% if form.correlation_id.errors %}
    {{ form.correlation_id.errors }}
    {% endif %}
    - {% trans "correlation_id" %} + {% trans "Correlation Id" %} {{ form.correlation_id }}
    - +
    diff --git a/apimanager/metrics/templates/metrics/custom_summary.html b/apimanager/metrics/templates/metrics/custom_summary.html index 311f246..a95e0b2 100644 --- a/apimanager/metrics/templates/metrics/custom_summary.html +++ b/apimanager/metrics/templates/metrics/custom_summary.html @@ -2,6 +2,7 @@ {% load static %} {% load i18n %} {% block page_title %}{{ block.super }} / API Usage Report{% endblock page_title %} +{% load bootstrap3 %} {% block content %}

    {% trans "API Usage Report" %}

    @@ -14,15 +15,12 @@
  • {% trans "Month" %}
  • {% trans "Week" %}
  • {% trans "Day" %}
  • -
  • {% trans "Custom" %}
  • {% endblock nav_tabs %}
    - - {% bootstrap_javascript jquery='full' %} {# Embed Bootstrap JS+jQuery #} {% block extrahead %} {# Extra Resources Start #} @@ -40,39 +38,32 @@
    {% if form.from_date_custom.errors %}
    {{ form.from_date_custom.errors }}
    {% endif %}
    - {% trans "from_date_custom" %} + {% trans "From Date Custom" %} {{ form.from_date_custom }}
    {% if form.to_date.errors %}
    {{ form.to_date.errors }}
    {% endif %}
    - {% trans "to_date" %} + {% trans "To Date Custom" %} {{ form.to_date }}
    - {% if form.exclude_app_names.errors %}
    {{ form.exclude_app_names.errors }}
    {% endif %} + {% if form.include_app_names.errors %}
    {{ form.include_app_names.errors }}
    {% endif %}
    - {{ form.exclude_app_names.label_tag }} - {{ form.exclude_app_names }} -
    -
    -
    -
    - {{ form.include_obp_apps }} - {{ form.include_obp_apps.label_tag }} + {{ form.include_app_names.label_tag }} + {{ form.include_app_names }}
    - +
    - {% if form.include_obp_apps.value %} {% block tab_content %}
    -

    {% trans "Period" %}: {% trans "From" %}{{ from_date }} {% trans "to" %}{{ to_date }}

    +

    {% if include_app_names != "" %} {{ include_app_names }} : {% endif %}{{ from_date }} - {{ to_date }}

    @@ -83,10 +74,10 @@ - + @@ -126,7 +117,7 @@ - +
    {% trans "Total API calls" %}: {{ api_calls }}
    {% trans "Calls per day (last 30 days)" %}:{% trans "Top 10 Consumers" %}: somealt
    {% endblock tab_content %} - {% else %} -

    {% trans "Period" %} : {% trans "From" %} {{ from_date }} {% trans "to" %} {{ to_date }}

    - {% endif %}
    @@ -157,6 +145,9 @@ {% endblock %} +{% block extrajs %} + +{% endblock extrajs %} {% block extracss %} {% endblock extracss %} \ No newline at end of file diff --git a/apimanager/metrics/templates/metrics/daily_summary.html b/apimanager/metrics/templates/metrics/daily_summary.html index 38c2b7c..02c2eb4 100644 --- a/apimanager/metrics/templates/metrics/daily_summary.html +++ b/apimanager/metrics/templates/metrics/daily_summary.html @@ -5,6 +5,7 @@ {% block page_title %}{{ block.super }} / API Usage Report{% endblock page_title %} +{% load bootstrap3 %} {% block content %}
    @@ -19,15 +20,12 @@
  • {% trans "Month" %}
  • {% trans "Week" %}
  • {% trans "Day" %}
  • -
  • {% trans "Custom" %}
  • {% endblock nav_tabs %}
    - - {% bootstrap_javascript jquery='full' %} {# Embed Bootstrap JS+jQuery #} {% block extrahead %} {# Extra Resources Start #} @@ -47,36 +45,29 @@
    {% if form.to_date.errors %}
    {{ form.to_date.errors }}
    {% endif %}
    - {% trans "to_date" %} + {% trans "To Date" %} {{ form.to_date }}
    - {% if form.exclude_app_names.errors %}
    {{ form.exclude_app_names.errors }}
    {% endif %} + {% if form.include_app_names.errors %}
    {{ form.include_app_names.errors }}
    {% endif %}
    - {{ form.exclude_app_names.label_tag }} - {{ form.exclude_app_names }} -
    -
    -
    -
    - {{ form.include_obp_apps }} - {{ form.include_obp_apps.label_tag }} + {{ form.include_app_names.label_tag }} + {{ form.include_app_names }}
    - +
    - {% if form.include_obp_apps.value %} {% block tab_content %}
    -

    {% trans "Period" %} : {% trans "From" %} {{ from_date }} {% trans "to" %} {{ to_date }}

    +

    {% if include_app_names != "" %} {{ include_app_names }} : {% endif %}{{ from_date }} - {{ to_date }}

    - +
    @@ -85,10 +76,10 @@ - + @@ -129,7 +120,7 @@ - +
    {% trans "Total API calls" %}: {{ api_calls }}
    {% trans "Calls per hour" %}:{% trans "Top 10 Consumers" %}: somealt
    {% endblock tab_content %} - {% else %} -

    {% trans "Period" %} : {% trans "From" %} {{ from_date }} {% trans "to" %} {{ to_date }}

    - {% endif %}
    diff --git a/apimanager/metrics/templates/metrics/hourly_summary.html b/apimanager/metrics/templates/metrics/hourly_summary.html index ca3398b..bef6d8d 100644 --- a/apimanager/metrics/templates/metrics/hourly_summary.html +++ b/apimanager/metrics/templates/metrics/hourly_summary.html @@ -3,6 +3,7 @@ {% block page_title %}{{ block.super }} / API Usage Report{% endblock page_title %} +{% load bootstrap3 %} {% block content %}
    @@ -24,8 +25,6 @@
    - - {% bootstrap_javascript jquery='full' %} {# Embed Bootstrap JS+jQuery #} {% block extrahead %} {# Extra Resources Start #} @@ -50,31 +49,24 @@
    - {% if form.exclude_app_names.errors %}
    {{ form.exclude_app_names.errors }}
    {% endif %} + {% if form.include_app_names.errors %}
    {{ form.include_app_names.errors }}
    {% endif %}
    - {{ form.exclude_app_names.label_tag }} - {{ form.exclude_app_names }} -
    -
    -
    -
    - {{ form.include_obp_apps }} - {{ form.include_obp_apps.label_tag }} + {{ form.include_app_names.label_tag }} + {{ form.include_app_names }}
    - +
    - {% if form.include_obp_apps.value %} {% block tab_content %}
    -

    {% trans "Period" %}: {% trans "From" %}{{ from_date }} {% trans "to" %} {{ to_date }}

    +

    {% if include_app_names != "" %} {{ include_app_names }} : {% endif %}{{ from_date }} - {{ to_date }}

    - +
    @@ -83,17 +75,17 @@ - + + + + - - - - - + @@ -126,7 +118,7 @@ - +
    {% trans "API calls" %}: {{ api_calls }}
    {% trans "Calls per minute" %}:{%for item in calls_per_hour_list%}
    1. {{item}}
  • {% endfor %}
    {% trans "Calls per minute" %}:{%for item in calls_per_hour_list%}
  • {{item}}
  • {% endfor %}
    {% trans "Calls per minute" %}:somealtsomealt
    {% trans "Average number of calls hour" %}: {% trans "Top APIs" %}: somealt
    {% endblock tab_content %} - {% else %} -

    {% trans "Period" %} : {% trans "From" %} {{ from_date }} {% trans "to" %} {{ to_date }}

    - {% endif %}
    diff --git a/apimanager/metrics/templates/metrics/monthly_summary.html b/apimanager/metrics/templates/metrics/monthly_summary.html index 8bcffa3..2932ed6 100644 --- a/apimanager/metrics/templates/metrics/monthly_summary.html +++ b/apimanager/metrics/templates/metrics/monthly_summary.html @@ -2,6 +2,7 @@ {% load static %} {% load i18n %} {% block page_title %}{{ block.super }} / API Usage Report{% endblock page_title %} +{% load bootstrap3 %} {% block content %}

    {% trans "API Usage Report" %}

    @@ -14,15 +15,12 @@
  • {% trans "Month" %}
  • {% trans "Week" %}
  • {% trans "Day" %}
  • -
  • {% trans "Custom" %}
  • {% endblock nav_tabs %}
    - - {% bootstrap_javascript jquery='full' %} {# Embed Bootstrap JS+jQuery #} {% block extrahead %} {# Extra Resources Start #} @@ -42,36 +40,29 @@
    {% if form.to_date.errors %}
    {{ form.to_date.errors }}
    {% endif %}
    - {% trans "to_date" %} + {% trans "To Date" %} {{ form.to_date }}
    - {% if form.exclude_app_names.errors %}
    {{ form.exclude_app_names.errors }}
    {% endif %} + {% if form.include_app_names.errors %}
    {{ form.include_app_names.errors }}
    {% endif %}
    - {{ form.exclude_app_names.label_tag }} - {{ form.exclude_app_names }} -
    -
    -
    -
    - {{ form.include_obp_apps }} - {{ form.include_obp_apps.label_tag }} + {{ form.include_app_names.label_tag }} + {{ form.include_app_names }}
    - +
    - {% if form.include_obp_apps.value %} {% block tab_content %}
    -

    {% trans "Period" %}: {% trans "From" %} {{ from_date }} {% trans "to" %} {{ to_date }}

    +

    {% if include_app_names != "" %} {{ include_app_names }} : {% endif %}{{ from_date }} - {{ to_date }}

    - +
    @@ -80,10 +71,10 @@ - + @@ -123,7 +114,7 @@ - +
    {% trans "Total API calls" %}: {{ api_calls }}
    {% trans "Calls per day" %}:{% trans "Top 10 Consumers" %}: somealt
    {% endblock tab_content %} - {% else %} -

    {% trans "Period" %} : {% trans "From" %} {{ from_date }} {% trans "to" %} {{ to_date }}

    - {% endif %}
    diff --git a/apimanager/metrics/templates/metrics/quarterly_summary.html b/apimanager/metrics/templates/metrics/quarterly_summary.html index 9ad4589..d47fcfc 100644 --- a/apimanager/metrics/templates/metrics/quarterly_summary.html +++ b/apimanager/metrics/templates/metrics/quarterly_summary.html @@ -4,6 +4,7 @@ {% block page_title %}{{ block.super }} / API Usage Report{% endblock page_title %} +{% load bootstrap3 %} {% block content %}
    @@ -18,15 +19,12 @@
  • {% trans "Month" %}
  • {% trans "Week" %}
  • {% trans "Day" %}
  • -
  • {% trans "Custom" %}
  • {% endblock nav_tabs %}
    - - {% bootstrap_javascript jquery='full' %} {# Embed Bootstrap JS+jQuery #} {% block extrahead %} {# Extra Resources Start #} @@ -51,31 +49,24 @@
    - {% if form.exclude_app_names.errors %}
    {{ form.exclude_app_names.errors }}
    {% endif %} + {% if form.include_app_names.errors %}
    {{ form.include_app_names.errors }}
    {% endif %}
    - {{ form.exclude_app_names.label_tag }} - {{ form.exclude_app_names }} -
    -
    -
    -
    - {{ form.include_obp_apps }} - {{ form.include_obp_apps.label_tag }} + {{ form.include_app_names.label_tag }} + {{ form.include_app_names }}
    - +
    - {% if form.include_obp_apps.value %} {% block tab_content %}
    -

    {% trans "Period" %}:{% trans "From" %} {{ from_date }} {% trans "to" %} {{ to_date }}

    +

    {% if include_app_names != "" %} {{ include_app_names }} : {% endif %}{{ from_date }} - {{ to_date }}

    - +
    @@ -84,10 +75,10 @@ - + @@ -132,7 +123,7 @@ - +
    {% trans "Total API calls" %}: {{ api_calls }}
    {% trans "Calls per month" %}:{% trans "Top 10 Consumers" %}: somealt
    {% endblock tab_content %} - {% else %} -

    {% trans "Period" %} : {% trans "From" %} {{ from_date }} {% trans "to" %} {{ to_date }}

    - {% endif %}
    diff --git a/apimanager/metrics/templates/metrics/weekly_summary.html b/apimanager/metrics/templates/metrics/weekly_summary.html index 5dd276e..91d2857 100644 --- a/apimanager/metrics/templates/metrics/weekly_summary.html +++ b/apimanager/metrics/templates/metrics/weekly_summary.html @@ -4,6 +4,7 @@ {% block page_title %}{{ block.super }} / API Usage Report{% endblock page_title %} +{% load bootstrap3 %} {% block content %}
    @@ -20,15 +21,12 @@
  • {% trans "Month" %}
  • {% trans "Week" %}
  • {% trans "Day" %}
  • -
  • {% trans "Custom" %}
  • {% endblock nav_tabs %}
    - - {% bootstrap_javascript jquery='full' %} {# Embed Bootstrap JS+jQuery #} {% block extrahead %} {# Extra Resources Start #} @@ -53,29 +51,22 @@
    - {% if form.exclude_app_names.errors %}
    {{ form.exclude_app_names.errors }}
    {% endif %} + {% if form.include_app_names.errors %}
    {{ form.include_app_names.errors }}
    {% endif %}
    - {{ form.exclude_app_names.label_tag }} - {{ form.exclude_app_names }} -
    -
    -
    -
    - {{ form.include_obp_apps }} - {{ form.include_obp_apps.label_tag }} + {{ form.include_app_names.label_tag }} + {{ form.include_app_names }}
    - +
    - {% if form.include_obp_apps.value %} {% block tab_content %}
    -

    {% trans "Period" %} : {% trans "From" %} {{ from_date }} {% trans "to" %} {{ to_date }}

    +

    {% if include_app_names != "" %} {{ include_app_names }} : {% endif %}{{ from_date }} - {{ to_date }}

    - +
    @@ -84,10 +75,10 @@ - + @@ -128,7 +119,7 @@ - +
    {% trans "Total API calls" %}: {{ api_calls }}
    {% trans "Calls per day" %}:{% trans "Top 10 Consumers" %}: somealt
    {% endblock tab_content %} - {% else %} -

    {% trans "Period" %} : {% trans "From" %} {{ from_date }} {% trans "to" %} {{ to_date }}

    - {% endif %}
    diff --git a/apimanager/metrics/templates/metrics/yearly_summary.html b/apimanager/metrics/templates/metrics/yearly_summary.html index 86716c0..67d7f76 100644 --- a/apimanager/metrics/templates/metrics/yearly_summary.html +++ b/apimanager/metrics/templates/metrics/yearly_summary.html @@ -4,6 +4,7 @@ {% block page_title %}{{ block.super }} / API Usage Report{% endblock page_title %} +{% load bootstrap3 %} {% block content %}
    @@ -20,15 +21,12 @@
  • {% trans "Month" %}
  • {% trans "Week" %}
  • {% trans "Day" %}
  • -
  • {% trans "Custom" %}
  • {% endblock nav_tabs %}
    - - {% bootstrap_javascript jquery='full' %} {# Embed Bootstrap JS+jQuery #} {% block extrahead %} {# Extra Resources Start #} @@ -53,30 +51,21 @@
    - {% if form.exclude_app_names.errors %}
    {{ form.exclude_app_names.errors }}
    {% endif %} + {% if form.include_app_names.errors %}
    {{ form.include_app_names.errors }}
    {% endif %}
    - {{ form.exclude_app_names.label_tag }} - {{ form.exclude_app_names }} -
    -
    -
    -
    - {{ form.include_obp_apps }} - {{ form.include_obp_apps.label_tag }} + {{ form.include_app_names.label_tag }} + {{ form.include_app_names }}
    - +
    - {% if form.include_obp_apps.value %} {% block tab_content %} -
    -

    {% trans "Period" %} : {% trans "From" %} {{ from_date }} {% trans "to" %} {{ to_date }}

    - - +

    {% if include_app_names != "" %} {{ include_app_names }} : {% endif %}{{ from_date }} - {{ to_date }}

    +
    @@ -86,10 +75,10 @@ - + @@ -114,7 +103,7 @@ - + @@ -130,7 +119,7 @@ - +
    {% trans "Total API calls" %}: {{ api_calls }}
    {% trans "Calls per month" %}:{{ number_of_apps_with_unique_app_name }}
    {% trans "Apps with distinct developer email addresses:{% trans "Apps with distinct developer email addresses:" %} {{ number_of_apps_with_unique_developer_email }}
    {% trans "Top 10 Consumers" %}: somealt
    {% endblock tab_content %} - {% else %} -

    {% trans "Period" %} : {% trans "From" %} {{ from_date }} {% trans "to" %} {{ to_date }}

    - {% endif %}
    diff --git a/apimanager/metrics/views.py b/apimanager/metrics/views.py index b57633a..c21657d 100644 --- a/apimanager/metrics/views.py +++ b/apimanager/metrics/views.py @@ -11,7 +11,7 @@ from enum import Enum from django.conf import settings from apimanager import local_settings -from apimanager.settings import API_HOST, EXCLUDE_APPS, EXCLUDE_FUNCTIONS, EXCLUDE_URL_PATTERN, API_EXPLORER_APP_NAME, API_DATEFORMAT +from apimanager.settings import API_HOST, EXCLUDE_APPS, EXCLUDE_FUNCTIONS, EXCLUDE_URL_PATTERN, API_EXPLORER_APP_NAME, API_DATE_FORMAT, API_DATE_TIME_FORMAT, DEBUG from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic import TemplateView @@ -33,6 +33,11 @@ import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import statistics +import urllib.parse + + +CACHE_SETTING_URL_MSG = "The cache setting url is" +CACHE_SETTING_KEY_MSG = "The cache setting key is" def get_random_color(to_hash): hashed = str(int(hashlib.md5(to_hash.encode('utf-8')).hexdigest(), 16)) @@ -109,7 +114,7 @@ class MetricsView(LoginRequiredMixin, TemplateView): """ for metric in metrics: metric['date'] = datetime.datetime.strptime( - metric['date'], settings.API_DATETIMEFORMAT) + metric['date'], settings.API_DATE_TIME_FORMAT) return metrics def to_api(self, cleaned_data): @@ -124,7 +129,7 @@ class MetricsView(LoginRequiredMixin, TemplateView): # Maybe we should define the API format as Django format to not # have to convert in places like this? if value.__class__.__name__ == 'datetime': - value = value.strftime(settings.API_DATEFORMAT) + value = value.strftime(settings.API_DATE_FORMAT) if value: # API does not like quoted data params.append('{}={}'.format(name, value)) @@ -143,11 +148,17 @@ class MetricsView(LoginRequiredMixin, TemplateView): metrics = api.get(urlpath) metrics = self.to_django(metrics['metrics']) except APIError as err: + if DEBUG: + raise(err) error_once_only(self.request, err) except KeyError as err: + if DEBUG: + raise(err) error_once_only(self.request, metrics['message']) except Exception as err: - error_once_only(self.request, 'Unknown Error. {}'.format(err)) + if DEBUG: + raise(err) + error_once_only(self.request, err) return metrics def get_context_data(self, **kwargs): @@ -197,13 +208,13 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): template_name = 'metrics/monthly_summary.html' api_urlpath = None - def get_form(self, web_page_type = ""): + def get_form(self): """ Get bound form either from request.GET or initials We need a bound form because we already send a request to the API without user intervention on initial request """ - if (self.request.GET) and (web_page_type != SummaryType.CUSTOM): + if self.request.GET: data = self.request.GET else: fields = self.form_class.declared_fields @@ -221,7 +232,7 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): """ for metric in metrics: metric['date'] = datetime.datetime.strptime( - metric['date'], API_DATEFORMAT) + metric['date'], API_DATE_FORMAT) return metrics def to_api(self, cleaned_data): @@ -236,113 +247,151 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): # Maybe we should define the API format as Django format to not # have to convert in places like this? if value.__class__.__name__ == 'datetime': - value = value.strftime(settings.API_DATEFORMAT) + value = value.strftime(settings.API_DATE_FORMAT) if value: # API does not like quoted data params.append('{}={}'.format(name, value)) params = '&'.join(params) return params - - def get_aggregate_metrics(self, from_date, to_date, is_included_obp_apps, only_show_api_explorer_metrics = False): + def get_app_name_parameters(self, include_app_names): + #if len(app_names) == 1: + # return + #1. Parse include_app_names create a list using a commo (,) separator + #2. Trim each word (remove space), + #3. Then is one word, &app_name = thing + #4. IF IT IS MORE than one word then return number of app without space + #5. return either &app_name=thing + #6. Or + #7. return &include_app_names=thing1,thing2, + #8. url encode + #app_names = [] + #input_string = "simon says, foo, bar , App 2 " + input_string = include_app_names.strip() + result = "" + if input_string != "": + input_list = input_string.strip().split(",") + #print("input_list is:", input_list) + cleaned_list = [item.strip() for item in input_list] + #print("cleaned_list is: ", cleaned_list) + cleaned_string=', '.join([str(item) for item in cleaned_list]) + #print("cleaned_string is:", cleaned_string) + url_encoded_string = urllib.parse.quote(cleaned_string) + #print("url_encoded_string is:", url_encoded_string) + if len(cleaned_list) == 0: + result = "" + elif len(cleaned_list) == 1: + result = "&app_name={}".format(url_encoded_string) + else: + result = "&include_app_names={}".format(url_encoded_string) + return result + def get_aggregate_metrics(self, from_date, to_date, include_app_names): """ Gets the metrics from the API, using given parameters, There are different use cases, so we accept different parameters. only_show_api_explorer_metrics has the default value False, because it is just used for app = API_Explorer. """ try: + print("get_app_name_parameters is: ", self.get_app_name_parameters(include_app_names)) api_calls_total = 0 average_response_time = 0 - urlpath = '/management/aggregate-metrics' - if only_show_api_explorer_metrics: - urlpath = urlpath + '?from_date={}&to_date={}&app_name={}'.format(from_date, to_date, API_EXPLORER_APP_NAME) - elif ((not only_show_api_explorer_metrics) and (not is_included_obp_apps)): - urlpath = urlpath + '?from_date={}&to_date={}&exclude_app_names={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format( - from_date, to_date, ",".join(local_settings.EXCLUDE_APPS),",".join(EXCLUDE_FUNCTIONS), ",".join(EXCLUDE_URL_PATTERN)) - else: - urlpath = urlpath + '?from_date={}&to_date={}'.format(from_date, to_date) - cache_key = get_cache_key_for_current_call(self.request, urlpath) - apicaches = None + url_path = '/management/aggregate-metrics' + #if only_show_api_explorer_metrics: + # urlpath = urlpath + '?from_date={}&to_date={}&app_name={}'.format(from_date, to_date) + #elif (not only_show_api_explorer_metrics): + # urlpath = urlpath + '?from_date={}&to_date={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format( + # from_date, to_date, ",".join(local_settings.EXCLUDE_FUNCTIONS), ",".join(local_settings.EXCLUDE_URL_PATTERN)) + # + #else: + url_path = url_path + '?from_date={}&to_date={}{}'.format(from_date, to_date, self.get_app_name_parameters(include_app_names)) + #print("get_app_name_parameters(include_app_names) is:", self.get_app_name_parameters(include_app_names)) + #print("url_path is: ", url_path) + cache_key = get_cache_key_for_current_call(self.request, url_path) + api_cache = None try: - apicaches = cache.get(cache_key) + api_cache = cache.get(cache_key) except Exception as err: - apicaches = None - if not apicaches is None: - metrics = apicaches + api_cache = None + if not api_cache is None: + metrics = api_cache else: api = API(self.request.session.get('obp')) - metrics = api.get(urlpath) - apicaches = cache.set(cache_key, metrics) - LOGGER.warning('The cache is setting, url is: {}'.format(urlpath)) - LOGGER.warning('The cache is setting key is: {}'.format(cache_key)) + metrics = api.get(url_path) + api_cache = cache.set(cache_key, metrics) + LOGGER.warning('{0}: {1}'.format(CACHE_SETTING_URL_MSG, url_path)) + LOGGER.warning('{0}: {1}'.format(CACHE_SETTING_KEY_MSG, cache_key)) api_calls_total, average_calls_per_day, average_response_time = self.get_internal_api_call_metrics( - api_calls_total, average_response_time, cache_key, from_date, metrics, to_date, urlpath) + api_calls_total, average_response_time, cache_key, from_date, metrics, to_date, url_path) return api_calls_total, average_response_time, int(average_calls_per_day) except APIError as err: + if DEBUG: + raise(err) error_once_only(self.request, err) except Exception as err: - error_once_only(self.request, 'Unknown Error. {}'.format(err)) + if DEBUG: + raise(err) + error_once_only(self.request, err) def get_internal_api_call_metrics(self, api_calls_total, average_response_time, cache_key, from_date, metrics, to_date, urlpath): api_calls_total = metrics[0]["count"] average_response_time = metrics[0]["average_response_time"] - to_date = datetime.datetime.strptime(to_date, API_DATEFORMAT) - from_date = datetime.datetime.strptime(from_date, API_DATEFORMAT) + to_date = datetime.datetime.strptime(to_date, API_DATE_FORMAT) + from_date = datetime.datetime.strptime(from_date, API_DATE_FORMAT) number_of_days = abs((to_date - from_date).days) # if number_of_days= 0, then it means calls_per_hour average_calls_per_day = api_calls_total if (number_of_days == 0) else api_calls_total / number_of_days return api_calls_total, average_calls_per_day, average_response_time - def get_aggregate_metrics_api_explorer(self, from_date, to_date): - return self.get_aggregate_metrics(from_date, to_date, True, True) - - def get_active_apps(self, is_included_obp_apps, from_date, to_date, exclude_app_names): + def get_active_apps(self, from_date, to_date): """ Gets the metrics from the API, using given parameters, - There are different use cases, so we accept different parameters. - only_show_api_explorer_metrics has the default value False, because it is just used for app = API_Explorer. """ apps = [] form = self.get_form() active_apps_list = [] - if is_included_obp_apps: - urlpath = '/management/metrics/top-consumers?from_date={}&to_date={}&exclude_app_names={}'.format(from_date, to_date, exclude_app_names) - api = API(self.request.session.get('obp')) - try: - apps = api.get(urlpath) - if apps is not None and 'code' in apps and apps['code']==403: - error_once_only(self.request, apps['message']) - else: - active_apps_list = list(apps) - except APIError as err: - error_once_only(self.request, err) - except Exception as err: - error_once_only(self.request, 'Unknown Error. {}'.format(err)) + urlpath = '/management/metrics/top-consumers?from_date={}&to_date={}'.format(from_date, to_date) + api = API(self.request.session.get('obp')) + try: + apps = api.get(urlpath) + if apps is not None and 'code' in apps and apps['code']==403: + error_once_only(self.request, apps['message']) + else: + active_apps_list = list(apps) + except APIError as err: + error_once_only(self.request, err) + except Exception as err: + if DEBUG: + raise(err) + error_once_only(self.request, err) else: - urlpath = '/management/metrics/top-consumers?from_date={}&to_date={}&exclude_app_names={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format( - from_date, to_date, ",".join(local_settings.EXCLUDE_APPS), ",".join(EXCLUDE_FUNCTIONS), ",".join(EXCLUDE_URL_PATTERN)) + urlpath = '/management/metrics/top-consumers?from_date={}&to_date={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format( + from_date, to_date, ",".join(EXCLUDE_FUNCTIONS), ",".join(EXCLUDE_URL_PATTERN)) api = API(self.request.session.get('obp')) try: apps = api.get(urlpath) active_apps_list = list(apps['top_consumers']) except APIError as err: + if DEBUG: + raise(err) error_once_only(self.request, err) except Exception as err: - error_once_only(self.request, 'Unknown Error. {}'.format(err)) + if DEBUG: + raise(err) + error_once_only(self.request, err) return active_apps_list def get_total_number_of_apps(self, cleaned_data, from_date, to_date): apps = [] - from_date = datetime.datetime.strptime(from_date, API_DATEFORMAT) - to_date = datetime.datetime.strptime(to_date, API_DATEFORMAT) + from_date = datetime.datetime.strptime(from_date, API_DATE_FORMAT) + to_date = datetime.datetime.strptime(to_date, API_DATE_FORMAT) apps_list = self.get_all_consumers() for app in apps_list: - app_created_date = datetime.datetime.strptime(app["created"], '%Y-%m-%dT%H:%M:%SZ') + app_created_date = datetime.datetime.strptime(app["created"], API_DATE_TIME_FORMAT) if app_created_date < from_date and app_created_date > to_date: apps_list.remove(app) @@ -353,12 +402,10 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): app_names.append(apps["app_name"]) # If include OBP Apps is selected - if cleaned_data.get('include_obp_apps'): - app_names = app_names - else: - for app in app_names: - if app in local_settings.EXCLUDE_APPS: - app_names.remove(app) + #if not cleaned_data.get('include_obp_apps'): + # for app in app_names: + # if app in local_settings.EXCLUDE_APPS: + # app_names.remove(app) app_names = list(filter(None, app_names)) @@ -380,35 +427,39 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): urlpath = '/management/consumers' api = API(self.request.session.get('obp')) cache_key = get_cache_key_for_current_call(self.request, urlpath) - apicaches = None + api_cache = None try: - apicaches = cache.get(cache_key) + api_cache = cache.get(cache_key) except Exception as err: - apicaches = None - if not apicaches is None: - apps_list = apicaches + api_cache = None + if api_cache is not None: + apps_list = api_cache else: try: apps = api.get(urlpath) apps_list = apps["consumers"] cache.set(cache_key, apps_list, 60 * 60) # for the consumers we cache for 1 hour, consumers may be increased - LOGGER.warning('The cache is setting, url is: {}'.format(urlpath)) - LOGGER.warning('The cache is setting key is: {}'.format(cache_key)) + LOGGER.warning('{0}: {1}'.format(CACHE_SETTING_URL_MSG, urlpath)) + LOGGER.warning('{0}: {1}'.format(CACHE_SETTING_KEY_MSG, cache_key)) except APIError as err: + if DEBUG: + raise(err) error_once_only(self.request, err) except Exception as err: - error_once_only(self.request, 'Unknown Error. {}'.format(err)) + if DEBUG: + raise(err) + error_once_only(self.request, err) return apps_list - def calls_per_delta(self, is_included_obp_apps, from_date_string, to_date_string, exclude_app_names, **delta ): + def calls_per_delta(self, from_date_string, to_date_string, include_app_names, **delta ): """ return how many calls were made in total per given delta. Here we need to convert date_string to datetime object, and calculate the dates. """ # we need to convert string to datetime object, then we can calculate the date - from_datetime_object = datetime.datetime.strptime(from_date_string, API_DATEFORMAT) - to_datetime_object = datetime.datetime.strptime(to_date_string , API_DATEFORMAT) + from_datetime_object = datetime.datetime.strptime(from_date_string, API_DATE_FORMAT) + to_datetime_object = datetime.datetime.strptime(to_date_string , API_DATE_FORMAT) time_delta_in_loop = from_datetime_object + timedelta(**delta) result_list = [] @@ -417,16 +468,18 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): while time_delta_in_loop <= to_datetime_object: try: # here we need to first convert datetime object to String - form_date= from_datetime_object.strftime(API_DATEFORMAT) - to_date= time_delta_in_loop.strftime(API_DATEFORMAT) - aggregate_metrics = self.get_aggregate_metrics(form_date, to_date, is_included_obp_apps) + form_date= from_datetime_object.strftime(API_DATE_FORMAT) + to_date= time_delta_in_loop.strftime(API_DATE_FORMAT) + aggregate_metrics = self.get_aggregate_metrics(form_date, to_date, include_app_names) result = aggregate_metrics[0] result_list_pure.append(result) result_list.append('{} - {} # {}'.format(from_datetime_object, time_delta_in_loop, result)) date_list.append(from_datetime_object) except Exception as err: + if DEBUG: + raise(err) + error_once_only(self.request, err) break - error_once_only(self.request, 'Unknown Error. {}'.format(err)) from_datetime_object = time_delta_in_loop time_delta_in_loop = time_delta_in_loop + timedelta(**delta) @@ -434,21 +487,20 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): return (result_list, result_list_pure, date_list) - def calls_per_month(self, is_included_obp_apps, from_date, to_date, exclude_app_names): + def calls_per_month(self,from_date, to_date, include_app_names): """ Convenience function to print number of calls per month It is actually 30 days, not a month """ - calls_per_month_list, calls_per_month, month_list = self.calls_per_delta(is_included_obp_apps, from_date, to_date, exclude_app_names, days=30) + calls_per_month_list, calls_per_month, month_list = self.calls_per_delta(from_date, to_date, include_app_names, days=30) return calls_per_month_list, calls_per_month, month_list - def calls_per_day(self, is_included_obp_apps, from_date, to_date, exclude_app_names): + def calls_per_day(self,from_date, to_date, include_app_names): """ Convenience function to print number of calls per day """ - index = [] - calls_per_day, calls_per_day_pure, date_list = self.calls_per_delta(is_included_obp_apps, from_date, to_date,exclude_app_names, days=1) + calls_per_day, calls_per_day_pure, date_list = self.calls_per_delta(from_date, to_date, include_app_names, days=1) if len(calls_per_day) >= 90: calls_per_day = calls_per_day[-90:] @@ -462,18 +514,18 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): return calls_per_day, calls_per_day_pure, date_list - def calls_per_half_day(self, is_included_obp_apps, from_date): + def calls_per_half_day(self,from_date, include_app_names): """ Convenience function to print number of calls per half day """ - return self.calls_per_delta(is_included_obp_apps, from_date, exclude_app_names, hours=12) + return self.calls_per_delta(from_date, hours=12) - def calls_per_hour(self, is_included_obp_apps, from_date, to_date, exclude_app_names): + def calls_per_hour(self,from_date, to_date, include_app_names): """ Convenience function to print number of calls per hour """ - calls_per_hour_list, calls_per_hour, hour_list = self.calls_per_delta(is_included_obp_apps, from_date, to_date, exclude_app_names, hours=1) + calls_per_hour_list, calls_per_hour, hour_list = self.calls_per_delta(from_date, to_date, include_app_names, hours=1) return calls_per_hour_list, calls_per_hour, hour_list def plot_line_chart(self, plot_data, date_month_list, period): @@ -482,40 +534,13 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): hour_list = [] if period == 'day': - if len(plot_data) == 0: - plt.xlabel("Dates", fontsize=8) - plt.plot() - else: - plt.title("API calls per day", fontsize=14) - plt.xlabel("Dates", fontsize=8) - for date in date_month_list: - date = date.strftime('%B %d') - date_list.append(str(date)) - plt.plot(date_list, plot_data, linewidth=1, marker='o') + self._day(plot_data, date_month_list, date_list) elif period == 'month': - if len(plot_data) == 0: - plt.xlabel("Months", fontsize=8) - plt.plot() - else: - plt.title("API calls per month", fontsize=14) - plt.xlabel("Months", fontsize=8) - for date in date_month_list: - month = date.strftime('%B %Y') - month_list.append(str(month)) - plt.plot(month_list, plot_data, linewidth=1, marker='o') + self._month(plot_data, date_month_list, month_list) elif period == 'hour': - if len(plot_data) == 0: - plt.xlabel("Hours", fontsize=8) - plt.plot() - else: - plt.title("API calls per hour", fontsize=14) - plt.xlabel("Hours", fontsize=8) - for date in date_month_list: - hour = date.strftime('%B %d -- %H : %m') - hour_list.append(str(hour)) - plt.plot(hour_list, plot_data, linewidth=1, marker='o') + self._hour(plot_data, date_month_list, hour_list) plt.xticks(rotation=90, fontsize=6) @@ -532,7 +557,41 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): plt.gcf().clear() return image_base64 + def _day(self, plot_data, date_month_list, date_list): + if len(plot_data) == 0: + plt.xlabel("Dates", fontsize=8) + plt.plot() + else: + plt.title("API calls per day", fontsize=14) + plt.xlabel("Dates", fontsize=8) + for date in date_month_list: + date = date.strftime('%B %d') + date_list.append(str(date)) + plt.plot(date_list, plot_data, linewidth=1, marker='o') + def _month(self, plot_data, date_month_list, month_list): + if len(plot_data) == 0: + plt.xlabel("Months", fontsize=8) + plt.plot() + else: + plt.title("API calls per month", fontsize=14) + plt.xlabel("Months", fontsize=8) + for date in date_month_list: + month = date.strftime('%B %Y') + month_list.append(str(month)) + plt.plot(month_list, plot_data, linewidth=1, marker='o') + + def _hour(self, plot_data, date_month_list, hour_list): + if len(plot_data) == 0: + plt.xlabel("Hours", fontsize=8) + plt.plot() + else: + plt.title("API calls per hour", fontsize=14) + plt.xlabel("Hours", fontsize=8) + for date in date_month_list: + hour = date.strftime('%B %d -- %H : %m') + hour_list.append(str(hour)) + plt.plot(hour_list, plot_data, linewidth=1, marker='o') def plot_bar_chart(self, data): x = [] @@ -592,60 +651,59 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): error_once_only(self.request, users['message']) if 'users' not in users: users['users']=[] + else: + self._update_user_with_cansearchwarehouse(users, users_with_cansearchwarehouse, email_with_cansearchwarehouse) + # fail gracefully in case API provides new structure except APIError as err: error_once_only(self.request, err) + except KeyError as err: + messages.error(self.request, 'KeyError: {}'.format(err)) except Exception as err: - error_once_only(self.request, 'Unknown Error. {}'.format(err)) - - else: - try: - for user in users['users']: - for entitlement in user['entitlements']['list']: - if 'CanSearchWarehouse' in entitlement['role_name']: - users_with_cansearchwarehouse.append(user["username"]) - email_with_cansearchwarehouse.append(user["email"]) - # fail gracefully in case API provides new structure - except KeyError as err: - messages.error(self.request, 'KeyError: {}'.format(err)) - except Exception as err: - error_once_only(self.request, 'Unknown Error. {}'.format(err)) + if DEBUG: + raise(err) + error_once_only(self.request, err) user_email_cansearchwarehouse = dict(zip(users_with_cansearchwarehouse, email_with_cansearchwarehouse)) number_of_users_with_cansearchwarehouse = len(user_email_cansearchwarehouse) return user_email_cansearchwarehouse, number_of_users_with_cansearchwarehouse + def _update_user_with_cansearchwarehouse(self, users, users_with_cansearchwarehouse, email_with_cansearchwarehouse): + for user in users['users']: + for entitlement in user['entitlements']['list']: + if 'CanSearchWarehouse' in entitlement['role_name']: + users_with_cansearchwarehouse.append(user["username"]) + email_with_cansearchwarehouse.append(user["email"]) + + def _api_data(self, urlpath, data_key): + api = API(self.request.session.get('obp')) + data = [] + try: + data = api.get(urlpath) + if data is not None and 'code' in data and data['code']==403: + error_once_only(self.request, data['message']) + data=[] + else: + data = data[data_key] + except APIError as err: + if DEBUG: + raise(err) + error_once_only(self.request, err) + except Exception as err: + if DEBUG: + raise(err) + error_once_only(self.request, err) + return data + def get_top_apis(self, cleaned_data, from_date, to_date): top_apis = [] - form = self.get_form() - if cleaned_data.get('include_obp_apps'): - urlpath = '/management/metrics/top-apis?from_date={}&to_date={}'.format(from_date, to_date) - api = API(self.request.session.get('obp')) - try: - top_apis = api.get(urlpath) - if top_apis is not None and 'code' in top_apis and top_apis['code']==403: - error_once_only(self.request, top_apis['message']) - top_apis=[] - else: - top_apis = top_apis['top_apis'] - except APIError as err: - error_once_only(self.request, err) - except Exception as err: - error_once_only(self.request, 'Unknown Error. {}'.format(err)) - else: - urlpath = '/management/metrics/top-apis?from_date={}&to_date={}&exclude_app_names={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format( - from_date, to_date, ",".join(local_settings.EXCLUDE_APPS), ",".join(EXCLUDE_FUNCTIONS), ",".join(EXCLUDE_URL_PATTERN)) - api = API(self.request.session.get('obp')) - try: - top_apis = api.get(urlpath) - if top_apis is not None and 'code' in top_apis and top_apis['code']==403: - error_once_only(self.request, top_apis['message']) - top_apis=[] - else: - top_apis = top_apis['top_apis'] - except APIError as err: - error_once_only(self.request, err) - except Exception as err: - error_once_only(self.request, 'Unknown Error. {}'.format(err)) + #if cleaned_data.get('include_obp_apps'): + # urlpath = '/management/metrics/top-apis?from_date={}&to_date={}'.format(from_date, to_date) + #else: + # urlpath = '/management/metrics/top-apis?from_date={}&to_date={}&exclude_app_names={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format( + # from_date, to_date, ",".join(local_settings.EXCLUDE_APPS), ",".join(EXCLUDE_FUNCTIONS), ",".join(EXCLUDE_URL_PATTERN)) + urlpath = '/management/metrics/top-apis?from_date={}&to_date={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format( + from_date, to_date, ",".join(EXCLUDE_FUNCTIONS), ",".join(EXCLUDE_URL_PATTERN)) + top_apis = self._api_data(urlpath, 'top_apis') for api in top_apis: if api['Implemented_by_partial_function'] == "": @@ -654,44 +712,20 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): for api in top_apis: api['Implemented_by_partial_function'] = api['Implemented_by_partial_function'] + '(' + api['implemented_in_version'] + ')' top_apis = top_apis[:10] - # for api in top_apis: - # #print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% TOP APIS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") - # print(str(top_apis.index(api) + 1) + "," + api['Implemented_by_partial_function'] + "," + str(api['count'])) top_apis = reversed(top_apis) return top_apis def get_top_consumers(self, cleaned_data, from_date, to_date): top_consumers = [] - form = self.get_form() - if cleaned_data.get('include_obp_apps'): - urlpath = '/management/metrics/top-consumers?from_date={}&to_date={}'.format(from_date, to_date) - api = API(self.request.session.get('obp')) - try: - top_consumers = api.get(urlpath) - if top_consumers is not None and 'code' in top_consumers and top_consumers['code']==403: - error_once_only(self.request, top_consumers['message']) - top_consumers=[] - else: - top_consumers = top_consumers['top_consumers'] - except APIError as err: - error_once_only(self.request, err) - except Exception as err: - error_once_only(self.request, 'Unknown Error. {}'.format(err)) - else: - urlpath = '/management/metrics/top-consumers?from_date={}&to_date={}&exclude_app_names={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format( - from_date, to_date, ",".join(local_settings.EXCLUDE_APPS), ",".join(EXCLUDE_FUNCTIONS), ",".join(EXCLUDE_URL_PATTERN)) - api = API(self.request.session.get('obp')) - try: - top_consumers = api.get(urlpath) - if top_consumers is not None and 'code' in top_consumers and top_consumers['code']==403: - error_once_only(self.request, top_consumers['message']) - top_consumers=[] - else: - top_consumers = top_consumers['top_consumers'] - except APIError as err: - error_once_only(self.request, err) - except Exception as err: - error_once_only(self.request, 'Unknown Error. {}'.format(err)) + #if cleaned_data.get('include_obp_apps'): + # urlpath = '/management/metrics/top-consumers?from_date={}&to_date={}'.format(from_date, to_date) + #else: + # urlpath = '/management/metrics/top-consumers?from_date={}&to_date={}&exclude_app_names={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format( + # from_date, to_date, ",".join(local_settings.EXCLUDE_APPS), ",".join(EXCLUDE_FUNCTIONS), ",".join(EXCLUDE_URL_PATTERN)) + urlpath = '/management/metrics/top-consumers?from_date={}&to_date={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format( + from_date, to_date, ",".join(EXCLUDE_FUNCTIONS), ",".join(EXCLUDE_URL_PATTERN)) + top_consumers = self._api_data(urlpath, 'top_consumers') + for consumer in top_consumers: if consumer['app_name'] == "": top_consumers.remove(consumer) @@ -709,17 +743,20 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): if "elasticSearchWarehouse" in api['Implemented_by_partial_function']: top_warehouse_calls.append(api) except APIError as err: + if DEBUG: + raise(err) error_once_only(self.request, err) except Exception as err: - error_once_only(self.request, 'Unknown Error. {}'.format(err)) + if DEBUG: + raise(err) + error_once_only(self.request, err) return top_warehouse_calls - def get_top_apps_using_warehouse(self, from_date, to_date, exclude_app_names): - form = self.get_form() + def get_top_apps_using_warehouse(self, from_date, to_date): top_apps_using_warehouse = [] - urlpath = '/management/metrics/top-consumers?from_date={}&to_date={}&exclude_app_names={}&implemented_by_partial_function={}'.format( - from_date, to_date, exclude_app_names, "elasticSearchWarehouse") + urlpath = '/management/metrics/top-consumers?from_date={}&to_date={}&implemented_by_partial_function={}'.format( + from_date, to_date, "elasticSearchWarehouse") api = API(self.request.session.get('obp')) try: top_apps_using_warehouse = api.get(urlpath) @@ -729,45 +766,49 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): else: top_apps_using_warehouse = top_apps_using_warehouse["top_consumers"][:2] except APIError as err: + if DEBUG: + raise(err) error_once_only(self.request, err) except Exception as err: - error_once_only(self.request, 'Unknown Error. {}'.format(err)) + if DEBUG: + raise(err) + error_once_only(self.request, err) return top_apps_using_warehouse def median_time_to_first_api_call(self, from_date, to_date): return 0 #TODO this cost too much time, do not use this at the moment. form = self.get_form() + form = self.get_form() new_apps_list = [] apps = [] apps_list = self.get_all_consumers() - for app in apps_list: created_date = datetime.datetime.strptime(app['created'], '%Y-%m-%dT%H:%M:%SZ') - created_date = created_date.strftime(API_DATEFORMAT) - created_date = datetime.datetime.strptime(created_date, API_DATEFORMAT) - if created_date >= datetime.datetime.strptime(from_date, API_DATEFORMAT): + created_date = created_date.strftime(API_DATE_FORMAT) + created_date = datetime.datetime.strptime(created_date, API_DATE_FORMAT) + if created_date >= datetime.datetime.strptime(from_date, API_DATE_FORMAT): new_apps_list.append(app) times_to_first_call = [] - strfrom_date=datetime.datetime.strptime(from_date, API_DATEFORMAT) - strto_date=datetime.datetime.strptime(to_date, API_DATEFORMAT) + strfrom_date=datetime.datetime.strptime(from_date, API_DATE_FORMAT) + strto_date=datetime.datetime.strptime(to_date, API_DATE_FORMAT) for app in new_apps_list: urlpath_metrics = '/management/metrics?from_date={}&to_date={}&consumer_id={}&sort_by={}&direction={}&limit={}'.format( from_date, to_date, app['consumer_id'], 'date', 'asc', '1') cache_key = get_cache_key_for_current_call(self.request, urlpath_metrics) api = API(self.request.session.get('obp')) try: - apicaches=None + api_cache=None try: - apicaches=cache.get(cache_key) + api_cache=cache.get(cache_key) except Exception as err: - apicaches=None + api_cache=None metrics=[] - if not apicaches is None: - metrics=apicaches + if not api_cache is None: + metrics=api_cache else: metrics = api.get(urlpath_metrics) @@ -787,8 +828,12 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): except APIError as err: + if DEBUG: + raise(err) error_once_only(self.request, err) except Exception as err: + if DEBUG: + raise(err) error_once_only(self.request, 'Unknown Error. {}'.format(err)) if times_to_first_call: @@ -803,15 +848,15 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): def prepare_general_context(self, web_page_type, **kwargs): try: - form = self.get_form(web_page_type) + form = self.get_form() per_day_chart=[] calls_per_month_list=[] per_month_chart=[] calls_per_hour_list=[] per_hour_chart=[] if form.is_valid(): - is_included_obp_apps = form.cleaned_data.get('include_obp_apps') - exclude_app_names = form.cleaned_data.get("exclude_app_names") + # = form.cleaned_data.get('include_obp_apps') + include_app_names = form.cleaned_data.get("include_app_names") #if exclude_app_names not in local_settings.EXCLUDE_APPS: # error_once_only(self.request, "Invalid Exclude App Name, Please select" + str(local_settings.EXCLUDE_APPS) + "Anyone of these") form_to_date_string = form.data['to_date'] @@ -820,41 +865,46 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): if (web_page_type == SummaryType.DAILY): # for one day, the from_date is 1 day ago. from_date = return_to_days_ago(to_date, 1) - calls_per_hour_list, calls_per_hour, hour_list = self.calls_per_hour(is_included_obp_apps, from_date, to_date, exclude_app_names) + calls_per_hour_list, calls_per_hour, hour_list = self.calls_per_hour(from_date, to_date, include_app_names) per_hour_chart = self.plot_line_chart(calls_per_hour, hour_list, 'hour') if (web_page_type == SummaryType.WEEKLY): # for one month, the from_date is 7 days ago. from_date = return_to_days_ago(to_date, 7) - calls_per_day_list, calls_per_day, date_list = self.calls_per_day(is_included_obp_apps, from_date, to_date, exclude_app_names) + calls_per_day_list, calls_per_day, date_list = self.calls_per_day(from_date, to_date, include_app_names) per_day_chart = self.plot_line_chart(calls_per_day, date_list, "day") if (web_page_type == SummaryType.MONTHLY): # for one month, the from_date is 30 days ago. from_date = return_to_days_ago(to_date, 30) - calls_per_day_list, calls_per_day, date_list = self.calls_per_day(is_included_obp_apps, from_date, to_date, exclude_app_names) + calls_per_day_list, calls_per_day, date_list = self.calls_per_day(from_date, to_date, include_app_names) per_day_chart = self.plot_line_chart(calls_per_day, date_list, "day") if (web_page_type == SummaryType.QUARTERLY): # for one quarter, the from_date is 90 days ago. - from_date = (datetime.datetime.strptime(to_date, API_DATEFORMAT) - timedelta(90)).strftime(API_DATEFORMAT) - calls_per_month_list, calls_per_month, month_list = self.calls_per_month(is_included_obp_apps, from_date, to_date, exclude_app_names) + from_date = (datetime.datetime.strptime(to_date, API_DATE_FORMAT) - timedelta(90)).strftime(API_DATE_FORMAT) + calls_per_month_list, calls_per_month, month_list = self.calls_per_month(from_date, to_date, include_app_names) per_month_chart = self.plot_line_chart(calls_per_month, month_list, 'month') if (web_page_type == SummaryType.YEARLY): from_date = return_to_days_ago(to_date, 365) - calls_per_month_list, calls_per_month, month_list = self.calls_per_month(is_included_obp_apps, from_date, to_date, exclude_app_names) + #calls_per_month_list, calls_per_month, month_list = self.calls_per_month(, from_date, to_date) + calls_per_month_list, calls_per_month, month_list = self.calls_per_month(from_date, to_date, include_app_names) per_month_chart = self.plot_line_chart(calls_per_month, month_list, "month") if (web_page_type == SummaryType.CUSTOM): # for one month, the from_date is x day ago. form_from_date_string = form.data['from_date_custom'] from_date = convert_form_date_to_obpapi_datetime_format(form_from_date_string) - calls_per_day_list, calls_per_day, date_list = self.calls_per_day(is_included_obp_apps, from_date, to_date, exclude_app_names) - per_day_chart = self.plot_line_chart(calls_per_day, date_list, "day") + #calls_per_day_list, calls_per_day, date_list = self.calls_per_day(, from_date, to_date) + calls_per_day_list, calls_per_day, date_list = self.calls_per_day(from_date, to_date,include_app_names) + if (len(calls_per_day) <= 31): + per_day_chart = self.plot_line_chart(calls_per_day, date_list, "day") + else: + per_day_chart = self.plot_line_chart(calls_per_day, date_list, "month") api_host_name = API_HOST - top_apps_using_warehouse = self.get_top_apps_using_warehouse(from_date, to_date, exclude_app_names) + top_apps_using_warehouse = self.get_top_apps_using_warehouse(from_date, to_date) user_email_cansearchwarehouse, number_of_users_with_cansearchwarehouse = self.get_users_cansearchwarehouse() median_time_to_first_api_call = self.median_time_to_first_api_call(from_date, to_date) @@ -863,19 +913,16 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): top_consumers = self.get_top_consumers(form.cleaned_data, from_date, to_date) top_consumers_bar_chart = self.plot_topconsumer_bar_chart(top_consumers) top_warehouse_calls = self.get_top_warehouse_calls(form.cleaned_data, from_date, to_date) - api_calls, average_response_time, average_calls_per_day = self.get_aggregate_metrics(from_date, to_date,is_included_obp_apps) - calls_by_api_explorer, average_response_time_api_explorer, average_calls_per_day_api_explorer = self.get_aggregate_metrics_api_explorer( - from_date, to_date) - + api_calls, average_response_time, average_calls_per_day = self.get_aggregate_metrics(from_date, to_date, include_app_names) unique_app_names, number_of_apps_with_unique_app_name, number_of_apps_with_unique_developer_email = self.get_total_number_of_apps( form.cleaned_data, from_date, to_date) - active_apps_list = self.get_active_apps(is_included_obp_apps, from_date, to_date, exclude_app_names) + active_apps_list = self.get_active_apps(from_date, to_date) context = super(MonthlyMetricsSummaryView, self).get_context_data(**kwargs) context.update({ 'form': form, 'api_calls': api_calls, - 'calls_by_api_explorer': calls_by_api_explorer, + 'include_app_names': include_app_names, 'calls_per_month_list': calls_per_month_list, 'per_month_chart': per_month_chart, 'per_day_chart': per_day_chart, @@ -891,19 +938,65 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView): 'user_email_cansearchwarehouse': user_email_cansearchwarehouse, 'number_of_users_with_cansearchwarehouse': number_of_users_with_cansearchwarehouse, 'api_host_name': api_host_name, - 'from_date': (datetime.datetime.strptime(from_date, API_DATEFORMAT)).strftime('%Y-%m-%d'), - 'to_date': (datetime.datetime.strptime(to_date, API_DATEFORMAT)).strftime('%Y-%m-%d'), + 'from_date': (datetime.datetime.strptime(from_date, API_DATE_FORMAT)).strftime('%d %B %Y'), + 'to_date': (datetime.datetime.strptime(to_date, API_DATE_FORMAT)).strftime('%d %B %Y'), 'top_apis': top_apis, 'top_apis_bar_chart': top_apis_bar_chart, 'top_consumers_bar_chart': top_consumers_bar_chart, 'median_time_to_first_api_call': median_time_to_first_api_call, - 'excluded_apps':[exclude_app_names if exclude_app_names in local_settings.EXCLUDE_APPS else "null"], + #'excluded_apps':[exclude_app_names if exclude_app_names in local_settings.EXCLUDE_APPS else "null"], }) return context else: error_once_only(self.request, str(form.errors)) except Exception as err: - error_once_only(self.request, 'Unknown Error. {}'.format(err)) + if DEBUG: + raise(err) + error_once_only(self.request, err) + def _daily_and_weekly(self, web_page_type,to_date, per_hour_chart, per_day_chart, from_date): + if (web_page_type == SummaryType.DAILY): + # for one day, the from_date is 1 day ago. + from_date = return_to_days_ago(to_date, 1) + calls_per_hour_list, calls_per_hour, hour_list = self.calls_per_hour(from_date, to_date) + per_hour_chart = self.plot_line_chart(calls_per_hour, hour_list, 'hour') + + if (web_page_type == SummaryType.WEEKLY): + # for one month, the from_date is 7 days ago. + from_date = return_to_days_ago(to_date, 7) + calls_per_day_list, calls_per_day, date_list = self.calls_per_day(from_date, to_date) + per_day_chart = self.plot_line_chart(calls_per_day, date_list, "day") + + return (from_date, per_hour_chart, per_day_chart) + + def _monthly_and_quarterly(self, web_page_type,to_date, per_day_chart, per_month_chart, from_date): + if (web_page_type == SummaryType.MONTHLY): + # for one month, the from_date is 30 days ago. + from_date = return_to_days_ago(to_date, 30) + calls_per_day_list, calls_per_day, date_list = self.calls_per_day(from_date, to_date) + per_day_chart = self.plot_line_chart(calls_per_day, date_list, "day") + + if (web_page_type == SummaryType.QUARTERLY): + # for one quarter, the from_date is 90 days ago. + from_date = (datetime.datetime.strptime(to_date, API_DATE_FORMAT) - timedelta(90)).strftime(API_DATE_FORMAT) + calls_per_month_list, calls_per_month, month_list = self.calls_per_month(from_date, to_date, include_app_names) + per_month_chart = self.plot_line_chart(calls_per_month, month_list, 'month') + + return (from_date, per_day_chart, per_month_chart) + + def _yearly_and_custom(self, web_page_type,to_date, per_month_chart, per_day_chart, from_date): + if (web_page_type == SummaryType.YEARLY): + from_date = return_to_days_ago(to_date, 365) + calls_per_month_list, calls_per_month, month_list = self.calls_per_month(from_date, to_date, include_app_names) + per_month_chart = self.plot_line_chart(calls_per_month, month_list, "month") + + if (web_page_type == SummaryType.CUSTOM): + # for one month, the from_date is x day ago. + form_from_date_string = form.data['from_date_custom'] + from_date = convert_form_date_to_obpapi_datetime_format(form_from_date_string) + calls_per_day_list, calls_per_day, date_list = self.calls_per_day(from_date, to_date) + per_day_chart = self.plot_line_chart(calls_per_day, date_list, "day") + + return (from_date, per_month_chart, per_day_chart) class YearlySummaryView(MonthlyMetricsSummaryView): template_name = 'metrics/yearly_summary.html' @@ -928,4 +1021,4 @@ class HourlySummaryView(MonthlyMetricsSummaryView): class CustomSummaryView(MonthlyMetricsSummaryView): form_class = CustomSummaryForm template_name = 'metrics/custom_summary.html' - def get_context_data(self, **kwargs): return self.prepare_general_context(SummaryType.CUSTOM, **kwargs) + def get_context_data(self, **kwargs): return self.prepare_general_context(SummaryType.CUSTOM, **kwargs) \ No newline at end of file diff --git a/apimanager/obp/api.py b/apimanager/obp/api.py index dbb363a..87c1e9a 100644 --- a/apimanager/obp/api.py +++ b/apimanager/obp/api.py @@ -107,18 +107,6 @@ class API(object): response = self.call('PUT', url, payload) return self.handle_response(response) - # def handle_response_404(self, response, prefix): - # msg = '{} {}: {}'.format( - # prefix, response.status_code, response.text) - # log(logging.ERROR, msg) - # raise APIError(msg) - # - # def handle_response_500(self, response, prefix): - # msg = '{} {}: {}'.format( - # prefix, response.status_code, response.text) - # log(logging.ERROR, msg) - # raise APIError(msg) - def handle_response_error(self, prefix, error): if 'Invalid or expired access token' in error: raise APIError(error) diff --git a/apimanager/obp/directlogin.py b/apimanager/obp/directlogin.py index ed71356..4625523 100644 --- a/apimanager/obp/directlogin.py +++ b/apimanager/obp/directlogin.py @@ -49,7 +49,7 @@ class DirectLoginAuthenticator(Authenticator): raise AuthenticatorError(Exception("The OBP-API server is not running or does not respond properly." "Please check OBP-API server. " "Details: "+str(err))) - except BaseException as err: + except Exception as err: raise AuthenticatorError(Exception("Unknown Error. Details:"+ str(err))) # This is the direct-Login Token: diff --git a/apimanager/obp/gatewaylogin.py b/apimanager/obp/gatewaylogin.py index 8315400..fb05b3c 100644 --- a/apimanager/obp/gatewaylogin.py +++ b/apimanager/obp/gatewaylogin.py @@ -56,7 +56,7 @@ class GatewayLoginAuthenticator(Authenticator): raise AuthenticatorError(Exception("The OBP-API server is not running or does not respond properly." "Please check OBP-API server. " "Details: " + str(err))) - except BaseException as err: + except Exception as err: raise AuthenticatorError(Exception("Unknown Error. Details:" + str(err))) # this will show the obp errors if response.status_code != 200: diff --git a/apimanager/obp/views.py b/apimanager/obp/views.py index 4e7fa73..8130bce 100644 --- a/apimanager/obp/views.py +++ b/apimanager/obp/views.py @@ -16,6 +16,7 @@ from .api import API, APIError from .authenticator import AuthenticatorError from .forms import DirectLoginForm, GatewayLoginForm from .oauth import OAuthAuthenticator +from django.conf import settings class LoginToDjangoMixin(object): @@ -31,8 +32,8 @@ class LoginToDjangoMixin(object): data = api.get('/users/current') except APIError as err: messages.error(self.request, err) - except: - messages.error(self.request, 'Unknown Error') + except Exception as err: + messages.error(self.request, err) return False else: userid = data['user_id'] or data['email'] @@ -53,8 +54,11 @@ class OAuthInitiateView(RedirectView): Gets the callback URI to where the user shall be returned after initiation at OAuth server """ - base_url = '{}://{}'.format( - request.scheme, request.environ['HTTP_HOST']) + if settings.CALLBACK_BASE_URL: + base_url = settings.CALLBACK_BASE_URL + else: + base_url = '{}://{}'.format( + request.scheme, request.environ['HTTP_HOST']) uri = base_url + reverse('oauth-authorize') if 'next' in request.GET: uri = '{}?next={}'.format(uri, request.GET['next']) @@ -69,8 +73,8 @@ class OAuthInitiateView(RedirectView): except AuthenticatorError as err: messages.error(self.request, err) return reverse('home') - except: - messages.error(self.request, 'Unknown Error') + except Exception as err: + messages.error(self.request, err) return reverse('home') else: self.request.session['obp'] = { @@ -95,8 +99,8 @@ class OAuthAuthorizeView(RedirectView, LoginToDjangoMixin): authenticator.set_access_token(authorization_url) except AuthenticatorError as err: messages.error(self.request, err) - except: - messages.error(self.request, 'Unknown Error') + except Exception as err: + messages.error(self.request, err) else: session_data['authenticator_kwargs'] = { 'token': authenticator.token, diff --git a/apimanager/products/urls.py b/apimanager/products/urls.py index a8d9614..84e4e9b 100644 --- a/apimanager/products/urls.py +++ b/apimanager/products/urls.py @@ -5,7 +5,7 @@ URLs for metrics app from django.conf.urls import url -from .views import IndexProductView, UpdateProductView, createList +from .views import IndexProductView, UpdateProductView, create_list urlpatterns = [ url(r'^create', @@ -15,6 +15,6 @@ urlpatterns = [ UpdateProductView.as_view(), name='products_update'), url(r'^createProductList', - createList, + create_list, name = 'create-product-list'), ] diff --git a/apimanager/products/views.py b/apimanager/products/views.py index 5f46215..2119252 100644 --- a/apimanager/products/views.py +++ b/apimanager/products/views.py @@ -36,8 +36,8 @@ class IndexProductView(LoginRequiredMixin, FormView): fields['bank_id'].choices = self.api.get_bank_id_choices() except APIError as err: messages.error(self.request, err) - except: - messages.error(self.request, "Unknown Error") + except Exception as err: + messages.error(self.request, err) return form def form_valid(self, form): @@ -91,8 +91,8 @@ class UpdateProductView(LoginRequiredMixin, FormView): fields['bank_id'].choices = self.api.get_bank_id_choices() except APIError as err: messages.error(self.request, err) - except: - messages.error(self.request, "Unknown Error") + except Exception as err: + messages.error(self.request, err) try: result = self.api.get(urlpath) fields['parent_product_code'].initial = self.kwargs['parent_product_code'] @@ -155,7 +155,7 @@ class UpdateProductView(LoginRequiredMixin, FormView): @exception_handle @csrf_exempt -def createList(request): +def create_list(request): print(request.POST, "createProductList listt") return HttpResponse("

    View 1

    ") diff --git a/apimanager/systemviews/templates/systemviews/index.html b/apimanager/systemviews/templates/systemviews/index.html index 079c219..ea97f4f 100644 --- a/apimanager/systemviews/templates/systemviews/index.html +++ b/apimanager/systemviews/templates/systemviews/index.html @@ -1,7 +1,7 @@ {% extends 'base.html' %} {% load static %} {% load i18n %} {% block page_title %} {{ block.super }} / {% trans "System View" %}{% endblock page_title %} {% block content %}
    -

    {% trans "System View" %}

    +

    {% trans "System Views" %}

    diff --git a/apimanager/users/views.py b/apimanager/users/views.py index c445624..da04aa4 100644 --- a/apimanager/users/views.py +++ b/apimanager/users/views.py @@ -100,14 +100,15 @@ class IndexView(LoginRequiredMixin, TemplateView): users = response except APIError as err: messages.error(self.request, err) - except: - messages.error(self.request, 'Unknown Error') + except Exception as err: + messages.error(self.request, err) role_names = self.get_users_rolenames(context) try: users = FilterRoleName(context, self.request.GET) \ .apply([users] if username else users['users']) - except: + except Exception as err: + messages.error(self.request, err) users = [] context.update({ 'role_names': role_names, @@ -137,8 +138,8 @@ class DetailView(LoginRequiredMixin, FormView): form.fields['bank_id'].choices = self.api.get_bank_id_choices() except APIError as err: messages.error(self.request, err) - except: - messages.error(self.request, 'Unknown Error') + except Exception as err: + messages.error(self.request, err) return form def form_valid(self, form): @@ -154,8 +155,8 @@ class DetailView(LoginRequiredMixin, FormView): except APIError as err: messages.error(self.request, err) return super(DetailView, self).form_invalid(form) - except: - messages.error(self.request, 'Unknown Error') + except Exception as err: + messages.error(self.request, err) return super(DetailView, self).form_invalid(form) if 'code' in entitlement and entitlement['code']>=400: messages.error(self.request, entitlement['message']) @@ -181,8 +182,8 @@ class DetailView(LoginRequiredMixin, FormView): context['form'].fields['user_id'].initial = user['user_id'] except APIError as err: messages.error(self.request, err) - except: - messages.error(self.request, 'Unknown Error') + except Exception as err: + messages.error(self.request, err) context.update({ 'apiuser': user, # 'user' is logged-in user in template context @@ -205,8 +206,8 @@ class MyDetailView(LoginRequiredMixin, FormView): form.fields['bank_id'].choices = self.api.get_bank_id_choices() except APIError as err: messages.error(self.request, err) - except: - messages.error(self.request, 'Unknown Error') + except Exception as err: + messages.error(self.request, err) return form def form_valid(self, form): @@ -229,7 +230,7 @@ class MyDetailView(LoginRequiredMixin, FormView): messages.error(self.request, err) return super(MyDetailView, self).form_invalid(form) except Exception as err: - messages.error(self.request, 'Unknown Error. {}'.format(err)) + messages.error(self.request, err) return super(MyDetailView, self).form_invalid(form) else: return super(MyDetailView, self).form_valid(form) @@ -246,10 +247,7 @@ class MyDetailView(LoginRequiredMixin, FormView): except APIError as err: messages.error(self.request, err) except Exception as err: - messages.error(self.request, 'Unknown Error') - #print(user,"This is ") - #entitlements=user["entitlements"]["list"] - user["entitlements"]["list"] = sorted(user["entitlements"]["list"], key=lambda d: d['role_name']) + messages.error(self.request, err) context.update({ 'apiuser': user, # 'user' is logged-in user in template context }) @@ -274,8 +272,8 @@ class InvitationView(LoginRequiredMixin, FormView): fields['bank_id'].choices = self.api.get_bank_id_choices() except APIError as err: messages.error(self.request, err) - except: - messages.error(self.request, "Unknown Error") + except Exception as err: + messages.error(self.request, err) return form def form_valid(self, form, **kwargs): @@ -306,7 +304,7 @@ class InvitationView(LoginRequiredMixin, FormView): messages.error(self.request, err) return super(InvitationView, self).form_invalid(form) except Exception as err: - messages.error(self.request, "Unknown Error:{}".format(str(err))) + messages.error(self.request, err) return super(InvitationView, self).form_invalid(form) def get_invitations(self, context, get_url_path, invitations): @@ -338,10 +336,10 @@ class DeleteEntitlementView(LoginRequiredMixin, View): messages.success(request, msg) except APIError as err: messages.error(request, err) - except: - messages.error(self.request, 'Unknown Error') + except Exception as err: + messages.error(self.request, err) - # from sonarcloud: Change this code to not perform redirects based on user-controlled data. + # from sonarcloud: Change this code to not perform redirects based on user-controlled data. redirect_url_from_gui = request.POST.get('next', reverse('users-index')) if "/users/all/user_id/" in str(redirect_url_from_gui): redirect_url = reverse('users-detail',kwargs={"user_id":kwargs['user_id']}) @@ -349,7 +347,6 @@ class DeleteEntitlementView(LoginRequiredMixin, View): redirect_url = reverse('my-user-detail',kwargs={"user_id":kwargs['user_id']}) else: redirect_url = reverse('users-index') - return HttpResponseRedirect(redirect_url) @@ -379,7 +376,6 @@ class UserStatusUpdateView(LoginRequiredMixin, View): else: urlpath = '/users/{}/lock-status'.format(kwargs['username']) result = api.put(urlpath, None) - print("result", result) #if result is not None and 'code' in result and result['code'] >= 400: if 'code' in result and result['code'] == 404: msg = 'User {} has been unlocked.'.format(kwargs['username']) @@ -392,8 +388,8 @@ class UserStatusUpdateView(LoginRequiredMixin, View): except APIError as err: messages.error(request, err) - except Exception as e: - messages.error(self.request, 'Unknown Error' + str(e)) + except Exception as err: + messages.error(self.request, err) # from sonarcloud: Change this code to not perform redirects based on user-controlled data. redirect_url_from_gui = request.POST.get('next', reverse('users-index')) @@ -433,8 +429,8 @@ class ExportCsvView(LoginRequiredMixin, View): except APIError as err: messages.error(self.request, err) - except: - messages.error(self.request, 'Unknown Error') + except Exception as err: + messages.error(self.request, err) response = HttpResponse(content_type = 'text/csv') response['Content-Disposition'] = 'attachment;filename= Users'+ str(datetime.datetime.now())+'.csv' writer = csv.writer(response) @@ -443,4 +439,3 @@ class ExportCsvView(LoginRequiredMixin, View): writer.writerow([user['username'], user['user_id'], user['email'], user['provider_id'], user['provider'], user['last_marketing_agreement_signed_date']]) return response - diff --git a/apimanager/webui/static/webui/js/webui.js b/apimanager/webui/static/webui/js/webui.js index 551ac2b..82b7c1e 100644 --- a/apimanager/webui/static/webui/js/webui.js +++ b/apimanager/webui/static/webui/js/webui.js @@ -1,10 +1,10 @@ $(document).ready(function($) { $('.runner button.forSave').click(function(e) { e.preventDefault(); - var t = $(this); - var runner = t.parent().parent().parent(); - var web_ui_props_name = $(runner).find('.web_ui_props_name').text(); - var web_ui_props_value = $(runner).find('.web_ui_props_value').val(); + const t = $(this); + const runner = t.parent().parent().parent(); + const web_ui_props_name = $(runner).find('.web_ui_props_name').text(); + const web_ui_props_value = $(runner).find('.web_ui_props_value').val(); $('.runner button.forSave').attr("disabled", "disabled"); $('.runner button.forDelete').attr("disabled", "disabled"); $.post('save/method', { @@ -17,13 +17,10 @@ $(document).ready(function($) { $('.runner button.forDelete').click(function(e) { e.preventDefault(); - var t = $(this); - var runner = t.parent().parent().parent(); - var web_ui_props_name = $(runner).find('.web_ui_props_name').text(); - var textArea = runner.find('.web_ui_props_value'); - var props_id = $(runner).find('.web_ui_props_id'); - var web_ui_props_id = props_id.val(); - var webui = $('#webui'); + const t = $(this); + const runner = t.parent().parent().parent(); + const props_id = $(runner).find('.web_ui_props_id'); + const web_ui_props_id = props_id.val(); $('.runner button.forSave').attr("disabled", "disabled"); $('.runner button.forDelete').attr("disabled", "disabled"); $.post('delete/method', { @@ -32,4 +29,4 @@ $(document).ready(function($) { location.reload(); }); }); -}); \ No newline at end of file +}); diff --git a/apimanager/webui/views.py b/apimanager/webui/views.py index ec3a894..b8c597e 100644 --- a/apimanager/webui/views.py +++ b/apimanager/webui/views.py @@ -38,8 +38,8 @@ class IndexView(LoginRequiredMixin, FormView): context.update(response) except APIError as err: messages.error(self.request, err) - except BaseException as err: - messages.error(self.request, (Exception("Unknown Error. Details:" + str(err)))) + except Exception as err: + messages.error(self.request, err) return context def get_form(self, *args, **kwargs): @@ -65,7 +65,6 @@ def webui_save(request): @csrf_exempt def webui_delete(request): web_ui_props_id = request.POST.get('web_ui_props_id') - web_ui_props_name = request.POST.get('web_ui_props_name') if web_ui_props_id == 'default' or web_ui_props_id == '' or web_ui_props_id is None: return {'code':403,'message':'Cann\'t delete web_ui_props_id default'} else: diff --git a/requirements.txt b/requirements.txt index 3c787ae..bde0e22 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,8 @@ #Django==1.11.7 -Django==2.0.7 -oauthlib==2.0.0 -requests==2.11.1 -requests-oauthlib==0.6.2 +Django==2.2.13 +oauthlib==3.2.0 +requests==2.27.1 +requests-oauthlib==1.3.1 PyJWT==1.5.3 gunicorn==19.6.0 matplotlib