From: lombardofr Date: Mon, 10 Sep 2018 09:36:06 +0000 (+0200) Subject: automatic reload on lists; new django decorator for ajax request X-Git-Tag: v5.0.0~32 X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=refs%2Fchanges%2F64%2F6464%2F2;p=osm%2FLW-UI.git automatic reload on lists; new django decorator for ajax request Change-Id: I3eb41de76217191268acb6053ad0c04aec0e8388 Signed-off-by: lombardofr --- diff --git a/authosm/backend.py b/authosm/backend.py index 9c316a9..628eb6a 100644 --- a/authosm/backend.py +++ b/authosm/backend.py @@ -21,6 +21,7 @@ from .exceptions import OSMAuthException class OsmBackend(object): + def authenticate(self, **kwargs): ''' kwargs will receive the python dict that may contain diff --git a/bower.json b/bower.json index 20c60cb..d8b5366 100644 --- a/bower.json +++ b/bower.json @@ -23,6 +23,7 @@ "codemirror": "^5.36.0", "d3": "^4", "bootbox.js": "bootbox#^4.4.0", - "components-font-awesome": "^5.0.6" + "components-font-awesome": "^5.0.6", + "moment": "^2.22.2" } } diff --git a/instancehandler/template/instance_list.html b/instancehandler/template/instance_list.html index 3b8ffcf..de47e62 100644 --- a/instancehandler/template/instance_list.html +++ b/instancehandler/template/instance_list.html @@ -75,9 +75,174 @@ {% endblock %} diff --git a/instancehandler/template/instance_list_ns.html b/instancehandler/template/instance_list_ns.html index 01bdc10..9a50881 100644 --- a/instancehandler/template/instance_list_ns.html +++ b/instancehandler/template/instance_list_ns.html @@ -21,7 +21,7 @@ {{alert_error}} {% endif %} - +
@@ -34,85 +34,7 @@ - {% for i in instances %} - - - - - - {% if i|get:"operational-status" == 'failed' %} - - {% elif i|get:"operational-status" == 'init' %} - - {% elif i|get:"operational-status" == 'running' %} - - {% else %} - - {% endif %} - {% if i|get:"config-status" == 'failed' %} - - {% elif i|get:"config-status" == 'init' %} - - {% elif i|get:"config-status" == 'running' %} - - {% elif i|get:"config-status" == 'configured' %} - - {% else %} - - {% endif %} - - - - - - {% endfor %}
Name
{{ i|get:"short-name" }}{{ i|get:"_id" }}{{ i|get:"nsd-name-ref" }}{{ i|get:"operational-status" }}{{ i|get:"operational-status" }}{{ i|get:"operational-status" }}{{ i|get:"operational-status" }}{{ i|get:"config-status" }}{{ i|get:"config-status" }}{{ i|get:"config-status" }}{{ i|get:"config-status" }}{{ i|get:"config-status" }}{{ i|get:"detailed-status" }} - - -
diff --git a/instancehandler/template/instance_list_vnf.html b/instancehandler/template/instance_list_vnf.html index 5f13f2b..d290ad1 100644 --- a/instancehandler/template/instance_list_vnf.html +++ b/instancehandler/template/instance_list_vnf.html @@ -13,7 +13,7 @@
- +
@@ -25,31 +25,7 @@ - {% for i in instances %} - - - - - - - - - - - - {% endfor %}
Identifier
{{ i|get:"_id" }} {{ i|get:"vnfd-ref" }}{{ i|get:"member-vnf-index-ref" }}{{ i|get:"nsr-id-ref" }}{{ i|get:"created-time"|get_date }} -
- - - -
- -
diff --git a/instancehandler/template/instance_operations_list.html b/instancehandler/template/instance_operations_list.html index 55c097b..7e84658 100644 --- a/instancehandler/template/instance_operations_list.html +++ b/instancehandler/template/instance_operations_list.html @@ -14,6 +14,8 @@ + + {% endblock %} {% block title_header_big %} {{ block.super }} @@ -26,6 +28,7 @@ {% block breadcrumb_body %} {{ block.super }}
  • Instances
  • +
  • Operations
  • {% endblock %} {% block content_body %} @@ -41,7 +44,7 @@
    - +
    @@ -53,40 +56,7 @@ - {% for i in operations %} - - - - - - {% if i|get:"operationState" == 'FAILED' %} - - {% elif i|get:"operationState" == 'PROCESSING' %} - - {% elif i|get:"operationState" == 'COMPLETED' %} - - {% else %} - - {% endif %} - - - - - - - - {% endfor %}
    Id
    {{ i|get:"_id" }}{{ i|get:"lcmOperationType" }}{{ i|get:"operationState" }} {{ i|get:"operationState" }} {{ i|get:"operationState" }} {{ i|get:"operationState" }}{{ i.startTime|get_date }}{{ i.statusEnteredTime|get_date }} -
    - - -
    - -
    @@ -114,10 +84,96 @@ + + + + {% endblock %} {% block footer %} {% include "footer.html" %} -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/instancehandler/views.py b/instancehandler/views.py index 212fbbf..d80d18d 100644 --- a/instancehandler/views.py +++ b/instancehandler/views.py @@ -15,33 +15,39 @@ # from django.shortcuts import render, redirect -from django.contrib.auth.decorators import login_required +#from django.contrib.auth.decorators import login_required from django.http import HttpResponse, JsonResponse import yaml import json import logging from lib.osm.osmclient.clientv2 import Client import authosm.utils as osmutils +from sf_t3d.decorators import login_required logging.basicConfig(level=logging.DEBUG) log = logging.getLogger('instancehandler/view.py') + @login_required def list(request, type=None): + user = osmutils.get_user(request) project_id = user.project_id client = Client() + result = {'type': type, 'project_id': project_id} + if "OSM_ERROR" in request.session: + result['alert_error'] = request.session["OSM_ERROR"] + del request.session["OSM_ERROR"] + raw_content_types = request.META.get('HTTP_ACCEPT', '*/*').split(',') + if 'application/json' not in raw_content_types: + return __response_handler(request, result, 'instance_list.html') + instance_list = None if type == 'ns': instance_list = client.ns_list(user.get_token()) elif type == 'vnf': instance_list = client.vnf_list(user.get_token()) - result = {'instances': instance_list['data'] if instance_list and instance_list['error'] is False else [], - 'type': type, 'project_id': project_id} - - if "OSM_ERROR" in request.session: - result['alert_error'] = request.session["OSM_ERROR"] - del request.session["OSM_ERROR"] + result['instances'] = instance_list['data'] if instance_list and instance_list['error'] is False else [] return __response_handler(request, result, 'instance_list.html') @@ -96,12 +102,16 @@ def create(request): def ns_operations(request, instance_id=None, type=None): user = osmutils.get_user(request) project_id = user.project_id + + result = {'type': 'ns', 'project_id': project_id, 'instance_id': instance_id} + raw_content_types = request.META.get('HTTP_ACCEPT', '*/*').split(',') + if 'application/json' not in raw_content_types: + return __response_handler(request, result, 'instance_operations_list.html') client = Client() op_list = client.ns_op_list(user.get_token(), instance_id) - return __response_handler(request, - {'operations': op_list['data'] if op_list and op_list['error'] is False else [], - 'type': 'ns', 'project_id': project_id}, 'instance_operations_list.html') + result['operations'] = op_list['data'] if op_list and op_list['error'] is False else [] + return __response_handler(request, result, 'instance_operations_list.html') @login_required def ns_operation(request, op_id, instance_id=None, type=None): diff --git a/projecthandler/middleware.py b/projecthandler/middleware.py index 4880ebe..89ae94d 100644 --- a/projecthandler/middleware.py +++ b/projecthandler/middleware.py @@ -1,6 +1,4 @@ class OsmProjectMiddleware(object): def process_view(self, request, view_func, view_args, view_kwargs): - print "OsmProjectMiddleware", view_func, view_args, view_kwargs - return None \ No newline at end of file diff --git a/projecthandler/template/project/osm/osm_project_descriptors.html b/projecthandler/template/project/osm/osm_project_descriptors.html index f877ea8..182c8cc 100644 --- a/projecthandler/template/project/osm/osm_project_descriptors.html +++ b/projecthandler/template/project/osm/osm_project_descriptors.html @@ -48,11 +48,104 @@ diff --git a/projecthandler/template/project/projectlist.html b/projecthandler/template/project/projectlist.html index 213c5b0..a90fec8 100644 --- a/projecthandler/template/project/projectlist.html +++ b/projecthandler/template/project/projectlist.html @@ -52,34 +52,7 @@ - {% for p in projects %} - - - {{ p.name }} - - - {{ p|get_sub:"_admin,modified"|get_date}} - {{ p|get_sub:"_admin,created"|get_date}} - - -
    - - -
    - - - {% endfor %} @@ -97,21 +70,86 @@ {% endblock %} diff --git a/sdnctrlhandler/views.py b/sdnctrlhandler/views.py index e015ded..52be0a4 100644 --- a/sdnctrlhandler/views.py +++ b/sdnctrlhandler/views.py @@ -15,7 +15,7 @@ # from django.shortcuts import render, redirect -from django.contrib.auth.decorators import login_required +from sf_t3d.decorators import login_required from django.http import HttpResponse import json import logging @@ -30,13 +30,15 @@ log = logging.getLogger('sdnctrlhandler/view.py') def list(request): user = osmutils.get_user(request) project_id = user.project_id + result = {'project_id': project_id} + raw_content_types = request.META.get('HTTP_ACCEPT', '*/*').split(',') + if 'application/json' not in raw_content_types: + return __response_handler(request, result, 'sdn_list.html') client = Client() - result = client.sdn_list(user.get_token()) + result_client = client.sdn_list(user.get_token()) + + result['sdns'] = result_client['data'] if result_client and result_client['error'] is False else [] - result = { - 'project_id': project_id, - 'sdns': result['data'] if result and result['error'] is False else [] - } return __response_handler(request, result, 'sdn_list.html') diff --git a/sf_t3d/decorators.py b/sf_t3d/decorators.py new file mode 100644 index 0000000..9f4981b --- /dev/null +++ b/sf_t3d/decorators.py @@ -0,0 +1,76 @@ +# +# Copyright 2018 EveryUP Srl +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +""" + This Decorator is a modified version of django.contrib.auth.decorators, in order to avoid retirect to login_url + with AJAX calls. +""" + +from django.http import HttpResponse +from django.conf import settings +from django.contrib.auth import REDIRECT_FIELD_NAME +from django.shortcuts import resolve_url +from django.utils.decorators import available_attrs +from django.utils.six.moves.urllib.parse import urlparse +from six import wraps +from django.contrib.auth.views import redirect_to_login + + +def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME): + """ + Decorator for views that checks that the user passes the given test, + redirecting to the log-in page if necessary. The test should be a callable + that takes the user object and returns True if the user passes. + """ + + def decorator(view_func): + @wraps(view_func, assigned=available_attrs(view_func)) + def _wrapped_view(request, *args, **kwargs): + if test_func(request.user): + return view_func(request, *args, **kwargs) + path = request.build_absolute_uri() + resolved_login_url = resolve_url(login_url or settings.LOGIN_URL) + # If the login url is the same scheme and net location then just + # use the path as the "next" url. + login_scheme, login_netloc = urlparse(resolved_login_url)[:2] + current_scheme, current_netloc = urlparse(path)[:2] + if ((not login_scheme or login_scheme == current_scheme) and + (not login_netloc or login_netloc == current_netloc)): + path = request.get_full_path() + raw_content_types = request.META.get('HTTP_ACCEPT', '*/*').split(',') + # if Browser call + if 'application/json' not in raw_content_types: + return redirect_to_login(path, resolved_login_url, redirect_field_name) + # if AJAX call + else: + return HttpResponse(status=401) + return _wrapped_view + return decorator + + +def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None): + """ + Decorator for views that checks that the user is logged in, redirecting + to the log-in page if necessary. + """ + actual_decorator = user_passes_test( + lambda u: u.is_authenticated, + login_url=login_url, + redirect_field_name=redirect_field_name + ) + if function: + return actual_decorator(function) + return actual_decorator diff --git a/static/src/instancehandler/instance_list.js b/static/src/instancehandler/instance_list.js index c53c0b4..fa9bef4 100644 --- a/static/src/instancehandler/instance_list.js +++ b/static/src/instancehandler/instance_list.js @@ -14,28 +14,27 @@ limitations under the License. */ -function performAction(url) { +function performAction(instance_name, instance_id) { + var url = '/instances/ns/'+instance_id+'/action'; $("#formActionNS").attr("action", url); $('#modal_instance_new_action').modal('show'); } -function exportMetricNs(url) { - console.log(url) +function exportMetricNs(instance_name, instance_id) { + var url = '/instances/ns/'+instance_id+'/monitoring/metric'; $("#formExportMetricNS").attr("action", url); $('#modal_instance_export_metric').modal('show'); } -function showInstanceTopology(url) { - window.location.href = url; -} - -function newAlarmNs(url) { +function newAlarmNs(instance_name, instance_id) { + var url = '/instances/ns/'+instance_id+'/monitoring/alarm'; $("#formAlarmNS").attr("action", url); $('#modal_instance_new_alarm').modal('show'); } -function deleteNs(url, force) { - bootbox.confirm("Are you sure want to delete?", function (result) { +function deleteNs(instance_name, instance_id, force) { + var url = '/instances/ns/'+instance_id+'/delete'; + bootbox.confirm("Are you sure want to delete " + instance_name + "?", function (result) { if (result) { if (force) url = url + '?force=true'; @@ -88,7 +87,8 @@ var removeFormGroup = function (event) { $formGroup.remove(); }; -function showInstanceDetails(url_info) { +function showInstanceDetails(type, instance_id) { + var url_info = '/instances/'+type+'/'+instance_id; var dialog = bootbox.dialog({ message: '
    Loading...
    ', closeButton: true diff --git a/static/src/instancehandler/instance_operations_list.js b/static/src/instancehandler/instance_operations_list.js index 705fce2..d85ebcf 100644 --- a/static/src/instancehandler/instance_operations_list.js +++ b/static/src/instancehandler/instance_operations_list.js @@ -15,7 +15,8 @@ */ -function showOperationDetails(url_info) { +function showOperationDetails(instance_id, operation_id) { + var url_info = '/instances/ns/'+instance_id+'/operation/' + operation_id; var dialog = bootbox.dialog({ message: '
    Loading...
    ', closeButton: true diff --git a/static/src/projecthandler/descriptorslist.js b/static/src/projecthandler/descriptorslist.js index d6ee937..c85603c 100644 --- a/static/src/projecthandler/descriptorslist.js +++ b/static/src/projecthandler/descriptorslist.js @@ -1,11 +1,11 @@ function deletePackage(descriptor_type, package_id) { - var dialog = bootbox.dialog({ - message: '
    Loading...
    ', - closeButton: true - }); + bootbox.confirm("Are you sure want to delete?", function (result) { if (result) { - + var dialog = bootbox.dialog({ + message: '
    Loading...
    ', + closeButton: true + }); $.ajax({ url: '/projects/descriptors/' + descriptor_type + '/' + package_id + '/delete', type: 'GET', diff --git a/static/src/sdnctrlhandler/sdn_list.js b/static/src/sdnctrlhandler/sdn_list.js index 013cb6f..5542825 100644 --- a/static/src/sdnctrlhandler/sdn_list.js +++ b/static/src/sdnctrlhandler/sdn_list.js @@ -1,5 +1,5 @@ -function deleteSDN(sdn_uuid) { - bootbox.confirm("Are you sure want to delete?", function (result) { +function deleteSDN(sdn_uuid, name) { + bootbox.confirm("Are you sure want to delete " + name +"?", function (result) { if (result) { var dialog = bootbox.dialog({ message: '
    Loading...
    ', diff --git a/static/src/userhandler/user_list.js b/static/src/userhandler/user_list.js index 282c314..88f4770 100644 --- a/static/src/userhandler/user_list.js +++ b/static/src/userhandler/user_list.js @@ -26,8 +26,9 @@ function openModalCreateUser(args) { $('#modal_new_user').modal('show'); } -function deleteUser(delete_url) { - bootbox.confirm("Are you sure want to delete?", function (confirm) { +function deleteUser(user_id, name) { + var delete_url = '/admin/users/'+user_id+'/delete'; + bootbox.confirm("Are you sure want to delete "+name+"?", function (confirm) { if (confirm) { var dialog = bootbox.dialog({ message: '
    Loading...
    ', diff --git a/static/src/utils.js b/static/src/utils.js index 83b580c..6763f78 100644 --- a/static/src/utils.js +++ b/static/src/utils.js @@ -2,8 +2,8 @@ function generateUID() { return ("0000" + (Math.random() * Math.pow(36, 4) << 0).toString(36)).slice(-4) } -function openProject(pId) { - window.location.href = '/projects/' + pId; +function moveToLogin(next) { + window.location.href = (next) ? "/auth/?next="+next : '/auth/'; } diff --git a/template/base.html b/template/base.html index bb56c29..ee790ff 100644 --- a/template/base.html +++ b/template/base.html @@ -174,6 +174,8 @@ + + diff --git a/userhandler/templates/user_list.html b/userhandler/templates/user_list.html index 8d7e84a..621df92 100644 --- a/userhandler/templates/user_list.html +++ b/userhandler/templates/user_list.html @@ -56,34 +56,7 @@ - {% for s in users %} - - - {{ s|get:"username" }} - {{ s|get:"projects" }} - {{ s|get:"_id" }} - {{ s|get_sub:"_admin,modified"|get_date}} - {{ s|get_sub:"_admin,created"|get_date}} - - - -
    - - -
    - - - - {% endfor %} + @@ -101,8 +74,76 @@ diff --git a/userhandler/views.py b/userhandler/views.py index 8e312fa..aa0d8d2 100644 --- a/userhandler/views.py +++ b/userhandler/views.py @@ -1,5 +1,5 @@ from django.shortcuts import render, redirect -from django.contrib.auth.decorators import login_required +from sf_t3d.decorators import login_required from django.http import HttpResponse import json import logging diff --git a/vimhandler/template/vim_list.html b/vimhandler/template/vim_list.html index 07cb857..adc823a 100644 --- a/vimhandler/template/vim_list.html +++ b/vimhandler/template/vim_list.html @@ -50,29 +50,7 @@ - {% for p in datacenters %} - - {{ p|get:"name" }} - {{ p|get:"_id" }} - {{ p|get:"vim_type" }} - {{ p|get_sub:"_admin,operationalState"}} - {{ p|get_sub:"_admin,description" }} - - - -
    - - -
    - - - - {% endfor %} @@ -88,13 +66,82 @@