added csv and gevents

root 2021-06-03 00:20:20 +02:00
parent a41d563f5f
commit 29b7bdef1d
12 changed files with 419 additions and 116 deletions

View File

@ -18,12 +18,12 @@ options = diceware.handle_options(None)
options.wordlist = 'cat_ascii' options.wordlist = 'cat_ascii'
options.num = 3 options.num = 3
from .events import Events
# from flask_socketio import SocketIO, emit, join_room, leave_room, \
from flask_socketio import SocketIO, emit, join_room, leave_room, \ # close_room, rooms, disconnect, send
close_room, rooms, disconnect, send # socketio = SocketIO(app)
socketio = SocketIO(app) # from ..views.Socketio import socketio
from ..views.Socketio import socketio
# socketio = SocketIO(app) # socketio = SocketIO(app)
class Admin(): class Admin():
@ -465,26 +465,76 @@ class Admin():
def get_external_roles(self): def get_external_roles(self):
return self.external['roles'] return self.external['roles']
def upload_json(self,data): def upload_csv_ug(self,data):
log.warning('Processing uploaded users...')
users=[]
total=len(data['data'])
item=1
ev=Events('Processing uploaded users',total=len(data['data']))
groups=[]
for u in data['data']:
log.warning('Processing ('+str(item)+'/'+str(total)+') uploaded user: '+u['username'])
user_groups=["/" + g.strip() for g in u['groups'].split(',')]
groups=groups+user_groups
users.append({'provider':'external',
'id':u['id'].strip(),
'email': u['email'].strip(),
'first': u['firstname'].strip(),
'last': u['lastname'].strip(),
'username': u['username'].strip(),
'groups':user_groups,
'roles':[u['role'].strip()],
'password':diceware.get_passphrase(options=options)})
item+=1
ev.increment({'name':u['username'].split('@')[0]})
self.external['users']=users
groups=list(dict.fromkeys(groups))
sysgroups=[]
for g in groups:
sysgroups.append({'provider':'external',
"id": g,
"mailid": g,
"name": g,
"description": 'Imported with csv'})
self.external['groups']=sysgroups
return True
def upload_json_ga(self,data):
groups=[] groups=[]
log.warning('Processing uploaded groups...') log.warning('Processing uploaded groups...')
ev=Events('Processing uploaded groups',total=len(data['data']['groups']))
for g in data['data']['groups']: for g in data['data']['groups']:
# for m in data['data']['d_members']: try:
ev.increment({'name':g['name']})
# data['provider'] groups.append({'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']}) except:
pass
self.external['groups']=groups self.external['groups']=groups
log.warning('Processing uploaded users...') log.warning('Processing uploaded users...')
users=[] users=[]
total=len(data['data']['users']) total=len(data['data']['users'])
i=1 item=1
ev=Events('Processing uploaded users',total=len(data['data']['users']))
for u in data['data']['users']: for u in data['data']['users']:
log.warning('Processing ('+str(i)+'/'+str(total)+') uploaded user: '+u['primaryEmail'].split('@')[0]) log.warning('Processing ('+str(item)+'/'+str(total)+') uploaded user: '+u['primaryEmail'].split('@')[0])
# self.e.send({'event':'progress',
# 'id':u['id'],
# 'item':'user',
# 'action':'passwdgen',
# 'name':u['primaryEmail'].split('@')[0],
# 'progress':str(item)+'/'+str(total),
# 'status':True,
# 'msg':'Generating password',
# 'payload':None})
# data['provider'] # data['provider']
users.append({'provider':'external', users.append({'provider':'external',
'id':u['id'], 'id':u['id'],
@ -494,12 +544,14 @@ 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': diceware.get_passphrase(options=options)})
socketio.emit('update', # app.socketio.emit('update',
json.dumps({'status':True,'item':'user','action':'delete','itemdata':''}), # json.dumps({'status':True,'item':'user','action':'delete','itemdata':''}),
namespace='/isard-sso-admin/sio', # namespace='/isard-sso-admin/sio',
room='admin') # room='admin')
i=i+1 # sleep(0)
item+=1
ev.increment({'name':u['primaryEmail'].split('@')[0]})
self.external['users']=users self.external['users']=users
## Add groups to users (now they only have their orgUnitPath) ## Add groups to users (now they only have their orgUnitPath)
@ -520,6 +572,7 @@ class Admin():
# log.warning('All syncs finished') # log.warning('All syncs finished')
def sync_to_keycloak(self): ### This one works from the external, moodle and nextcloud from the internal def sync_to_keycloak(self): ### This one works from the external, moodle and nextcloud from the internal
groups=[] groups=[]
for u in self.external['users']: for u in self.external['users']:
groups=groups+u['groups'] groups=groups+u['groups']
@ -527,18 +580,22 @@ class Admin():
total=len(groups) total=len(groups)
i=0 i=0
ev=Events('Syncing import groups to keycloak',total=len(groups))
for g in groups: for g in groups:
i=i+1 i=i+1
# print('ADDING FULL PATH: '+str(g)) # print('ADDING FULL PATH: '+str(g))
log.warning(' KEYCLOAK GROUPS: Adding group ('+str(i)+'/'+str(total)+'): '+g) log.warning(' KEYCLOAK GROUPS: Adding group ('+str(i)+'/'+str(total)+'): '+g)
ev.increment({'name':g})
self.keycloak.add_group_tree(g) self.keycloak.add_group_tree(g)
total=len(self.external['users']) total=len(self.external['users'])
index=0 index=0
ev=Events('Syncing import users to keycloak',total=len(self.external['users']))
for u in self.external['users']: for u in self.external['users']:
index=index+1 index=index+1
# Add user # Add user
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']})
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'])
# Add user to role and group rolename # Add user to role and group rolename
@ -573,12 +630,14 @@ class Admin():
### Create all groups. Skip / in system groups ### Create all groups. Skip / in system groups
total=len(groups) total=len(groups)
i=0 i=0
ev=Events('Syncing groups from keycloak to moodle',total=len(groups))
for g in groups: for g in groups:
parts=g.split('/') parts=g.split('/')
subpath='' subpath=''
for i in range(1,len(parts)): for i in range(1,len(parts)):
try: try:
log.warning(' MOODLE GROUPS: Adding group as cohort ('+str(i)+'/'+str(total)+'): '+subpath) log.warning(' MOODLE GROUPS: Adding group as cohort ('+str(i)+'/'+str(total)+'): '+subpath)
ev.increment({'name':subpath})
if parts[i] in ['admin','manager','teacher','student']: if parts[i] in ['admin','manager','teacher','student']:
subpath=parts[i] subpath=parts[i]
else: else:
@ -592,19 +651,28 @@ class Admin():
cohorts=self.moodle.get_cohorts() cohorts=self.moodle.get_cohorts()
### Create users in moodle ### Create users in moodle
ev=Events('Syncing users from keycloak to moodle',total=len(self.internal['users']))
for u in self.internal['users']: for u in self.internal['users']:
if not u['moodle']: if not u['moodle']:
log.error('Creating moodle user: '+u['username']) log.warning('Creating moodle user: '+u['username'])
user=self.moodle.create_user(u['email'],u['username'],'1Random 1String',u['first'],u['last'])[0] ev.increment({'name':u['username']})
if u['first'] == '': u['first']=' '
if u['last'] == '': u['last']=' '
try:
# pprint(u)
pprint(self.moodle.create_user(u['email'],u['username'],'1Random 1String',u['first'],u['last'])[0])
except:
log.error(' -->> Error creating on moodle the user: '+u['username'])
# user_id=user['id'] # user_id=user['id']
self.resync_data() self.resync_data()
### Add user to their cohorts (groups) ### Add user to their cohorts (groups)
ev=Events('Syncing users groups from keycloak to moodle cohorts',total=len(self.internal['users']))
for u in self.internal['users']: for u in self.internal['users']:
total=len(u['keycloak_groups']) total=len(u['keycloak_groups'])
index=0 index=0
ev.increment({'name':u['username']})
for g in u['keycloak_groups']: for g in u['keycloak_groups']:
log.error('for user groups')
parts=g.split('/') parts=g.split('/')
subpath='' subpath=''
# pprint(parts) # pprint(parts)
@ -640,18 +708,21 @@ class Admin():
total=len(groups) total=len(groups)
i=0 i=0
ev=Events('Syncing groups from keycloak to nextcloud',total=len(groups))
for g in groups: for g in groups:
parts=g.split('/') parts=g.split('/')
subpath='' subpath=''
for i in range(1,len(parts)): for i in range(1,len(parts)):
try: try:
log.warning(' NEXTCLOUD GROUPS: Adding group ('+str(i)+'/'+str(total)+'): '+subpath) log.warning(' NEXTCLOUD GROUPS: Adding group ('+str(i)+'/'+str(total)+'): '+subpath)
ev.increment({'name':subpath})
subpath=subpath+'/'+parts[i] subpath=subpath+'/'+parts[i]
self.nextcloud.add_group(subpath) self.nextcloud.add_group(subpath)
except: except:
log.error('probably exists') log.error('probably exists')
i=i+1 i=i+1
ev=Events('Syncing users from keycloak to nextcloud',total=len(self.internal['users']))
for u in self.internal['users']: for u in self.internal['users']:
# print('User '+u['username']) # print('User '+u['username'])
if not u['nextcloud']: if not u['nextcloud']:
@ -659,6 +730,7 @@ class Admin():
log.warning(' NEXTCLOUD USERS: Creating nextcloud user: '+u['username']+' in groups '+str(u['keycloak_groups'])) log.warning(' NEXTCLOUD USERS: Creating nextcloud user: '+u['username']+' in groups '+str(u['keycloak_groups']))
# group=u['keycloak_groups'][0] if len(u['keycloak_groups']) else False # group=u['keycloak_groups'][0] if len(u['keycloak_groups']) else False
try: try:
ev.increment({'name':u['username']})
self.nextcloud.add_user_with_groups(u['username'],'1Random 1String',500000000000,u['keycloak_groups'],u['email'],u['first']+' '+u['last']) self.nextcloud.add_user_with_groups(u['username'],'1Random 1String',500000000000,u['keycloak_groups'],u['email'],u['first']+' '+u['last'])
except ProviderItemExists: except ProviderItemExists:
log.warning('User '+u['username']+' already exists. Skipping...') log.warning('User '+u['username']+' already exists. Skipping...')
@ -678,7 +750,7 @@ class Admin():
log.info(' KEYCLOAK USERS: Removing user ('+str(i)+'/'+str(total)+'): '+u['username']) log.info(' KEYCLOAK USERS: Removing user ('+str(i)+'/'+str(total)+'): '+u['username'])
try: try:
self.keycloak.delete_user(u['id']) self.keycloak.delete_user(u['id'])
socketio.emit('update', app.socketio.emit('update',
json.dumps({'status':True,'item':'user','action':'delete','itemdata':u}), json.dumps({'status':True,'item':'user','action':'delete','itemdata':u}),
namespace='/isard-sso-admin/sio', namespace='/isard-sso-admin/sio',
room='admin') room='admin')
@ -692,7 +764,7 @@ class Admin():
log.info('Removing nextcloud user: '+u['username']) log.info('Removing nextcloud user: '+u['username'])
try: try:
self.nextcloud.delete_user(u['nextcloud_id']) self.nextcloud.delete_user(u['nextcloud_id'])
socketio.emit('update', app.socketio.emit('update',
json.dumps({'status':True,'item':'user','action':'delete','itemdata':u}), json.dumps({'status':True,'item':'user','action':'delete','itemdata':u}),
namespace='/isard-sso-admin/sio', namespace='/isard-sso-admin/sio',
room='admin') room='admin')
@ -711,7 +783,7 @@ class Admin():
log.warning('Removing moodle users: '+','.join(usernames)) log.warning('Removing moodle users: '+','.join(usernames))
try: try:
self.moodle.delete_users(userids) self.moodle.delete_users(userids)
socketio.emit('update', app.socketio.emit('update',
json.dumps({'status':True,'item':'user','action':'delete','itemdata':u}), json.dumps({'status':True,'item':'user','action':'delete','itemdata':u}),
namespace='/isard-sso-admin/sio', namespace='/isard-sso-admin/sio',
room='admin') room='admin')

View File

@ -0,0 +1,73 @@
#!flask/bin/python
# coding=utf-8
from admin import app
import logging as log
import traceback
from uuid import uuid4
import json
from time import sleep
import sys,os
from flask import render_template, Response, request, redirect, url_for, jsonify
from flask_socketio import SocketIO, emit, join_room, leave_room, \
close_room, rooms, disconnect, send
import base64
class Events():
def __init__(self,title,text='',total=0):
self.eid=str(base64.b64encode(os.urandom(32))[:8])
self.title=title
self.text=text
self.total=total
self.item=0
self.create()
def create(self):
app.socketio.emit('notify-create',
json.dumps({'id':self.eid,
'title':self.title,
'text':self.text}),
namespace='/isard-sso-admin/sio',
room='admin')
sleep(0.1)
def __del__(self):
app.socketio.emit('notify-destroy',
json.dumps({'id':self.eid}),
namespace='/isard-sso-admin/sio',
room='admin')
sleep(0.1)
def update_text(self,text):
self.text=text
app.socketio.emit('notify-update',
json.dumps({'id':self.eid,
'text':self.text,}),
namespace='/isard-sso-admin/sio',
room='admin')
sleep(0.1)
def increment(self,data={}):
self.item+=1
app.socketio.emit('notify-update',
json.dumps({'id':self.eid,
'text': '['+str(self.item)+'/'+str(self.total)+'] ',
'item':self.item,
'total':self.total,
'data':data}),
namespace='/isard-sso-admin/sio',
room='admin')
sleep(0.1)
def decrement(self,data={}):
self.item-=1
app.socketio.emit('notify-update',
json.dumps({'id':self.eid,
'text':'['+str(self.item)+'/'+str(self.total)+'] ',
'item':self.item,
'total':self.total,
'data':data}),
namespace='/isard-sso-admin/sio',
room='admin')
sleep(0.1)

View File

@ -17,7 +17,7 @@ $(document).ready(function() {
$.each(users_table.rows().data(),function(key, value){ $.each(users_table.rows().data(),function(key, value){
ids[value['id']]=value['roles'] ids[value['id']]=value['roles']
}); });
console.log(ids) // console.log(ids)
$.ajax({ $.ajax({
type: "PUT", type: "PUT",
url:"/isard-sso-admin/external", url:"/isard-sso-admin/external",
@ -46,25 +46,30 @@ $(document).ready(function() {
}) })
$("#modalImport #send").on('click', function(e){ $("#modalImport #send").on('click', function(e){
console.log(users_table.rows().data()) // console.log(users_table.rows().data())
var form = $('#modalImportForm'); var form = $('#modalImportForm');
form.parsley().validate(); form.parsley().validate();
if (form.parsley().isValid()){ if (form.parsley().isValid()){
formdata = form.serializeObject() formdata = form.serializeObject()
formdata['data']=JSON.parse(filecontents) if($('#format').val() == 'csv-ug'){
formdata['data']=parseCSV(filecontents)
}else{
formdata['data']=JSON.parse(filecontents)
}
$.ajax({ $.ajax({
type: "POST", type: "POST",
url:"/isard-sso-admin/external", url:"/isard-sso-admin/external",
data: JSON.stringify(formdata), data: JSON.stringify(formdata),
success: function(data) success: function(data)
{ {
$("#modalImport").modal('hide'); console.log('SUCCESS')
users_table.ajax.reload(); // $("#modalImport").modal('hide');
groups_table.ajax.reload(); // users_table.ajax.reload();
// groups_table.ajax.reload();
}, },
error: function(data) error: function(data)
{ {
alert('Something went wrong on our side...') console.log('Ajax timeout')
} }
}); });
} }
@ -194,20 +199,46 @@ $(document).ready(function() {
}); });
function readFile (evt) { function readFile (evt) {
path = ""; if($('#format').val() == 'json-ga'){
items = []; path = "";
var files = evt.target.files; items = [];
var file = files[0]; var files = evt.target.files;
var reader = new FileReader(); var file = files[0];
reader.onload = function(event) { var reader = new FileReader();
filecontents=event.target.result; reader.onload = function(event) {
$.each(JSON.parse(filecontents), walker); filecontents=event.target.result;
populate_path(items) $.each(JSON.parse(filecontents), walker);
populate_path(items)
}
reader.readAsText(file, 'UTF-8')
}
if($('#format').val() == 'csv-ug'){
var files = evt.target.files;
var file = files[0];
var reader = new FileReader();
reader.onload = function(event) {
filecontents=event.target.result;
// $.each(JSON.parse(filecontents), walker);
// populate_path(items)
}
reader.readAsText(file, 'UTF-8')
} }
reader.readAsText(file, 'UTF-8')
} }
function parseCSV(){
lines=filecontents.split('\n')
header=lines[0].split(';')
users=[]
$.each(lines, function(n, l){
if(n!=0 && l.length > 10){
usr=toObject(header,l.split(';'))
usr['id']=usr['username']
users.push(usr)
}
})
return users;
}
function toObject(names, values) { function toObject(names, values) {
var result = {}; var result = {};
for (var i = 0; i < names.length; i++) for (var i = 0; i < names.length; i++)

View File

@ -1,19 +1,86 @@
// SocketIO notice={}
socket = io.connect(location.protocol+'//' + document.domain +'/isard-sso-admin/sio'); $lost=0;
console.log(location.protocol+'//' + document.domain +'/isard-sso-admin/sio')
socket.on('connect', function() {
// connection_done();
console.log('Listening status socket');
});
socket.on('connect_error', function(data) { socket = io.connect(location.protocol+'//' + document.domain +'/isard-sso-admin/sio');
// connection_lost(); console.log(location.protocol+'//' + document.domain +'/isard-sso-admin/sio')
}); socket.on('connect', function() {
if($lost){location.reload();}
socket.on('update', function(data) { console.log('Listening status socket');
var data = JSON.parse(data); });
console.log('Status update')
console.log(data) socket.on('connect_error', function(data) {
// var data = JSON.parse(data); $lost=$lost+1;
// drawUserQuota(data); $('#modal-lostconnection').modal({
backdrop: 'static',
keyboard: false
}).modal('show');
});
socket.on('notify-create', function(data) {
var data = JSON.parse(data);
notice[data.id] = new PNotify({
title: data.title,
text: data.text,
hide: false
}); });
});
socket.on('notify-destroy', function(data) {
var data = JSON.parse(data);
notice[data.id].remove()
});
socket.on('notify-update', function(data) {
var data = JSON.parse(data);
// console.log(data.text)
notice[data.id].update({
text: data.text
})
});
// new PNotify({
// title: "Quota for creating desktops full.",
// text: "Can't create another desktop, user quota full.",
// hide: true,
// delay: 3000,
// icon: 'fa fa-alert-sign',
// opacity: 1,
// type: 'error'
// });
// socket.on('update', function(data) {
// var data = JSON.parse(data);
// console.log('Status update')
// console.log(data)
// // var data = JSON.parse(data);
// // drawUserQuota(data);
// });
socket.on('update', function(data) {
var data = JSON.parse(data);
console.log('Status update')
console.log(data)
// var data = JSON.parse(data);
// drawUserQuota(data);
});
// {'event':'traceback',
// 'id':u['id'],
// 'item':'group',
// 'action':'add'
// 'name':g['name'],
// 'progress':str(item)+'/'+str(total),
// 'status':False,
// 'msg':,
// 'payload':{'traceback':traceback.format_exc(),
// 'data':g})
socket.on('progress', function(data) {
var data = JSON.parse(data);
console.log(data)
// $('.modal-progress #item').html(data.item)
});
////

View File

@ -59,26 +59,9 @@
<!-- /footer content --> <!-- /footer content -->
</div> </div>
</div> </div>
<div id="modal-lostconnection" class="modal fade" role="dialog" style="width:50%;margin-left:30%;margin-top:10%;z-index: 100000;">
<div class="modal-admin"> {% include 'pages/modals/common_modals.html' %}
<div class="modal-content">
<div class="row text-center"><h2 style="margin-bottom:5px">Connection lost</h2></div>
<hr>
<div class="row">
<div class="col-md-1 col-sm-1 col-xs-12"></div>
<div class="col-md-10 col-sm-10 col-xs-12">
<div class="row text-center">Unable to contact server. There should be a problem with network or a heavy load.</div>
<br>
<div class="row text-center" style="margin-bottom:25px">
<i class="fa fa-circle-o-notch fa-spin fa-fw"></i> Trying to reconnect...
</div>
</div>
<div class="col-md-1 col-sm-1 col-xs-12">
</div>
</div>
</div>
</div>
</div>
<!-- jQuery --> <!-- jQuery -->
<script src="/isard-sso-admin/vendors/jquery/dist/jquery.js"></script> <script src="/isard-sso-admin/vendors/jquery/dist/jquery.js"></script>

View File

@ -0,0 +1,44 @@
<div id="modal-lostconnection" class="modal fade" role="dialog" style="width:50%;margin-left:30%;margin-top:10%;z-index: 100000;">
<div class="modal-admin">
<div class="modal-content">
<div class="row text-center"><h2 style="margin-bottom:5px">Connection lost</h2></div>
<hr>
<div class="row">
<div class="col-md-1 col-sm-1 col-xs-12"></div>
<div class="col-md-10 col-sm-10 col-xs-12">
<div class="row text-center">Unable to contact server. There should be a problem with network or a heavy load.</div>
<br>
<div class="row text-center">
<i class="fa fa-circle-o-notch fa-spin fa-fw"></i> Trying to reconnect...
</div>
<br>
<div class="col-md-1 col-sm-1 col-xs-12">
</div>
</div>
</div>
</div>
</div>
</div>
<div id="modal-info" class="modal fade" role="dialog" style="width:100%;margin-left:10%;margin-top:10%;z-index: 100000;">
<div class="modal-admin">
<div class="modal-content">
<div class="row text-center"><h2 style="margin-bottom:5px">Connection lost</h2></div>
<hr>
<div class="row">
<div class="col-md-10 col-sm-10 col-xs-12">
<div class="row text-center">Unable to contact server. There should be a problem with network or a heavy load.</div>
<br>
<div class="row text-center">
<i class="fa fa-circle-o-notch fa-spin fa-fw"></i> Trying to reconnect...
</div>
<br>
<div class="col-md-1 col-sm-1 col-xs-12">
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -32,7 +32,8 @@
<label class="control-label col-md-3 col-sm-3 col-xs-12" for="format">Format: <span class="required">*</span></label> <label class="control-label col-md-3 col-sm-3 col-xs-12" for="format">Format: <span class="required">*</span></label>
<div class="col-md-6 col-sm-6 col-xs-12"> <div class="col-md-6 col-sm-6 col-xs-12">
<select id="format" name="format" class="form-control format" required> <select id="format" name="format" class="form-control format" required>
<option value="json">JSON dump</option> <option value="json-ga">GAdminconsole JSON</option>
<option value="csv-ug">CSV user with groups</option>
</select> </select>
</div> </div>
</div> </div>

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>
<!-- <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>
<button class="btn btn-danger btn-xs btn-delete_nextcloud"> <button class="btn btn-danger btn-xs btn-delete_nextcloud">
@ -35,7 +35,7 @@
</button> </button>
<button class="btn btn-danger btn-xs btn-delete_moodle"> <button class="btn btn-danger btn-xs btn-delete_moodle">
<i class="fa fa-trash"></i> Delete missing keycloak in moodle <i class="fa fa-trash"></i> Delete missing keycloak in moodle
</button> --> </button>
<table id="users" class="table" width="100%"> <table id="users" class="table" width="100%">
<thead> <thead>
<tr> <tr>

View File

@ -8,9 +8,14 @@ from uuid import uuid4
import time,json import time,json
import sys,os import sys,os
from flask import render_template, Response, request, redirect, url_for, jsonify from flask import render_template, Response, request, redirect, url_for, jsonify
import concurrent.futures
from pprint import pprint from pprint import pprint
# from flask_socketio import SocketIO, emit, join_room, leave_room, \
# close_room, rooms, disconnect, send
# socketio = SocketIO(app)
@app.route('/isard-sso-admin/resync') @app.route('/isard-sso-admin/resync')
# @login_required # @login_required
def resync(): def resync():
@ -70,7 +75,12 @@ def groups_list():
# @login_required # @login_required
def external(): def external():
if request.method == 'POST': if request.method == 'POST':
return json.dumps(app.admin.upload_json(request.get_json(force=True))), 200, {'Content-Type': 'application/json'} data=request.get_json(force=True)
if data['format']=='json-ga':
app.admin.upload_json_ga(data)
if data['format']=='csv-ug':
app.admin.upload_csv_ug(data)
return json.dumps({}), 200, {'Content-Type': 'application/json'}
if request.method == 'PUT': if request.method == 'PUT':
return json.dumps(app.admin.sync_external(request.get_json(force=True))), 200, {'Content-Type': 'application/json'} return json.dumps(app.admin.sync_external(request.get_json(force=True))), 200, {'Content-Type': 'application/json'}
return render_template('pages/external.html', title="External", nav="External") return render_template('pages/external.html', title="External", nav="External")
@ -89,4 +99,15 @@ def external_groups_list():
# @login_required # @login_required
def external_roles(): def external_roles():
if request.method == 'PUT': if request.method == 'PUT':
return json.dumps(app.admin.external_roleassign(request.get_json(force=True))), 200, {'Content-Type': 'application/json'} return json.dumps(app.admin.external_roleassign(request.get_json(force=True))), 200, {'Content-Type': 'application/json'}
def WaitStatus(self, desktop_id, original_status, transition_status, final_status):
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
future = executor.submit(lambda p: self._wait_for_domain_status(*p), [desktop_id, original_status, transition_status, final_status])
try:
result = future.result()
except ReqlTimeoutError:
raise DesktopActionTimeout
except DesktopWaitFailed:
raise DesktopActionFailed
return True

View File

@ -1,19 +1,19 @@
from flask_socketio import SocketIO, emit, join_room, leave_room, \ # from flask_socketio import SocketIO, emit, join_room, leave_room, \
close_room, rooms, disconnect, send # close_room, rooms, disconnect, send
from admin import app # from admin import app
import json # import json
socketio = SocketIO(app) # # socketio = SocketIO(app)
# from ...start import socketio # # from ...start import socketio
@socketio.on('connect', namespace='/isard-sso-admin/sio') # @socketio.on('connect', namespace='/isard-sso-admin/sio')
def socketio_connect(): # def socketio_connect():
join_room('admin') # join_room('admin')
socketio.emit('update', # socketio.emit('update',
json.dumps('Joined'), # json.dumps('Joined'),
namespace='/isard-sso-admin/sio', # namespace='/isard-sso-admin/sio',
room='admin') # room='admin')
@socketio.on('disconnect', namespace='/isard-sso-admin/sio') # @socketio.on('disconnect', namespace='/isard-sso-admin/sio')
def socketio_domains_disconnect(): # def socketio_domains_disconnect():
None # None

View File

@ -11,19 +11,26 @@ from admin import app
# socketio.init_app(app, cors_allowed_origins="*") # socketio.init_app(app, cors_allowed_origins="*")
from admin.views.Socketio import * # from admin.views.Socketio import *
# socketio = SocketIO(app)
# @socketio.on('connect', namespace='/isard-sso-admin/sio') app.socketio = SocketIO(app)
# def socketio_connect(): # app.socketio.init_app(app, cors_allowed_origins="*")
# join_room('admin') @app.socketio.on('connect', namespace='/isard-sso-admin/sio')
# socketio.emit('update', def socketio_connect():
# json.dumps('Joined'), join_room('admin')
# namespace='/isard-sso-admin/sio', app.socketio.emit('update',
# room='admin') json.dumps('Joined'),
namespace='/isard-sso-admin/sio',
room='admin')
# socketio.emit('update',
# json.dumps('DATA SENT'),
# namespace='/isard-sso-admin/sio',
# room='admin')
# @socketio.on('disconnect', namespace='/isard-sso-admin/sio') @app.socketio.on('disconnect', namespace='/isard-sso-admin/sio')
# def socketio_domains_disconnect(): def socketio_domains_disconnect():
# None None
if __name__ == '__main__': if __name__ == '__main__':
socketio.run(app,host='0.0.0.0', port=9000, debug=False, cors_allowed_origins="*") #, logger=logger, engineio_logger=engineio_logger) app.socketio.run(app,host='0.0.0.0', port=9000, debug=False, cors_allowed_origins="*", async_mode="threading") #, logger=logger, engineio_logger=engineio_logger)

View File

@ -93,6 +93,10 @@ backend be_sso
backend be_admin backend be_admin
mode http mode http
option forwardfor
timeout queue 600s
timeout server 600s
timeout connect 600s
acl authorized http_auth(AuthUsers) acl authorized http_auth(AuthUsers)
http-request auth realm AuthUsers unless authorized http-request auth realm AuthUsers unless authorized
acl existing-x-forwarded-host req.hdr(X-Forwarded-Host) -m found acl existing-x-forwarded-host req.hdr(X-Forwarded-Host) -m found