user: list, create, delete 50/6350/2
authorlombardofr <lombardo@everyup.it>
Tue, 17 Jul 2018 21:42:28 +0000 (23:42 +0200)
committergarciadeblas <gerardo.garciadeblas@telefonica.com>
Thu, 19 Jul 2018 12:13:06 +0000 (13:13 +0100)
Change-Id: Ie670a45c4f60107b6563b10504b744d13c58b328
Signed-off-by: lombardofr <lombardo@everyup.it>
16 files changed:
lib/osm/osmclient/clientv2.py
projecthandler/views.py
sf_t3d/settings.py
sf_t3d/urls.py
static/src/userhandler/user_list.js [new file with mode: 0644]
userhandler/__init__.py [new file with mode: 0644]
userhandler/admin.py [new file with mode: 0644]
userhandler/apps.py [new file with mode: 0644]
userhandler/migrations/__init__.py [new file with mode: 0644]
userhandler/models.py [new file with mode: 0644]
userhandler/templates/modal/user_create.html [new file with mode: 0644]
userhandler/templates/modal/user_details.html [new file with mode: 0644]
userhandler/templates/user_list.html [new file with mode: 0644]
userhandler/tests.py [new file with mode: 0644]
userhandler/urls.py [new file with mode: 0644]
userhandler/views.py [new file with mode: 0644]

index 6555071..536ef65 100644 (file)
@@ -55,6 +55,61 @@ class Client(object):
 
         return result
 
+    def user_list(self, token):
+        result = {'error': True, 'data': ''}
+        headers = {"Content-Type": "application/json", "accept": "application/json",
+                   'Authorization': 'Bearer {}'.format(token['id'])}
+
+        _url = "{0}/admin/v1/users".format(self._base_path)
+        try:
+            r = requests.get(_url, params=None, verify=False, stream=True, headers=headers)
+        except Exception as e:
+            log.exception(e)
+            result['data'] = str(e)
+            return result
+        if r.status_code == requests.codes.ok:
+            result['error'] = False
+        result['data'] = Util.json_loads_byteified(r.text)
+
+        return result
+
+    def user_create(self, token, user_data):
+        result = {'error': True, 'data': ''}
+        headers = {"Content-Type": "application/json", "accept": "application/json",
+                   'Authorization': 'Bearer {}'.format(token['id'])}
+
+        _url = "{0}/admin/v1/users".format(self._base_path)
+
+        try:
+            r = requests.post(_url, json=user_data, verify=False, headers=headers)
+        except Exception as e:
+            log.exception(e)
+            result['data'] = str(e)
+            return result
+        print r.status_code
+        if r.status_code == requests.codes.created:
+            result['error'] = False
+        result['data'] = Util.json_loads_byteified(r.text)
+        return result
+
+    def user_delete(self, token, id):
+        result = {'error': True, 'data': ''}
+        headers = {"Content-Type": "application/yaml", "accept": "application/json",
+                   'Authorization': 'Bearer {}'.format(token['id'])}
+
+        _url = "{0}/admin/v1/users/{1}".format(self._base_path, id)
+        try:
+            r = requests.delete(_url, params=None, verify=False, headers=headers)
+        except Exception as e:
+            log.exception(e)
+            result['data'] = str(e)
+            return result
+        if r.status_code == requests.codes.no_content:
+            result['error'] = False
+        else:
+            result['data'] = Util.json_loads_byteified(r.text)
+        return result
+
     def project_list(self, token):
         result = {'error': True, 'data': ''}
         headers = {"Content-Type": "application/yaml", "accept": "application/json",
index 144aa5b..575d253 100644 (file)
@@ -59,9 +59,10 @@ def user_projects(request):
     user = osmutils.get_user(request)
     client = Client()
     result = client.project_list(user.get_token())
-    return render(request, 'projectlist.html', {
+    return __response_handler(request,{
         'projects': result['data'] if result and result['error'] is False else [],
-    })
+    },'projectlist.html')
+
 
 
 def open_composer(request):
index 53bde44..0649cde 100644 (file)
@@ -51,6 +51,7 @@ INSTALLED_APPS = [
     'vimhandler',
     'instancehandler',
     'sdnctrlhandler',
+    'userhandler'
 
 ]
 
@@ -86,6 +87,7 @@ TEMPLATES = [
             os.path.join(BASE_DIR, 'vimhandler', 'template'),
             os.path.join(BASE_DIR, 'instancehandler', 'template'),
             os.path.join(BASE_DIR, 'sdnctrlhandler', 'template'),
+            os.path.join(BASE_DIR, 'userhandler', 'templates'),
         ],
         'APP_DIRS': True,
         'OPTIONS': {
index 3524ebb..4902f8d 100644 (file)
@@ -25,6 +25,7 @@ urlpatterns = [
     url(r'^auth/$', user_views.user_login, name='auth_user'),
     #url(r'^register', user_views.register_view, name='register_user'),
     url(r'^projects/', include('projecthandler.urls.project', namespace='projects'), name='projects_base'),
+    url(r'^users/', include('userhandler.urls', namespace='users'), name='users_base'),
 
     url(r'^$', views.home, name='home'),
     url(r'^home', views.home, name='home'),
diff --git a/static/src/userhandler/user_list.js b/static/src/userhandler/user_list.js
new file mode 100644 (file)
index 0000000..196b878
--- /dev/null
@@ -0,0 +1,55 @@
+function openModalCreateUser(args) {
+    console.log(args)
+    // load projects list
+    select2_groups = $('#projects').select2({
+        placeholder: 'Select Projects',
+        width: '100%',
+        ajax: {
+            url: args.projects_list_url,
+            dataType: 'json',
+            processResults: function (data) {
+                projects = [];
+                if (data['projects']) {
+                    for (d in data['projects']) {
+                        var project = data['projects'][d];
+                        projects.push({id: project['_id'], text: project['name']})
+                    }
+                }
+
+                return {
+                    results: projects
+                };
+            }
+        }
+    });
+
+
+
+    $('#modal_new_user').modal('show');
+}
+
+function deleteUser(delete_url) {
+    bootbox.confirm("Are you sure want to delete?", function (confirm) {
+        if (confirm) {
+            var dialog = bootbox.dialog({
+                message: '<div class="text-center"><i class="fa fa-spin fa-spinner"></i> Loading...</div>',
+                closeButton: false
+            });
+            $.ajax({
+                url: delete_url,
+                dataType: "json",
+                contentType: "application/json;charset=utf-8",
+                success: function (result) {
+                    //$('#modal_show_vim_body').empty();
+                    dialog.modal('hide');
+                    location.reload();
+                },
+                error: function (result) {
+                    dialog.modal('hide');
+                    bootbox.alert("An error occurred.");
+                }
+            });
+        }
+    })
+
+}
\ No newline at end of file
diff --git a/userhandler/__init__.py b/userhandler/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/userhandler/admin.py b/userhandler/admin.py
new file mode 100644 (file)
index 0000000..8c38f3f
--- /dev/null
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/userhandler/apps.py b/userhandler/apps.py
new file mode 100644 (file)
index 0000000..45574cc
--- /dev/null
@@ -0,0 +1,7 @@
+from __future__ import unicode_literals
+
+from django.apps import AppConfig
+
+
+class UserhandlerConfig(AppConfig):
+    name = 'userhandler'
diff --git a/userhandler/migrations/__init__.py b/userhandler/migrations/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/userhandler/models.py b/userhandler/models.py
new file mode 100644 (file)
index 0000000..bd4b2ab
--- /dev/null
@@ -0,0 +1,5 @@
+from __future__ import unicode_literals
+
+from django.db import models
+
+# Create your models here.
diff --git a/userhandler/templates/modal/user_create.html b/userhandler/templates/modal/user_create.html
new file mode 100644 (file)
index 0000000..7967cc6
--- /dev/null
@@ -0,0 +1,53 @@
+<div class="modal" id="modal_new_user" xmlns="http://www.w3.org/1999/html">
+    <div class="modal-dialog">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">×</span></button>
+                <h4 class="modal-title">New User</h4>
+            </div>
+            <form id="formCreateNS" action='{% url "users:create"   %}'
+                  class="form-horizontal"
+                  method="post" enctype="multipart/form-data">
+                {% csrf_token %}
+                <div class="modal-body" id="modal_new_user_body">
+                    <div class="form-group">
+                        <label for="username" class="col-sm-3 control-label">Username *</label>
+                        <div class="col-sm-6">
+                            <input class="form-control" id="username" name="username"
+                                   placeholder="Username" required>
+                        </div>
+                    </div>
+
+                    <div class="form-group">
+                        <label for="password" class="col-sm-3 control-label">Password *</label>
+                        <div class="col-sm-6">
+                           <input class="form-control" id="password" name="password" type="password"
+                                   placeholder="Password" required>
+                        </div>
+                    </div>
+                    <div class="form-group">
+                        <label for=projects" class="col-sm-3 control-label">Projects *</label>
+                        <div class="col-sm-6">
+                            <select required id="projects" class="js-example-basic-multiple form-control" name="projects"
+                            multiple="multiple">
+                            </select>
+                        </div>
+                    </div>
+
+
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-default pull-left" data-dismiss="modal">Cancel</button>
+                    <button class="btn btn-primary"
+                            data-loading-text="<i class='fa fa-circle-o-notch fa-spin'></i> Creating..."
+                            id="create_new_user">Create
+                    </button>
+
+                </div>
+            </form>
+        </div>
+        <!-- /.modal-content -->
+    </div>
+    <!-- /.modal-dialog -->
+</div>
diff --git a/userhandler/templates/modal/user_details.html b/userhandler/templates/modal/user_details.html
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/userhandler/templates/user_list.html b/userhandler/templates/user_list.html
new file mode 100644 (file)
index 0000000..03ae70f
--- /dev/null
@@ -0,0 +1,98 @@
+{% extends "base.html" %}
+{% load get %}
+{% load date_tag %}
+{% load staticfiles %}
+
+
+{% block head_block %}
+    {{ block.super }}
+    <link rel="stylesheet" href="/static/bower_components/select2/dist/css/select2.min.css">
+{% endblock %}
+{% block title_header_big %}
+    {{ block.super }}
+{% endblock %}
+{% block left_sidebar %}
+    {% include 'osm/osm_project_left_sidebar.html' %}
+{% endblock %}
+
+
+{% block breadcrumb_body %}
+    {{ block.super }}
+    <li><a href="#">Users</a></li>
+{% endblock %}
+
+{% block content_body %}
+    {{ block.super }}
+    {% include 'modal/user_details.html' %}
+    {% include 'modal/user_create.html' %}
+    {% csrf_token %}
+    <div class="row">
+        <div class="col-md-12">
+
+            <div class="box">
+                <div class="box-header with-border">
+                    <h3 class="box-title">Users</h3>
+                    <div class="box-tools">
+                        <button type="button" class="btn btn-default" data-container="body"
+                                onclick="javascript:openModalCreateUser({'projects_list_url': '{% url "projects:projects_list"  %}'})"
+                                        data-toggle="tooltip" data-placement="top" title="New User">
+
+                                    <i class="fa fa-plus"></i> Create User</button>
+
+                    </div>
+                </div>
+                <div class="box-body">
+                    <table id="users_table" class="table table-bordered table-striped">
+                        <thead>
+                        <tr>
+                            <th>Name</th>
+                            <th>Projects</th>
+                            <th>Identifier</th>
+                            <th>Modified</th>
+                             <th>Created</th>
+                            <th>Actions</th>
+
+                        </tr>
+                        </thead>
+                        <tbody>
+                        {% for s in users %}
+                            <tr>
+
+                                <td>{{ s|get:"username" }}</td>
+                                <td>{{ s|get:"projects" }}</td>
+                                <td>{{ s|get:"_id" }}</td>
+                                <td>{{ s|get_sub:"_admin,modified"|get_date}}</td>
+                                <td>{{ s|get_sub:"_admin,created"|get_date}}</td>
+
+                                <td>
+                                    <div class="btn-group">
+
+                                        <button type="button" class="btn btn-default"
+                                                onclick="javascript:deleteUser('{% url "users:delete" user_id=s|get:"_id"  %}')" data-toggle="tooltip" data-placement="top" data-container="body" title="Delete"><i
+                                                class="far fa-trash-alt" ></i></button>
+                                    </div>
+                                </td>
+
+                            </tr>
+                        {% endfor %}
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+        </div>
+
+    </div>
+{% endblock %}
+
+{% block resource_block %}
+    {{ block.super }}
+    <!-- moment JS -->
+    <script src="/static/bower_components/select2/dist/js/select2.js"></script>
+    <script src="/static/src/userhandler/user_list.js"></script>
+
+
+{% endblock %}
+
+{% block footer %}
+    {% include "footer.html"  %}
+{% endblock %}
\ No newline at end of file
diff --git a/userhandler/tests.py b/userhandler/tests.py
new file mode 100644 (file)
index 0000000..7ce503c
--- /dev/null
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/userhandler/urls.py b/userhandler/urls.py
new file mode 100644 (file)
index 0000000..05d88f0
--- /dev/null
@@ -0,0 +1,25 @@
+#
+#   Copyright 2018 CNIT - Consorzio Nazionale Interuniversitario per le Telecomunicazioni
+#
+#   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.
+#
+
+from django.conf.urls import url
+from userhandler import views
+
+urlpatterns = [
+    url(r'^list$', views.list, name='list'),
+    url(r'^create$', views.create, name='create'),
+    url(r'^(?P<user_id>[0-9a-zA-Z]+)/delete$', views.delete, name='delete'),
+
+]
\ No newline at end of file
diff --git a/userhandler/views.py b/userhandler/views.py
new file mode 100644 (file)
index 0000000..8e312fa
--- /dev/null
@@ -0,0 +1,57 @@
+from django.shortcuts import render, redirect
+from django.contrib.auth.decorators import login_required
+from django.http import HttpResponse
+import json
+import logging
+import authosm.utils as osmutils
+from lib.osm.osmclient.clientv2 import Client
+
+logging.basicConfig(level=logging.DEBUG)
+log = logging.getLogger(__name__)
+
+
+@login_required
+def list(request):
+    user = osmutils.get_user(request)
+    client = Client()
+    result = client.user_list(user.get_token())
+    result = {
+        'users': result['data'] if result and result['error'] is False else []
+    }
+    return __response_handler(request, result, 'user_list.html')
+
+
+@login_required
+def create(request):
+    user = osmutils.get_user(request)
+    client = Client()
+    user_data ={
+        "username": request.POST['username'],
+        "password": request.POST['password'],
+        "projects": request.POST.getlist('projects')
+    }
+
+    result = client.user_create(user.get_token(), user_data)
+
+    return __response_handler(request, result, 'users:list', to_redirect=True)
+
+
+@login_required
+def delete(request, user_id=None):
+    user = osmutils.get_user(request)
+    try:
+        client = Client()
+        del_res = client.user_delete(user.get_token(), user_id)
+    except Exception as e:
+        log.exception(e)
+    return __response_handler(request, {}, 'users:list', to_redirect=True, )
+
+
+def __response_handler(request, data_res, url=None, to_redirect=None, *args, **kwargs):
+    raw_content_types = request.META.get('HTTP_ACCEPT', '*/*').split(',')
+    if 'application/json' in raw_content_types or url is None:
+        return HttpResponse(json.dumps(data_res), content_type="application/json", *args, **kwargs)
+    elif to_redirect:
+        return redirect(url, *args, **kwargs)
+    else:
+        return render(request, url, data_res)