Fixed avatars on deleting and UI things

root 2021-06-07 03:02:59 +02:00
parent fab77bc09e
commit 09ae3e16e6
19 changed files with 218 additions and 185 deletions

View File

@ -78,9 +78,9 @@ class Admin():
'groups':[], 'groups':[],
'roles':[]} 'roles':[]}
log.warning(' Updating missing user avatars with defaults') 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.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') log.warning(' SYSTEM READY TO HANDLE CONNECTIONS')
## This function should be moved to postup.py ## This function should be moved to postup.py
@ -457,21 +457,28 @@ class Admin():
def get_dice_pwd(self): def get_dice_pwd(self):
return diceware.get_passphrase(options=options) return diceware.get_passphrase(options=options)
def reset_external(self):
self.external={'users':[],
'groups':[],
'roles':[]}
return True
def upload_json_ga(self,data): def upload_json_ga(self,data):
groups=[] groups=[]
log.warning('Processing uploaded groups...') log.warning('Processing uploaded groups...')
try: 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: except:
log.error(traceback.format_exc()) log.error(traceback.format_exc())
for g in data['data']['groups']: for g in data['data']['groups']:
try: try:
ev.increment({'name':g['name'],'data':g}) group={'provider':'external',
groups.append({'provider':'external',
"id": g['id'], "id": g['id'],
"mailid": g['email'].split('@')[0], "mailid": g['email'].split('@')[0],
"name": g['name'], "name": g['name'],
"description": g['description']}) "description": g['description']}
ev.increment({'name':g['name'],'data':group})
groups.append(group)
except: except:
pass pass
self.external['groups']=groups self.external['groups']=groups
@ -480,7 +487,7 @@ class Admin():
users=[] users=[]
total=len(data['data']['users']) total=len(data['data']['users'])
item=1 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']: for u in data['data']['users']:
log.warning('Processing ('+str(item)+'/'+str(total)+') uploaded user: '+u['primaryEmail'].split('@')[0]) log.warning('Processing ('+str(item)+'/'+str(total)+') uploaded user: '+u['primaryEmail'].split('@')[0])
new_user={'provider':'external', new_user={'provider':'external',
@ -491,7 +498,7 @@ class Admin():
'username': u['primaryEmail'].split('@')[0], 'username': u['primaryEmail'].split('@')[0],
'groups':[u['orgUnitPath']], ## WARNING: Removing the first 'groups':[u['orgUnitPath']], ## WARNING: Removing the first
'roles':[], 'roles':[],
'password': diceware.get_passphrase(options=options)} 'password': self.get_dice_pwd()}
users.append(new_user) users.append(new_user)
item+=1 item+=1
ev.increment({'name':u['primaryEmail'].split('@')[0],'data':new_user}) 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']) log.warning(' KEYCLOAK USERS: Adding user ('+str(index)+'/'+str(total)+'): '+u['username'])
ev.increment({'name':u['username'],'data':u}) ev.increment({'name':u['username'],'data':u})
uid=self.keycloak.add_user(u['username'],u['first'],u['last'],u['email'],u['password']) 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 # Add user to role and group rolename
if len(u['roles']) != 0: if len(u['roles']) != 0:
log.warning(' KEYCLOAK USERS: Assign user '+u['username']+' with initial pwd '+ u['password']+' to role '+u['roles'][0]) log.warning(' KEYCLOAK USERS: Assign user '+u['username']+' with initial pwd '+ u['password']+' to role '+u['roles'][0])
@ -687,6 +694,8 @@ class Admin():
log.error(traceback.format_exc()) log.error(traceback.format_exc())
log.warning('Could not remove users: '+user['username']) log.warning('Could not remove users: '+user['username'])
self.av.delete_user_avatar(userid)
def delete_keycloak_users(self): def delete_keycloak_users(self):
total=len(self.internal['users']) total=len(self.internal['users'])
i=0 i=0
@ -702,6 +711,7 @@ class Admin():
self.keycloak.delete_user(u['id']) self.keycloak.delete_user(u['id'])
except: except:
log.warning(' KEYCLOAK USERS: Could not remove user: '+u['username'] +'. Probably already not exists.') 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): def delete_nextcloud_user(self,userid):
user=[u for u in self.internal['users'] if u['id']==userid] user=[u for u in self.internal['users'] if u['id']==userid]

View File

@ -21,6 +21,16 @@ class Avatars():
self._minio_set_realm() self._minio_set_realm()
# self.update_missing_avatars() # 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): def update_missing_avatars(self,users):
sys_roles=['admin','manager','teacher','student'] sys_roles=['admin','manager','teacher','student']
for u in self.get_users_without_image(users): 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) errors=self.mclient.remove_objects(self.bucket, delete_object_list)
for error in errors: 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): 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()] return [u for u in users if u['id'] and u['id'] not in self.minio_get_objects()]

View File

@ -14,11 +14,12 @@ from flask_socketio import SocketIO, emit, join_room, leave_room, \
import base64 import base64
class Events(): 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.eid=str(base64.b64encode(os.urandom(32))[:8])
self.title=title self.title=title
self.text=text self.text=text
self.total=total self.total=total
self.table=table
self.item=0 self.item=0
self.create() self.create()
@ -61,12 +62,13 @@ class Events():
def increment(self,data={'name':'','data':[]}): def increment(self,data={'name':'','data':[]}):
self.item+=1 self.item+=1
log.info('INCREMENT '+self.eid+': '+self.text) log.info('INCREMENT '+self.eid+': '+self.text)
app.socketio.emit('notify-update', app.socketio.emit('notify-increment',
json.dumps({'id':self.eid, json.dumps({'id':self.eid,
'title':self.title, 'title':self.title,
'text': '['+str(self.item)+'/'+str(self.total)+'] '+self.text+' '+data['name'], 'text': '['+str(self.item)+'/'+str(self.total)+'] '+self.text+' '+data['name'],
'item':self.item, 'item':self.item,
'total':self.total, 'total':self.total,
'table':self.table,
'data':data}), 'data':data}),
namespace='/sio', namespace='/sio',
room='admin') room='admin')
@ -75,12 +77,13 @@ class Events():
def decrement(self,data={'name':'','data':[]}): def decrement(self,data={'name':'','data':[]}):
self.item-=1 self.item-=1
log.info('DECREMENT '+self.eid+': '+self.text) log.info('DECREMENT '+self.eid+': '+self.text)
app.socketio.emit('notify-update', app.socketio.emit('notify-decrement',
json.dumps({'id':self.eid, json.dumps({'id':self.eid,
'title':self.title, 'title':self.title,
'text': '['+str(self.item)+'/'+str(self.total)+'] '+self.text+' '+data['name'], 'text': '['+str(self.item)+'/'+str(self.total)+'] '+self.text+' '+data['name'],
'item':self.item, 'item':self.item,
'total':self.total, 'total':self.total,
'table':self.table,
'data':data}), 'data':data}),
namespace='/sio', namespace='/sio',
room='admin') room='admin')

View File

@ -268,12 +268,12 @@ class KeycloakClient():
## Add user ## Add user
uid=self.add_user(username,first,last,email,password) uid=self.add_user(username,first,last,email,password)
## Add user to role ## Add user to role
print('User uid: '+str(uid)+ ' role: '+str(role)) log.info('User uid: '+str(uid)+ ' role: '+str(role))
try: try:
therole=role[0] therole=role[0]
except: except:
therole='' therole=''
print(self.assign_realm_roles(uid,role)) log.info(self.assign_realm_roles(uid,role))
## Create groups in user ## Create groups in user
for g in groups: for g in groups:
log.warning('Creating keycloak group: '+g) log.warning('Creating keycloak group: '+g)

View File

@ -97,7 +97,6 @@ class Moodle():
(headers,users)=self.moodle_pg.select_with_headers(q) (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] 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] list_dict_users = [dict(zip(headers, r)) for r in users_with_lists]
pprint(list_dict_users)
return list_dict_users return list_dict_users
## NOT USED. Too slow ## NOT USED. Too slow

View File

@ -3,7 +3,6 @@
import time import time
from admin import app from admin import app
from datetime import datetime, timedelta from datetime import datetime, timedelta
import pprint
import logging as log import logging as log
import traceback import traceback

View File

@ -296,8 +296,6 @@ class Nextcloud():
try: try:
result = json.loads(self._request('GET',url)) result = json.loads(self._request('GET',url))
if result['ocs']['meta']['statuscode'] == 100: return [g for g in result['ocs']['data']['groups']] if result['ocs']['meta']['statuscode'] == 100: return [g for g in result['ocs']['data']['groups']]
import pprint
pprint.pprint(result)
raise ProviderOpError raise ProviderOpError
except: except:
log.error(traceback.format_exc()) log.error(traceback.format_exc())

View File

@ -3,7 +3,6 @@
import time import time
from admin import app from admin import app
from datetime import datetime, timedelta from datetime import datetime, timedelta
import pprint
import logging as log import logging as log
import traceback import traceback

View File

@ -3,7 +3,6 @@
import time, os import time, os
from admin import app from admin import app
from datetime import datetime, timedelta from datetime import datetime, timedelta
import pprint
import logging as log import logging as log
import traceback import traceback

View File

@ -292,6 +292,7 @@ function dtUpdateInsertoLD(table, data, append){
} }
function dtUpdateInsert(table, data, append){ function dtUpdateInsert(table, data, append){
table=$("#"+table).DataTable()
//Quickly appends new data rows. Does not update rows //Quickly appends new data rows. Does not update rows
new_id=false new_id=false
if(append == true){ if(append == true){

View File

@ -30,7 +30,7 @@ socket.on('notify-destroy', function(data) {
notice[data.id].remove() notice[data.id].remove()
}); });
socket.on('notify-update', function(data) { socket.on('notify-increment', function(data) {
var data = JSON.parse(data); var data = JSON.parse(data);
if(!( data.id in notice)){ if(!( data.id in notice)){
notice[data.id] = new PNotify({ notice[data.id] = new PNotify({
@ -43,8 +43,13 @@ socket.on('notify-update', function(data) {
notice[data.id].update({ notice[data.id].update({
text: data.text text: data.text
}) })
if(! data.table == false){
dtUpdateInsert(data.table,data['data']['data'])
}
}); });
// new PNotify({ // new PNotify({
// title: "Quota for creating desktops full.", // title: "Quota for creating desktops full.",
// text: "Can't create another desktop, user quota full.", // text: "Can't create another desktop, user quota full.",

View File

@ -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 () { $('.btn-download').on('click', function () {
data=users_table.rows().data() data=users_table.rows().data()
@ -63,7 +101,7 @@ $(document).ready(function() {
success: function(data) success: function(data)
{ {
console.log('SUCCESS') console.log('SUCCESS')
// $("#modalImport").modal('hide'); $("#modalImport").modal('hide');
// users_table.ajax.reload(); // users_table.ajax.reload();
// groups_table.ajax.reload(); // groups_table.ajax.reload();
}, },
@ -137,7 +175,7 @@ $(document).ready(function() {
}, },
"language": { "language": {
"loadingRecords": '<i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i><span class="sr-only">Loading...</span>', "loadingRecords": '<i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i><span class="sr-only">Loading...</span>',
"emptyTable": "<h1>You don't have any user created yet.</h1><br><h2>Create one using the +Add new button on top right of this page.</h2>" "emptyTable": "<h2>No users imported yet.</h2><br><h2>Import with the Upload button on top right of this page.</h2>"
}, },
"rowId": "id", "rowId": "id",
"deferRender": true, "deferRender": true,
@ -150,7 +188,7 @@ $(document).ready(function() {
"defaultContent": '<button class="btn btn-xs btn-info" type="button" data-placement="top" ><i class="fa fa-plus"></i></button>' "defaultContent": '<button class="btn btn-xs btn-info" type="button" data-placement="top" ><i class="fa fa-plus"></i></button>'
}, },
// { "data": "provider", "width": "10px" }, // { "data": "provider", "width": "10px" },
// { "data": "id", "width": "10px" }, { "data": "id", "width": "10px" },
{ "data": "username", "width": "10px"}, { "data": "username", "width": "10px"},
{ "data": "first", "width": "10px"}, { "data": "first", "width": "10px"},
{ "data": "last", "width": "10px"}, { "data": "last", "width": "10px"},
@ -161,7 +199,13 @@ $(document).ready(function() {
], ],
"order": [[3, 'asc']], "order": [[3, 'asc']],
"columnDefs": [ { "columnDefs": [ {
"targets": 5, "targets": 1,
"render": function ( data, type, full, meta ) {
return '<img src="/custom/avatars/'+full.roles+'.jpg" title="'+full.id+'" width="25" height="25" onerror="if (this.src != \'/static/img/missing.jpg\') this.src = \'/static/img/missing.jpg\';">'
return '<img src="/avatar/'+full.id+'" title="'+full.id+'" width="25" height="25">'
}},
{
"targets": 6,
"render": function ( data, type, full, meta ) { "render": function ( data, type, full, meta ) {
return "<li>" + full.groups.join("</li><li>") + "</li>" return "<li>" + full.groups.join("</li><li>") + "</li>"
}} }}
@ -176,7 +220,7 @@ $(document).ready(function() {
}, },
"language": { "language": {
"loadingRecords": '<i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i><span class="sr-only">Loading...</span>', "loadingRecords": '<i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i><span class="sr-only">Loading...</span>',
"emptyTable": "<h1>You don't have any user created yet.</h1><br><h2>Create one using the +Add new button on top right of this page.</h2>" "emptyTable": "<h2>No groups imported yet.</h2>"
}, },
"rowId": "id", "rowId": "id",
"deferRender": true, "deferRender": true,

View File

@ -97,6 +97,24 @@ $(document).ready(function() {
}); });
$('.btn-delete_keycloak').on('click', function () { $('.btn-delete_keycloak').on('click', function () {
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
},
buttons: {
closer: false,
sticker: false
},
history: {
history: false
},
addclass: 'pnotify-center'
}).get().on('pnotify.confirm', function() {
console.log('Updating user password...')
$.ajax({ $.ajax({
type: "DELETE", type: "DELETE",
url:"/api/users/keycloak", url:"/api/users/keycloak",
@ -112,9 +130,31 @@ $(document).ready(function() {
alert('Something went wrong on our side...') alert('Something went wrong on our side...')
} }
}); });
}).on('pnotify.cancel', function() {
});
}); });
$('.btn-delete_nextcloud').on('click', function () { $('.btn-delete_nextcloud').on('click', function () {
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
},
buttons: {
closer: false,
sticker: false
},
history: {
history: false
},
addclass: 'pnotify-center'
}).get().on('pnotify.confirm', function() {
console.log('Updating user password...')
$.ajax({ $.ajax({
type: "DELETE", type: "DELETE",
url:"/api/users/nextcloud", url:"/api/users/nextcloud",
@ -130,9 +170,29 @@ $(document).ready(function() {
alert('Something went wrong on our side...') alert('Something went wrong on our side...')
} }
}); });
}).on('pnotify.cancel', function() {
});
}); });
$('.btn-delete_moodle').on('click', function () { $('.btn-delete_moodle').on('click', function () {
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
},
buttons: {
closer: false,
sticker: false
},
history: {
history: false
},
addclass: 'pnotify-center'
}).get().on('pnotify.confirm', function() {
console.log('Updating user password...')
$.ajax({ $.ajax({
type: "DELETE", type: "DELETE",
url:"/api/users/moodle", url:"/api/users/moodle",
@ -148,7 +208,10 @@ $(document).ready(function() {
alert('Something went wrong on our side...') alert('Something went wrong on our side...')
} }
}); });
}).on('pnotify.cancel', function() {
}); });
});
$('.btn-sync_to_moodle').on('click', function () { $('.btn-sync_to_moodle').on('click', function () {
$.ajax({ $.ajax({
type: "POST", type: "POST",

View File

@ -77,9 +77,6 @@ $(document).ready(function() {
success: function(data) success: function(data)
{ {
table.ajax.reload(); table.ajax.reload();
// $("#modalImport").modal('hide');
// users_table.ajax.reload();
// groups_table.ajax.reload();
}, },
error: function(data) 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 //DataTable Main renderer
var table = $('#users').DataTable({ var table = $('#users').DataTable({
"ajax": { "ajax": {
@ -250,7 +158,7 @@ $(document).ready(function() {
"targets": 1, "targets": 1,
"render": function ( data, type, full, meta ) { "render": function ( data, type, full, meta ) {
// return '<object data="/static/img/missing.jpg" type="image/jpeg" width="25" height="25"><img src="/avatar/'+full.id+'" title="'+full.id+'" width="25" height="25"></object>' // return '<object data="/static/img/missing.jpg" type="image/jpeg" width="25" height="25"><img src="/avatar/'+full.id+'" title="'+full.id+'" width="25" height="25"></object>'
return '<img src="/avatar/'+full.id+'" title="'+full.id+'" width="25" height="25">' return '<img src="/avatar/'+full.id+'" title="'+full.id+'" width="25" height="25" onerror="if (this.src != \'/static/img/missing.jpg\') this.src = \'/static/img/missing.jpg\';">'
}}, }},
{ {
"targets": 2, "targets": 2,

View File

@ -16,7 +16,7 @@
</ul> </ul>
</li> </li>
<li role="presentation" class="sync-status"> <!-- <li role="presentation" class="sync-status">
<a href="javascript:" class="dropdown-toggle info-number" data-toggle="dropdown" aria-expanded="false"> <a href="javascript:" class="dropdown-toggle info-number" data-toggle="dropdown" aria-expanded="false">
<i class="fa fa-spinner"></i> <i class="fa fa-spinner"></i>
<span class="badge"></span> <span class="badge"></span>
@ -45,7 +45,7 @@
</a> </a>
</li> </li>
</ul> </ul>
</li> </li> -->
</ul> </ul>
</nav> </nav>
</div> </div>

View File

@ -31,6 +31,7 @@
<a class="btn-sync"><span style="color: #5499c7; "><i class="fa fa-rocket"></i> Sync to system</span></a> <a class="btn-sync"><span style="color: #5499c7; "><i class="fa fa-rocket"></i> Sync to system</span></a>
<a class="btn-upload"><span style="color: #5499c7; "><i class="fa fa-upload"></i> Upload</span></a> <a class="btn-upload"><span style="color: #5499c7; "><i class="fa fa-upload"></i> Upload</span></a>
<a class="btn-download"><span style="color: #5499c7; "><i class="fa fa-download"></i> Download</span></a> <a class="btn-download"><span style="color: #5499c7; "><i class="fa fa-download"></i> Download</span></a>
<a class="btn-clear-upload"><span style="color: #5499c7; "><i class="fa fa-cross"></i> Clear upload</span></a>
</li> </li>
</ul> </ul>
<div class="clearfix"></div> <div class="clearfix"></div>
@ -41,6 +42,7 @@
<thead> <thead>
<tr> <tr>
<th></th> <th></th>
<th>Avatar</th>
<th>Username</th> <th>Username</th>
<th>First</th> <th>First</th>
<th>Last</th> <th>Last</th>
@ -83,5 +85,5 @@
<!-- Switchery --> <!-- Switchery -->
<script src="/vendors/switchery/dist/switchery.min.js"></script> <script src="/vendors/switchery/dist/switchery.min.js"></script>
<!-- Desktops sse & modals --> <!-- Desktops sse & modals -->
<script src="/static/js/external.js"></script> <script src="/static/js/sysadmin/external.js"></script>
{% endblock %} {% endblock %}

View File

@ -27,7 +27,7 @@
<button class="btn btn-primary btn-xs btn-sync_to_moodle"> <button class="btn btn-primary btn-xs btn-sync_to_moodle">
<i class="fa fa-refresh" aria-hidden="true"></i> Sync to Moodle <i class="fa fa-refresh" aria-hidden="true"></i> Sync to Moodle
</button> </button>
{% if current_user.role =='sysadmin' %} {% if current_user.role =='admin' %}
<button class="btn btn-danger btn-xs btn-delete_keycloak"> <button class="btn btn-danger btn-xs btn-delete_keycloak">
<i class="fa fa-trash"></i> Delete all keycloak <i class="fa fa-trash"></i> Delete all keycloak
</button> </button>

View File

@ -21,23 +21,6 @@
<div class="clearfix"></div> <div class="clearfix"></div>
</div> </div>
<div class="x_content"> <div class="x_content">
{% if current_user.role =='admin' %}
<button class="btn btn-primary btn-xs btn-sync_to_nextcloud">
<i class="fa fa-refresh" aria-hidden="true"></i> Sync to Nextcloud
</button>
<button class="btn btn-primary btn-xs btn-sync_to_moodle">
<i class="fa fa-refresh" aria-hidden="true"></i> Sync to Moodle
</button>
<button class="btn btn-danger btn-xs btn-delete_keycloak">
<i class="fa fa-trash"></i> Delete all keycloak
</button>
<button class="btn btn-danger btn-xs btn-delete_nextcloud">
<i class="fa fa-trash"></i> Delete missing keycloak in nextcloud
</button>
<button class="btn btn-danger btn-xs btn-delete_moodle">
<i class="fa fa-trash"></i> Delete missing keycloak in moodle
</button>
{% endif %}
<table id="users" class="table" width="100%"> <table id="users" class="table" width="100%">
<thead> <thead>
<tr> <tr>

View File

@ -103,7 +103,7 @@ def groups(provider=False):
### SYSADM USERS ONLY ### SYSADM USERS ONLY
@app.route('/api/external', methods=['POST', 'PUT', 'GET']) @app.route('/api/external', methods=['POST', 'PUT', 'GET','DELETE'])
@login_required @login_required
def external(): def external():
if 'external' in threads.keys(): if 'external' in threads.keys():
@ -112,8 +112,8 @@ def external():
else: else:
threads['external']=None threads['external']=None
data=request.get_json(force=True)
if request.method == 'POST': if request.method == 'POST':
data=request.get_json(force=True)
if data['format']=='json-ga': if data['format']=='json-ga':
threads['external'] = threading.Thread(target=app.admin.upload_json_ga, args=(data,)) threads['external'] = threading.Thread(target=app.admin.upload_json_ga, args=(data,))
threads['external'].start() threads['external'].start()
@ -123,9 +123,14 @@ def external():
threads['external'].start() threads['external'].start()
return json.dumps({}), 200, {'Content-Type': 'application/json'} return json.dumps({}), 200, {'Content-Type': 'application/json'}
if request.method == 'PUT': if request.method == 'PUT':
data=request.get_json(force=True)
threads['external'] = threading.Thread(target=app.admin.sync_external, args=(data,)) threads['external'] = threading.Thread(target=app.admin.sync_external, args=(data,))
threads['external'].start() threads['external'].start()
return json.dumps({}), 200, {'Content-Type': 'application/json'} 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'} return json.dumps({}), 500, {'Content-Type': 'application/json'}
@app.route('/api/external/users') @app.route('/api/external/users')