From c02ef731af09f6edc25a2fba051184e69c65665f Mon Sep 17 00:00:00 2001 From: root Date: Mon, 31 May 2021 15:28:06 +0200 Subject: [PATCH] parent child groups --- admin/docker/requirements.pip3 | 9 ++- admin/src/admin/__init__.py | 3 + admin/src/admin/lib/admin.py | 73 ++++++++++++++++++- admin/src/admin/lib/keycloak_client.py | 4 + admin/src/admin/lib/moodle.py | 10 ++- admin/src/admin/lib/nextcloud.py | 2 +- admin/src/admin/static/js/external.js | 72 ++++++++++++++++-- admin/src/admin/static/js/status_socket.js | 8 +- admin/src/admin/static/js/users.js | 35 +++++++++ .../static/templates/pages/external.html | 17 ++++- .../pages/modals/external_modals.html | 8 +- .../admin/static/templates/pages/users.html | 9 ++- admin/src/admin/views/MenuViews.py | 12 ++- admin/src/admin/views/Socketio.py | 16 ++++ admin/src/moodle_saml.py | 1 + admin/src/start.py | 22 +++++- docker/haproxy/haproxy.conf | 5 ++ 17 files changed, 277 insertions(+), 29 deletions(-) create mode 100644 admin/src/admin/views/Socketio.py diff --git a/admin/docker/requirements.pip3 b/admin/docker/requirements.pip3 index aa385c7..b693745 100644 --- a/admin/docker/requirements.pip3 +++ b/admin/docker/requirements.pip3 @@ -16,4 +16,11 @@ zope.event==4.4 zope.interface==5.1.0 psycopg2==2.8.6 Flask-SocketIO==2.8.6 -mysql-connector-python==8.0.25 \ No newline at end of file +mysql-connector-python==8.0.25 + + +#Flask-SocketIO==2.8.6 +#gevent==1.4.0 +#greenlet==0.4.15 +python-engineio==3.8.1 +python-socketio==4.1.0 \ No newline at end of file diff --git a/admin/src/admin/__init__.py b/admin/src/admin/__init__.py index e0e0d6d..7aaeb9d 100644 --- a/admin/src/admin/__init__.py +++ b/admin/src/admin/__init__.py @@ -32,6 +32,8 @@ Postup() from admin.lib.admin import Admin app.admin=Admin() +app.ready=False + ''' Debug should be removed on production! ''' @@ -84,3 +86,4 @@ from .views import AvatarViews + diff --git a/admin/src/admin/lib/admin.py b/admin/src/admin/lib/admin.py index f4aa3e8..3a68dcf 100644 --- a/admin/src/admin/lib/admin.py +++ b/admin/src/admin/lib/admin.py @@ -30,6 +30,19 @@ class Admin(): sleep(2) log.warning('Keycloak connected.') + # try: + # self.keycloak.add_group('parent1') + # except: + # pass + # try: + # self.keycloak.add_group('child1','/parent1') + # except: + # pass + # try: + # self.keycloak.add_group('child2','/parent1') + # except: + # pass + ready=False while not ready: try: @@ -306,6 +319,7 @@ class Admin(): theuser={**moodle_exists[0], **theuser} theuser['moodle']=True theuser['moodle_groups']=moodle_exists[0]['groups'] + theuser['moodle_id']=moodle_exists[0]['id'] else: theuser['moodle']=False theuser['moodle_groups']=[] @@ -315,6 +329,7 @@ class Admin(): theuser={**nextcloud_exists[0], **theuser} theuser['nextcloud']=True theuser['nextcloud_groups']=nextcloud_exists[0]['groups'] + theuser['nextcloud_id']=nextcloud_exists[0]['id'] else: theuser['nextcloud']=False theuser['nextcloud_groups']=[] @@ -406,15 +421,18 @@ class Admin(): for g in data['data']['groups']: # for m in data['data']['d_members']: - groups.append({'provider':data['provider'], + # data['provider'] + groups.append({'provider':'external', "id": g['id'], + "mailid": g['email'].split('@')[0], "name": g['name'], "description": g['description']}) self.external['groups']=groups users=[] for u in data['data']['users']: - users.append({'provider':data['provider'], + # data['provider'] + users.append({'provider':'external', 'id':u['id'], 'email': u['primaryEmail'], 'first': u['name']['givenName'], @@ -424,6 +442,12 @@ class Admin(): 'roles':[]}) self.external['users']=users + ## Add groups to users (now they only have their orgUnitPath) + for g in self.external['groups']: + for useringroup in data['data']['d_members'][g['mailid']]: + for u in self.external['users']: + if u['id'] == useringroup['id']: + u['groups']=u['groups']+[g['name']] return True def sync_external(self): @@ -468,7 +492,41 @@ class Admin(): log.error(traceback.format_exc()) log.warning('Could not remove user: '+u['username']) - def delete_keycloak_groups(self): + def delete_nextcloud_users(self): + for u in self.internal['users']: + if u['nextcloud'] and not u['keycloak']: + if u['roles'] and 'admin' in u['roles']: continue + log.info('Removing nextcloud user: '+u['username']) + try: + self.nextcloud.delete_user(u['nextcloud_id']) + socketio.emit('update', + json.dumps({'status':True,'item':'user','action':'delete','itemdata':u}), + namespace='/isard-sso-admin/sio', + room='admin') + except: + log.error(traceback.format_exc()) + log.warning('Could not remove user: '+u['username']) + + def delete_moodle_users(self): + userids=[] + usernames=[] + for u in self.internal['users']: + if u['moodle'] and not u['keycloak']: + userids.append(u['moodle_id']) + usernames.append(u['username']) + + log.warning('Removing moodle users: '+','.join(usernames)) + try: + self.moodle.delete_users(userids) + socketio.emit('update', + json.dumps({'status':True,'item':'user','action':'delete','itemdata':u}), + namespace='/isard-sso-admin/sio', + room='admin') + except: + log.error(traceback.format_exc()) + log.warning('Could not remove users: '+','.join(usernames)) + + def delete_moodle_groups(self): for g in self.internal['groups']: if not g['keycloak']: continue # Do not remove admin group. It should not exist in keycloak, only in nextcloud @@ -478,4 +536,11 @@ class Admin(): self.keycloak.delete_group(g['id']) except: log.error(traceback.format_exc()) - log.warning('Could not remove group: '+g['name']) \ No newline at end of file + log.warning('Could not remove group: '+g['name']) + + def external_roleassign(self,data): + for newuserid in data['ids']: + for externaluser in self.external['users']: + if externaluser['id'] == newuserid: + externaluser['roles']=[data['action']] + return True \ No newline at end of file diff --git a/admin/src/admin/lib/keycloak_client.py b/admin/src/admin/lib/keycloak_client.py index 67faabe..e38a62f 100644 --- a/admin/src/admin/lib/keycloak_client.py +++ b/admin/src/admin/lib/keycloak_client.py @@ -164,6 +164,10 @@ class KeycloakClient(): def add_group(self,name,parent=None): self.connect() + if parent is not None: parent=self.get_group(parent)['id'] + print(name) + print(parent) + print('DONE') return self.keycloak_admin.create_group({"name":name}, parent=parent) def delete_group(self,group_id): diff --git a/admin/src/admin/lib/moodle.py b/admin/src/admin/lib/moodle.py index 3261d77..34d7d6d 100644 --- a/admin/src/admin/lib/moodle.py +++ b/admin/src/admin/lib/moodle.py @@ -2,7 +2,7 @@ from requests import get, post from admin import app import logging as log - +from pprint import pprint from .postgres import Postgres @@ -72,6 +72,14 @@ class Moodle(): user = self.call('core_user_create_users', users=data) return user + def delete_user(self, user_id): + user = self.call('core_user_delete_users', userids=[user_id]) + return user + + def delete_users(self, userids): + user = self.call('core_user_delete_users', userids=userids) + return user + def get_user_by(self, key, value): criteria = [{'key': key, 'value': value}] user = self.call('core_user_get_users', criteria=criteria) diff --git a/admin/src/admin/lib/nextcloud.py b/admin/src/admin/lib/nextcloud.py index d6b2cb6..903fb7b 100644 --- a/admin/src/admin/lib/nextcloud.py +++ b/admin/src/admin/lib/nextcloud.py @@ -128,7 +128,7 @@ class Nextcloud(): def add_user(self,userid,userpassword,quota=False,group=False,email='',displayname=''): data={'userid':userid,'password':userpassword,'quota':quota,'groups[]':group,'email':email,'displayname':displayname} - if not group: del data['group'] + if not group: del data['groups[]'] if not quota: del data['quota'] # if group: # data={'userid':userid,'password':userpassword,'quota':quota,'groups[]':group,'email':email,'displayname':displayname} diff --git a/admin/src/admin/static/js/external.js b/admin/src/admin/static/js/external.js index c9a0da4..7187a98 100644 --- a/admin/src/admin/static/js/external.js +++ b/admin/src/admin/static/js/external.js @@ -54,6 +54,60 @@ $(document).ready(function() { } }); + $('#action_role').on('change', function () { + action=$(this).val(); + names='' + ids=[] + + if(users_table.rows('.active').data().length){ + $.each(users_table.rows('.active').data(),function(key, value){ + names+=value['name']+'\n'; + ids.push(value['id']); + }); + var text = "You are about to assign role "+action+" these users:\n\n "+names + }else{ + $.each(users_table.rows({filter: 'applied'}).data(),function(key, value){ + ids.push(value['id']); + }); + var text = "You are about to assign role "+action+" "+users_table.rows({filter: 'applied'}).data().length+" users!\n All the users in list!" + } + new PNotify({ + title: 'Role assignment!', + text: 'You will asign the role '+action, + hide: false, + opacity: 0.9, + confirm: { + confirm: true + }, + buttons: { + closer: false, + sticker: false + }, + history: { + history: false + }, + addclass: 'pnotify-center' + }).get().on('pnotify.confirm', function() { + $.ajax({ + type: "PUT", + url:"/isard-sso-admin/external/roles", + data: JSON.stringify({'ids':ids,'action':action}), + success: function(data) + { + console.log('SUCCESS') + users_table.ajax.reload(); + groups_table.ajax.reload(); + }, + error: function(data) + { + alert('Something went wrong on our side...') + } + }); + }).on('pnotify.cancel', function() { + $('#action_role option[value="none"]').prop("selected",true); + }); + } ); + //DataTable Main renderer var users_table = $('#users').DataTable({ "ajax": { @@ -74,8 +128,8 @@ $(document).ready(function() { "width": "10px", "defaultContent": '' }, - { "data": "provider", "width": "10px" }, - { "data": "id", "width": "10px" }, + // { "data": "provider", "width": "10px" }, + // { "data": "id", "width": "10px" }, { "data": "username", "width": "10px"}, { "data": "first", "width": "10px"}, { "data": "last", "width": "10px"}, @@ -84,9 +138,15 @@ $(document).ready(function() { { "data": "roles", "width": "10px"}, ], "order": [[3, 'asc']], - "columnDefs": [ ] + "columnDefs": [ { + "targets": 5, + "render": function ( data, type, full, meta ) { + return "
  • " + full.groups.join("
  • ") + "
  • " + }} + ] } ); - + + var groups_table = $('#groups').DataTable({ "ajax": { "url": "/isard-sso-admin/external_groups_list", @@ -106,8 +166,8 @@ $(document).ready(function() { "width": "10px", "defaultContent": '' }, - { "data": "id", "width": "10px" }, - { "data": "provider", "width": "10px" }, + // { "data": "id", "width": "10px" }, + // { "data": "provider", "width": "10px" }, { "data": "name", "width": "10px" }, { "data": "description", "width": "10px"}, ], diff --git a/admin/src/admin/static/js/status_socket.js b/admin/src/admin/static/js/status_socket.js index 81baeaa..7053b12 100644 --- a/admin/src/admin/static/js/status_socket.js +++ b/admin/src/admin/static/js/status_socket.js @@ -1,13 +1,13 @@ // SocketIO - socket = io.connect(location.protocol+'//' + document.domain + ':' + location.port+'/isard-sso-admin/sio'); - + socket = io.connect(location.protocol+'//' + document.domain +'/isard-sso-admin/sio'); + console.log(location.protocol+'//' + document.domain +'/isard-sso-admin/sio') socket.on('connect', function() { - connection_done(); + // connection_done(); console.log('Listening status socket'); }); socket.on('connect_error', function(data) { - connection_lost(); + // connection_lost(); }); socket.on('update', function(data) { diff --git a/admin/src/admin/static/js/users.js b/admin/src/admin/static/js/users.js index d5f2ad2..088d631 100644 --- a/admin/src/admin/static/js/users.js +++ b/admin/src/admin/static/js/users.js @@ -112,6 +112,41 @@ $(document).ready(function() { }); }); + $('.btn-delete_nextcloud').on('click', function () { + $.ajax({ + type: "DELETE", + url:"/isard-sso-admin/users/nextcloud", + success: function(data) + { + console.log('SUCCESS') + // $("#modalImport").modal('hide'); + // users_table.ajax.reload(); + // groups_table.ajax.reload(); + }, + error: function(data) + { + alert('Something went wrong on our side...') + } + }); + }); + + $('.btn-delete_moodle').on('click', function () { + $.ajax({ + type: "DELETE", + url:"/isard-sso-admin/users/moodle", + success: function(data) + { + console.log('SUCCESS') + // $("#modalImport").modal('hide'); + // users_table.ajax.reload(); + // groups_table.ajax.reload(); + }, + error: function(data) + { + alert('Something went wrong on our side...') + } + }); + }); $('.btn-sync_to_moodle').on('click', function () { $.ajax({ type: "POST", diff --git a/admin/src/admin/static/templates/pages/external.html b/admin/src/admin/static/templates/pages/external.html index 7977142..a40b828 100644 --- a/admin/src/admin/static/templates/pages/external.html +++ b/admin/src/admin/static/templates/pages/external.html @@ -14,6 +14,19 @@

    External