added csv and gevents
parent
a41d563f5f
commit
29b7bdef1d
|
@ -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')
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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++)
|
||||||
|
|
|
@ -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)
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue