feature/add consents app with views, URLs, and templates

This commit is contained in:
Hongwei 2025-05-21 09:33:22 +02:00
parent 9e0bd20032
commit 73761a5160
11 changed files with 172 additions and 6 deletions

View File

@ -71,7 +71,8 @@ INSTALLED_APPS = [
'connectormethod',
'dynamicendpoints',
'apicollections',
'apicollectionlist'
'apicollectionlist',
'consents',
]
MIDDLEWARE = [

View File

@ -38,6 +38,7 @@ urlpatterns += i18n_patterns(
re_path(r'^account/list', include('accountlist.urls')),
re_path(r'^consumers/', include('consumers.urls')),
re_path(r'^entitlementrequests/', include('entitlementrequests.urls')),
re_path(r'^consents', include('consents.urls')),
re_path(r'^users/', include('users.urls')),
re_path(r'^branches/', include('branches.urls')),
re_path(r'^atms/', include('atms.urls')),

View File

@ -37,6 +37,8 @@
<li {% if consumers_index_url in request.path %} class="active" {% endif %}><a href="{{ consumers_index_url }}">{% trans "Consumers" %}</a></li>
{% url "entitlementrequests-index" as entitlementrequests_index_url %}
<li {% if entitlementrequests_index_url in request.path %} class="active" {% endif %}><a href="{{ entitlementrequests_index_url }}">{% trans "Entitlement Requests" %}</a></li>
{% url "consents-index" as consents_index_url %} {% url 'my-consent-detail' as url_consents_detail %}
<li {% if consents_index_url in request.path %} class="active" {% endif %}><a href="{{ consents_index_url }}">{% trans "Consents" %}</a></li>
{% url "users-index" as users_index_url %} {% url 'my-user-detail' as url_users_detail %} {% url "my-user-invitation" as my_user_invitation %}
<li class="dropdown{% if users_index_url in request.path or url_users_detail in request.path or my_user_invitation in request.path %} active{% endif %}">
<a href="#" data-toggle="dropdown" class="dropdown-toggle">{% trans "Users" %}</a>

View File

View File

@ -0,0 +1,11 @@
# -*- coding: utf-8 -*-
"""
App config for consumers app
"""
from django.apps import AppConfig
class AppsConfig(AppConfig):
"""Config for consents"""
name = 'consents'

View File

@ -0,0 +1,7 @@
.table-responsive {
margin-top: 20px;
}
#consents .filter a {
font-size: 12px;
}

View File

@ -0,0 +1,2 @@
$(document).ready(function($) {
});

View File

@ -0,0 +1,59 @@
{% extends 'base.html' %}
{% load humanize static %}
{% load i18n %}
{% block page_title %}{{ block.super }} / Consents {% endblock page_title %}
{% block content %}
<div id="consents">
<h2>Consents</h2>
<table class="table">
<thead>
<tr>
<th>Consent Reference_id</th>
<th>Created User Id</th>
<th>Consumer Id</th>
<th>Jwt Payload</th>
<th>Status</th>
<th>Api Standard</th>
<th scope="col">{% trans "Revoke" %}</th>
</tr>
</thead>
<tbody>
{% for consent in consents %}
<tr>
<td>{{ consent.consent_id }}</td>
<td>{{ consent.created_by_user_id }}</td>
<td>{{ consent.consumer_id }}</td>
<td>{{ consent.jwt_payload }}</td>
<td>{{ consent.status }}</td>
<td>{{ consent.api_standard }}</td>
<td>
<form action="{% url 'consent-revoke' consent.consent_id %}" method="post">
{% csrf_token %}
<button type="submit" class="btn btn-primary btn-sm btn-red">{% trans "Revoke" %}</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock content %}
{% block extrajs %}
{% comment %}
<script type="text/javascript" src="{% static 'consents/js/consents.js' %}"></script>
<script type="text/javascript">
</script>
{% endcomment %}
{% endblock extrajs %}
{% block extracss %}
<link href="{% static 'consents/css/consents.css' %}" rel="stylesheet">
{% endblock extracss %}

View File

@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-
"""
URLs for entitlement requests app
"""
from django.urls import re_path
from .views import IndexView, RevokeConsents
urlpatterns = [
re_path(r'^$',
IndexView.as_view(),
name='consents-index'),
re_path(r'^consents/consent_id/(?P<consent_id>[\w\@\.\+-]+)$',
RevokeConsents.as_view(),
name='consent-revoke'),
]

View File

@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
"""
Views of consent requests app
"""
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView, RedirectView, View
from obp.api import API, APIError
from base.filters import BaseFilter, FilterTime
from datetime import datetime
from django.conf import settings
from django.urls import reverse
from django.http import HttpResponseRedirect
from apimanager.settings import UNDEFINED
class IndexView(LoginRequiredMixin, TemplateView):
"""Index view for consent requests"""
template_name = "consents/index.html"
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
consents = []
api = API(self.request.session.get('obp'))
try:
urlpath = '/my/consents'
consents = api.get(urlpath, settings.API_VERSION['v510'])
if 'code' in consents and consents['code']>=400:
messages.error(self.request, consents['message'])
consents = []
else:
consents = consents['consents']
except APIError as err:
messages.error(self.request, err)
except Exception as err:
messages.error(self.request, err)
context.update({
'consents': consents,
})
return context
class RevokeConsents(LoginRequiredMixin, View):
"""View to revoke a consent"""
def post(self, request, *args, **kwargs):
"""Deletes consent from API"""
api = API(self.request.session.get('obp'))
try:
urlpath = '/my/consent/current'
consent_id= kwargs['consent_id']
headers = {'Consent-Id': consent_id}
response = api.delete(urlpath, settings.API_VERSION['v510'], headers=headers)
if 'code' in response and response['code'] >= 400:
messages.error(self.request, response['message'])
else:
msg = 'Consent {} has been deleted.'.format(consent_id)
messages.success(request, msg)
except APIError as err:
messages.error(request, err)
except Exception as err:
messages.error(self.request, err)
return HttpResponseRedirect(reverse('consents-index'))

View File

@ -43,7 +43,7 @@ class API(object):
self.start_session(session_data)
self.session_data = session_data
def call(self, method='GET', url='', payload=None, version=settings.API_VERSION['v500']):
def call(self, method='GET', url='', payload=None, headers = None):
"""Workhorse which actually calls the API"""
log(logging.INFO, '{} {}'.format(method, url))
if payload:
@ -53,9 +53,9 @@ class API(object):
time_start = time.time()
try:
if payload:
response = session.request(method, url, json=payload, verify=settings.VERIFY)
response = session.request(method, url, json=payload, verify=settings.VERIFY, headers=headers)
else:
response = session.request(method, url, json={}, verify=settings.VERIFY)
response = session.request(method, url, json={}, verify=settings.VERIFY, headers=headers)
except ConnectionError as err:
raise APIError(err)
time_end = time.time()
@ -77,14 +77,14 @@ class API(object):
else:
return response
def delete(self, urlpath, version=settings.API_VERSION['v500']):
def delete(self, urlpath, version=settings.API_VERSION['v500'], headers=None):
"""
Deletes data from the API
Convenience call which uses API_VERSION from settings
"""
url = version + urlpath
response = self.call('DELETE', url)
response = self.call('DELETE', url, headers=headers)
return self.handle_response(response)
def post(self, urlpath, payload, version=settings.API_VERSION['v500']):