From 09ae3e16e6f111b3ce60d106659934f081ca1e89 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 7 Jun 2021 03:02:59 +0200 Subject: [PATCH] Fixed avatars on deleting and UI things --- admin/src/admin/lib/admin.py | 34 +++-- admin/src/admin/lib/avatars.py | 17 ++- admin/src/admin/lib/events.py | 9 +- admin/src/admin/lib/keycloak_client.py | 4 +- admin/src/admin/lib/moodle.py | 1 - admin/src/admin/lib/mysql.py | 1 - admin/src/admin/lib/nextcloud.py | 2 - admin/src/admin/lib/postgres.py | 1 - admin/src/admin/lib/postup.py | 1 - admin/src/admin/static/dd.js | 1 + admin/src/admin/static/js/status_socket.js | 7 +- .../static/js/{ => sysadmin}/external.js | 54 ++++++- admin/src/admin/static/js/sysadmin/users.js | 141 +++++++++++++----- admin/src/admin/static/js/users.js | 94 +----------- admin/src/admin/static/templates/header.html | 4 +- .../templates/pages/sysadmin/external.html | 4 +- .../templates/pages/sysadmin/users.html | 2 +- .../admin/static/templates/pages/users.html | 17 --- admin/src/admin/views/ApiViews.py | 9 +- 19 files changed, 218 insertions(+), 185 deletions(-) rename admin/src/admin/static/js/{ => sysadmin}/external.js (82%) diff --git a/admin/src/admin/lib/admin.py b/admin/src/admin/lib/admin.py index 0fa3ea5..94169bc 100644 --- a/admin/src/admin/lib/admin.py +++ b/admin/src/admin/lib/admin.py @@ -78,9 +78,9 @@ class Admin(): 'groups':[], 'roles':[]} log.warning(' Updating missing user avatars with defaults') - av=Avatars() + self.av=Avatars() # av.minio_delete_all_objects() # This will reset all avatars on usres - av.update_missing_avatars(self.internal['users']) + self.av.update_missing_avatars(self.internal['users']) log.warning(' SYSTEM READY TO HANDLE CONNECTIONS') ## This function should be moved to postup.py @@ -457,21 +457,28 @@ class Admin(): def get_dice_pwd(self): return diceware.get_passphrase(options=options) + def reset_external(self): + self.external={'users':[], + 'groups':[], + 'roles':[]} + return True + def upload_json_ga(self,data): groups=[] log.warning('Processing uploaded groups...') try: - ev=Events('Processing uploaded groups','Group:',total=len(data['data']['groups'])) + ev=Events('Processing uploaded groups','Group:',total=len(data['data']['groups']),table='groups') except: log.error(traceback.format_exc()) for g in data['data']['groups']: try: - ev.increment({'name':g['name'],'data':g}) - groups.append({'provider':'external', - "id": g['id'], - "mailid": g['email'].split('@')[0], - "name": g['name'], - "description": g['description']}) + group={'provider':'external', + "id": g['id'], + "mailid": g['email'].split('@')[0], + "name": g['name'], + "description": g['description']} + ev.increment({'name':g['name'],'data':group}) + groups.append(group) except: pass self.external['groups']=groups @@ -480,7 +487,7 @@ class Admin(): users=[] total=len(data['data']['users']) item=1 - ev=Events('Processing uploaded users','User:',total=len(data['data']['users'])) + ev=Events('Processing uploaded users','User:',total=len(data['data']['users']),table='users') for u in data['data']['users']: log.warning('Processing ('+str(item)+'/'+str(total)+') uploaded user: '+u['primaryEmail'].split('@')[0]) new_user={'provider':'external', @@ -491,7 +498,7 @@ class Admin(): 'username': u['primaryEmail'].split('@')[0], 'groups':[u['orgUnitPath']], ## WARNING: Removing the first 'roles':[], - 'password': diceware.get_passphrase(options=options)} + 'password': self.get_dice_pwd()} users.append(new_user) item+=1 ev.increment({'name':u['primaryEmail'].split('@')[0],'data':new_user}) @@ -539,7 +546,7 @@ class Admin(): log.warning(' KEYCLOAK USERS: Adding user ('+str(index)+'/'+str(total)+'): '+u['username']) ev.increment({'name':u['username'],'data':u}) uid=self.keycloak.add_user(u['username'],u['first'],u['last'],u['email'],u['password']) - + self.av.add_user_default_avatar(uid,u['roles'][0]) # Add user to role and group rolename if len(u['roles']) != 0: log.warning(' KEYCLOAK USERS: Assign user '+u['username']+' with initial pwd '+ u['password']+' to role '+u['roles'][0]) @@ -686,6 +693,8 @@ class Admin(): except: log.error(traceback.format_exc()) log.warning('Could not remove users: '+user['username']) + + self.av.delete_user_avatar(userid) def delete_keycloak_users(self): total=len(self.internal['users']) @@ -702,6 +711,7 @@ class Admin(): self.keycloak.delete_user(u['id']) except: log.warning(' KEYCLOAK USERS: Could not remove user: '+u['username'] +'. Probably already not exists.') + self.av.minio_delete_all_objects() def delete_nextcloud_user(self,userid): user=[u for u in self.internal['users'] if u['id']==userid] diff --git a/admin/src/admin/lib/avatars.py b/admin/src/admin/lib/avatars.py index b3b197b..f80f82c 100644 --- a/admin/src/admin/lib/avatars.py +++ b/admin/src/admin/lib/avatars.py @@ -21,6 +21,16 @@ class Avatars(): self._minio_set_realm() # self.update_missing_avatars() + def add_user_default_avatar(self,userid,role='unknown'): + self.mclient.fput_object( + self.bucket, userid, os.path.join(app.root_path,"../custom/avatars/"+role+'.jpg'), + content_type="image/jpeg ", + ) + log.warning(' AVATARS: Updated avatar for user '+userid+' with role '+role) + + def delete_user_avatar(self,userid): + self.minio_delete_object(userid) + def update_missing_avatars(self,users): sys_roles=['admin','manager','teacher','student'] for u in self.get_users_without_image(users): @@ -49,7 +59,12 @@ class Avatars(): ) errors=self.mclient.remove_objects(self.bucket, delete_object_list) for error in errors: - log.error(" AVATARS: Error occured when deleting avatar object", error) + log.error(" AVATARS: Error occured when deleting avatar object: "+ error) + + def minio_delete_object(self,oid): + errors=self.mclient.remove_objects(self.bucket, [DeleteObject(oid)]) + for error in errors: + log.error(" AVATARS: Error occured when deleting avatar object: "+ error) def get_users_without_image(self,users): return [u for u in users if u['id'] and u['id'] not in self.minio_get_objects()] \ No newline at end of file diff --git a/admin/src/admin/lib/events.py b/admin/src/admin/lib/events.py index 7a003d8..63152b1 100644 --- a/admin/src/admin/lib/events.py +++ b/admin/src/admin/lib/events.py @@ -14,11 +14,12 @@ from flask_socketio import SocketIO, emit, join_room, leave_room, \ import base64 class Events(): - def __init__(self,title,text='',total=0): + def __init__(self,title,text='',total=0,table=False): self.eid=str(base64.b64encode(os.urandom(32))[:8]) self.title=title self.text=text self.total=total + self.table=table self.item=0 self.create() @@ -61,12 +62,13 @@ class Events(): def increment(self,data={'name':'','data':[]}): self.item+=1 log.info('INCREMENT '+self.eid+': '+self.text) - app.socketio.emit('notify-update', + app.socketio.emit('notify-increment', json.dumps({'id':self.eid, 'title':self.title, 'text': '['+str(self.item)+'/'+str(self.total)+'] '+self.text+' '+data['name'], 'item':self.item, 'total':self.total, + 'table':self.table, 'data':data}), namespace='/sio', room='admin') @@ -75,12 +77,13 @@ class Events(): def decrement(self,data={'name':'','data':[]}): self.item-=1 log.info('DECREMENT '+self.eid+': '+self.text) - app.socketio.emit('notify-update', + app.socketio.emit('notify-decrement', json.dumps({'id':self.eid, 'title':self.title, 'text': '['+str(self.item)+'/'+str(self.total)+'] '+self.text+' '+data['name'], 'item':self.item, 'total':self.total, + 'table':self.table, 'data':data}), namespace='/sio', room='admin') diff --git a/admin/src/admin/lib/keycloak_client.py b/admin/src/admin/lib/keycloak_client.py index effbff9..65bc058 100644 --- a/admin/src/admin/lib/keycloak_client.py +++ b/admin/src/admin/lib/keycloak_client.py @@ -268,12 +268,12 @@ class KeycloakClient(): ## Add user uid=self.add_user(username,first,last,email,password) ## Add user to role - print('User uid: '+str(uid)+ ' role: '+str(role)) + log.info('User uid: '+str(uid)+ ' role: '+str(role)) try: therole=role[0] except: therole='' - print(self.assign_realm_roles(uid,role)) + log.info(self.assign_realm_roles(uid,role)) ## Create groups in user for g in groups: log.warning('Creating keycloak group: '+g) diff --git a/admin/src/admin/lib/moodle.py b/admin/src/admin/lib/moodle.py index 190d49c..54da5eb 100644 --- a/admin/src/admin/lib/moodle.py +++ b/admin/src/admin/lib/moodle.py @@ -97,7 +97,6 @@ class Moodle(): (headers,users)=self.moodle_pg.select_with_headers(q) users_with_lists = [list(l[:-2])+([[]] if l[-2] == [None] else [list(set(l[-2]))]) + ([[]] if l[-1] == [None] else [list(set(l[-1]))]) for l in users] list_dict_users = [dict(zip(headers, r)) for r in users_with_lists] - pprint(list_dict_users) return list_dict_users ## NOT USED. Too slow diff --git a/admin/src/admin/lib/mysql.py b/admin/src/admin/lib/mysql.py index e901cb1..ede7185 100644 --- a/admin/src/admin/lib/mysql.py +++ b/admin/src/admin/lib/mysql.py @@ -3,7 +3,6 @@ import time from admin import app from datetime import datetime, timedelta -import pprint import logging as log import traceback diff --git a/admin/src/admin/lib/nextcloud.py b/admin/src/admin/lib/nextcloud.py index 80e76f2..c3bab4d 100644 --- a/admin/src/admin/lib/nextcloud.py +++ b/admin/src/admin/lib/nextcloud.py @@ -296,8 +296,6 @@ class Nextcloud(): try: result = json.loads(self._request('GET',url)) if result['ocs']['meta']['statuscode'] == 100: return [g for g in result['ocs']['data']['groups']] - import pprint - pprint.pprint(result) raise ProviderOpError except: log.error(traceback.format_exc()) diff --git a/admin/src/admin/lib/postgres.py b/admin/src/admin/lib/postgres.py index 6c7652b..ef2813f 100644 --- a/admin/src/admin/lib/postgres.py +++ b/admin/src/admin/lib/postgres.py @@ -3,7 +3,6 @@ import time from admin import app from datetime import datetime, timedelta -import pprint import logging as log import traceback diff --git a/admin/src/admin/lib/postup.py b/admin/src/admin/lib/postup.py index b0a8aa7..1d616d5 100644 --- a/admin/src/admin/lib/postup.py +++ b/admin/src/admin/lib/postup.py @@ -3,7 +3,6 @@ import time, os from admin import app from datetime import datetime, timedelta -import pprint import logging as log import traceback diff --git a/admin/src/admin/static/dd.js b/admin/src/admin/static/dd.js index c3652cb..0a083f8 100644 --- a/admin/src/admin/static/dd.js +++ b/admin/src/admin/static/dd.js @@ -292,6 +292,7 @@ function dtUpdateInsertoLD(table, data, append){ } function dtUpdateInsert(table, data, append){ + table=$("#"+table).DataTable() //Quickly appends new data rows. Does not update rows new_id=false if(append == true){ diff --git a/admin/src/admin/static/js/status_socket.js b/admin/src/admin/static/js/status_socket.js index 83cfabb..47c7519 100644 --- a/admin/src/admin/static/js/status_socket.js +++ b/admin/src/admin/static/js/status_socket.js @@ -30,7 +30,7 @@ socket.on('notify-destroy', function(data) { notice[data.id].remove() }); -socket.on('notify-update', function(data) { +socket.on('notify-increment', function(data) { var data = JSON.parse(data); if(!( data.id in notice)){ notice[data.id] = new PNotify({ @@ -43,8 +43,13 @@ socket.on('notify-update', function(data) { notice[data.id].update({ text: data.text }) + if(! data.table == false){ + dtUpdateInsert(data.table,data['data']['data']) + } }); + + // new PNotify({ // title: "Quota for creating desktops full.", // text: "Can't create another desktop, user quota full.", diff --git a/admin/src/admin/static/js/external.js b/admin/src/admin/static/js/sysadmin/external.js similarity index 82% rename from admin/src/admin/static/js/external.js rename to admin/src/admin/static/js/sysadmin/external.js index 9dbf4c7..c63aa30 100644 --- a/admin/src/admin/static/js/external.js +++ b/admin/src/admin/static/js/sysadmin/external.js @@ -36,6 +36,44 @@ $(document).ready(function() { }); }); + $('.btn-clear-upload').on('click', function () { + new PNotify({ + title: 'Cleaning imported data', + text: 'Are you sure you want to clean imported data?', + 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: "DELETE", + url:"/api/external", + 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); + }); + + }); + $('.btn-download').on('click', function () { data=users_table.rows().data() @@ -63,7 +101,7 @@ $(document).ready(function() { success: function(data) { console.log('SUCCESS') - // $("#modalImport").modal('hide'); + $("#modalImport").modal('hide'); // users_table.ajax.reload(); // groups_table.ajax.reload(); }, @@ -137,7 +175,7 @@ $(document).ready(function() { }, "language": { "loadingRecords": 'Loading...', - "emptyTable": "

You don't have any user created yet.


Create one using the +Add new button on top right of this page.

" + "emptyTable": "

No users imported yet.


Import with the Upload button on top right of this page.

" }, "rowId": "id", "deferRender": true, @@ -150,7 +188,7 @@ $(document).ready(function() { "defaultContent": '' }, // { "data": "provider", "width": "10px" }, - // { "data": "id", "width": "10px" }, + { "data": "id", "width": "10px" }, { "data": "username", "width": "10px"}, { "data": "first", "width": "10px"}, { "data": "last", "width": "10px"}, @@ -161,7 +199,13 @@ $(document).ready(function() { ], "order": [[3, 'asc']], "columnDefs": [ { - "targets": 5, + "targets": 1, + "render": function ( data, type, full, meta ) { + return '' + return '' + }}, + { + "targets": 6, "render": function ( data, type, full, meta ) { return "
  • " + full.groups.join("
  • ") + "
  • " }} @@ -176,7 +220,7 @@ $(document).ready(function() { }, "language": { "loadingRecords": 'Loading...', - "emptyTable": "

    You don't have any user created yet.


    Create one using the +Add new button on top right of this page.

    " + "emptyTable": "

    No groups imported yet.

    " }, "rowId": "id", "deferRender": true, diff --git a/admin/src/admin/static/js/sysadmin/users.js b/admin/src/admin/static/js/sysadmin/users.js index eebe59a..4e68e58 100644 --- a/admin/src/admin/static/js/sysadmin/users.js +++ b/admin/src/admin/static/js/sysadmin/users.js @@ -97,58 +97,121 @@ $(document).ready(function() { }); $('.btn-delete_keycloak').on('click', function () { - $.ajax({ - type: "DELETE", - url:"/api/users/keycloak", - success: function(data) - { - console.log('SUCCESS') - // $("#modalImport").modal('hide'); - // users_table.ajax.reload(); - // groups_table.ajax.reload(); + new PNotify({ + title: 'Confirmation Needed', + text: "Are you sure you want to DELETE ALL USERS IN KEYCLOAK???", + hide: false, + opacity: 0.9, + confirm: { + confirm: true }, - error: function(data) - { - alert('Something went wrong on our side...') - } + buttons: { + closer: false, + sticker: false + }, + history: { + history: false + }, + addclass: 'pnotify-center' + }).get().on('pnotify.confirm', function() { + console.log('Updating user password...') + $.ajax({ + type: "DELETE", + url:"/api/users/keycloak", + 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...') + } + }); + }).on('pnotify.cancel', function() { }); + + }); $('.btn-delete_nextcloud').on('click', function () { - $.ajax({ - type: "DELETE", - url:"/api/users/nextcloud", - success: function(data) - { - console.log('SUCCESS') - // $("#modalImport").modal('hide'); - // users_table.ajax.reload(); - // groups_table.ajax.reload(); + new PNotify({ + title: 'Confirmation Needed', + text: "Are you sure you want to DELETE ALL USERS IN NEXTCLOUD?", + hide: false, + opacity: 0.9, + confirm: { + confirm: true }, - error: function(data) - { - alert('Something went wrong on our side...') - } + buttons: { + closer: false, + sticker: false + }, + history: { + history: false + }, + addclass: 'pnotify-center' + }).get().on('pnotify.confirm', function() { + console.log('Updating user password...') + $.ajax({ + type: "DELETE", + url:"/api/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...') + } + }); + }).on('pnotify.cancel', function() { }); }); $('.btn-delete_moodle').on('click', function () { - $.ajax({ - type: "DELETE", - url:"/api/users/moodle", - success: function(data) - { - console.log('SUCCESS') - // $("#modalImport").modal('hide'); - // users_table.ajax.reload(); - // groups_table.ajax.reload(); + new PNotify({ + title: 'Confirmation Needed', + text: "Are you sure you want to DELETE ALL USERS IN MOODLE?", + hide: false, + opacity: 0.9, + confirm: { + confirm: true }, - error: function(data) - { - alert('Something went wrong on our side...') - } + buttons: { + closer: false, + sticker: false + }, + history: { + history: false + }, + addclass: 'pnotify-center' + }).get().on('pnotify.confirm', function() { + console.log('Updating user password...') + $.ajax({ + type: "DELETE", + url:"/api/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...') + } + }); + }).on('pnotify.cancel', function() { }); }); + $('.btn-sync_to_moodle').on('click', function () { $.ajax({ type: "POST", diff --git a/admin/src/admin/static/js/users.js b/admin/src/admin/static/js/users.js index 60ea880..b0509a8 100644 --- a/admin/src/admin/static/js/users.js +++ b/admin/src/admin/static/js/users.js @@ -77,9 +77,6 @@ $(document).ready(function() { success: function(data) { table.ajax.reload(); - // $("#modalImport").modal('hide'); - // users_table.ajax.reload(); - // groups_table.ajax.reload(); }, error: function(data) { @@ -117,95 +114,6 @@ $(document).ready(function() { // }); }); - $('.btn-delete_keycloak').on('click', function () { - $.ajax({ - type: "DELETE", - url:"/api/users/keycloak", - 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_nextcloud').on('click', function () { - $.ajax({ - type: "DELETE", - url:"/api/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:"/api/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", - url:"/api/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_nextcloud').on('click', function () { - $.ajax({ - type: "POST", - url:"/api/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...') - } - }); - }); - //DataTable Main renderer var table = $('#users').DataTable({ "ajax": { @@ -250,7 +158,7 @@ $(document).ready(function() { "targets": 1, "render": function ( data, type, full, meta ) { // return '' - return '' + return '' }}, { "targets": 2, diff --git a/admin/src/admin/static/templates/header.html b/admin/src/admin/static/templates/header.html index 30b13af..c40be62 100644 --- a/admin/src/admin/static/templates/header.html +++ b/admin/src/admin/static/templates/header.html @@ -16,7 +16,7 @@ -
    @@ -41,6 +42,7 @@ + Avatar Username First Last @@ -83,5 +85,5 @@ - + {% endblock %} diff --git a/admin/src/admin/static/templates/pages/sysadmin/users.html b/admin/src/admin/static/templates/pages/sysadmin/users.html index 4304c00..80eb6f2 100644 --- a/admin/src/admin/static/templates/pages/sysadmin/users.html +++ b/admin/src/admin/static/templates/pages/sysadmin/users.html @@ -27,7 +27,7 @@ - {% if current_user.role =='sysadmin' %} + {% if current_user.role =='admin' %} diff --git a/admin/src/admin/static/templates/pages/users.html b/admin/src/admin/static/templates/pages/users.html index f2841ba..286d826 100644 --- a/admin/src/admin/static/templates/pages/users.html +++ b/admin/src/admin/static/templates/pages/users.html @@ -21,23 +21,6 @@
    - {% if current_user.role =='admin' %} - - - - - - {% endif %} diff --git a/admin/src/admin/views/ApiViews.py b/admin/src/admin/views/ApiViews.py index bfbb4e1..e11a7ac 100644 --- a/admin/src/admin/views/ApiViews.py +++ b/admin/src/admin/views/ApiViews.py @@ -103,7 +103,7 @@ def groups(provider=False): ### SYSADM USERS ONLY -@app.route('/api/external', methods=['POST', 'PUT', 'GET']) +@app.route('/api/external', methods=['POST', 'PUT', 'GET','DELETE']) @login_required def external(): if 'external' in threads.keys(): @@ -112,8 +112,8 @@ def external(): else: threads['external']=None - data=request.get_json(force=True) if request.method == 'POST': + data=request.get_json(force=True) if data['format']=='json-ga': threads['external'] = threading.Thread(target=app.admin.upload_json_ga, args=(data,)) threads['external'].start() @@ -123,9 +123,14 @@ def external(): threads['external'].start() return json.dumps({}), 200, {'Content-Type': 'application/json'} if request.method == 'PUT': + data=request.get_json(force=True) threads['external'] = threading.Thread(target=app.admin.sync_external, args=(data,)) threads['external'].start() return json.dumps({}), 200, {'Content-Type': 'application/json'} + if request.method == 'DELETE': + print('RESET') + app.admin.reset_external() + return json.dumps({}), 200, {'Content-Type': 'application/json'} return json.dumps({}), 500, {'Content-Type': 'application/json'} @app.route('/api/external/users')