updated admin functs
parent
a65441bc03
commit
90ef56bbdf
|
@ -16,7 +16,7 @@ You can generate one with:
|
|||
os.urandom(24)
|
||||
And paste it here.
|
||||
'''
|
||||
app.secret_key = "Change this key!//\xf7\x83\xbe\x17\xfa\xa3zT\n\\]m\xa6\x8bF\xdd\r\xf7\x9e\x1d\x1f\x14'"
|
||||
app.secret_key = "Change this key!/\xf7\x83\xbe\x17\xfa\xa3zT\n\\]m\xa6\x8bF\xdd\r\xf7\x9e\x1d\x1f\x14'"
|
||||
|
||||
print('Starting isard-sso api...')
|
||||
|
||||
|
@ -45,15 +45,15 @@ else:
|
|||
'''
|
||||
Serve static files
|
||||
'''
|
||||
@app.route('/isard-sso-admin/build/<path:path>')
|
||||
@app.route('/build/<path:path>')
|
||||
def send_build(path):
|
||||
return send_from_directory(os.path.join(app.root_path, 'node_modules/gentelella/build'), path)
|
||||
|
||||
@app.route('/isard-sso-admin/vendors/<path:path>')
|
||||
@app.route('/vendors/<path:path>')
|
||||
def send_vendors(path):
|
||||
return send_from_directory(os.path.join(app.root_path, 'node_modules/gentelella/vendors'), path)
|
||||
|
||||
@app.route('/isard-sso-admin/templates/<path:path>')
|
||||
@app.route('/templates/<path:path>')
|
||||
def send_templates(path):
|
||||
return send_from_directory(os.path.join(app.root_path, 'templates'), path)
|
||||
|
||||
|
@ -61,14 +61,18 @@ def send_templates(path):
|
|||
# def send_templates(path):
|
||||
# return send_from_directory(os.path.join(app.root_path, 'static/templates'), path)
|
||||
|
||||
@app.route('/isard-sso-admin/static/<path:path>')
|
||||
@app.route('/static/<path:path>')
|
||||
def send_static_js(path):
|
||||
return send_from_directory(os.path.join(app.root_path, 'static'), path)
|
||||
|
||||
@app.route('/isard-sso-admin/avatars/<path:path>')
|
||||
@app.route('/avatars/<path:path>')
|
||||
def send_avatars_img(path):
|
||||
return send_from_directory(os.path.join(app.root_path, '../avatars/master-avatars'), path)
|
||||
|
||||
@app.route('/custom/<path:path>')
|
||||
def send_custom(path):
|
||||
return send_from_directory(os.path.join(app.root_path, '../custom'), path)
|
||||
|
||||
# @app.errorhandler(404)
|
||||
# def not_found_error(error):
|
||||
# return render_template('page_404.html'), 404
|
||||
|
@ -81,8 +85,8 @@ def send_avatars_img(path):
|
|||
Import all views
|
||||
'''
|
||||
from .views import LoginViews
|
||||
from .views import MenuViews
|
||||
from .views import AvatarViews
|
||||
from .views import WebViews
|
||||
from .views import ApiViews
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,31 +1,28 @@
|
|||
from admin import app
|
||||
from flask_login import LoginManager, UserMixin
|
||||
|
||||
from flask_login import login_required
|
||||
from flask_oidc import OpenIDConnect
|
||||
login_manager = LoginManager()
|
||||
login_manager.init_app(app)
|
||||
login_manager.login_view = "login"
|
||||
|
||||
app.config.update({
|
||||
'SECRET_KEY': 'u\x91\xcf\xfa\x0c\xb9\x95\xe3t\xba2K\x7f\xfd\xca\xa3\x9f\x90\x88\xb8\xee\xa4\xd6\xe4',
|
||||
'TESTING': True,
|
||||
'DEBUG': True,
|
||||
'OIDC_CLIENT_SECRETS': 'client_secrets.json',
|
||||
'OIDC_ID_TOKEN_COOKIE_SECURE': False,
|
||||
'OIDC_REQUIRE_VERIFIED_EMAIL': False,
|
||||
'OIDC_VALID_ISSUERS': ['https://sso.santantoni.duckdns.org:8080/auth/realms/master'],
|
||||
'OIDC_OPENID_REALM': 'https://sso.santantoni.duckdns.org/isard-sso-admin/custom_callback',
|
||||
'OVERWRITE_REDIRECT_URI': 'https://sso.santantoni.duckdns.org/isard-sso-admin/custom_callback',
|
||||
})
|
||||
# 'OVERWRITE_REDIRECT_URI': 'https://sso.santantoni.duckdns.org/isard-sso-admin/custom_callback',
|
||||
# 'OIDC_CALLBACK_ROUTE': '/isard-sso-admin/custom_callback'
|
||||
oidc = OpenIDConnect(app)
|
||||
|
||||
import os
|
||||
|
||||
# login_manager = LoginManager()
|
||||
# login_manager.init_app(app)
|
||||
''' OIDC TESTS '''
|
||||
# from flask_oidc import OpenIDConnect
|
||||
# app.config.update({
|
||||
# 'SECRET_KEY': 'u\x91\xcf\xfa\x0c\xb9\x95\xe3t\xba2K\x7f\xfd\xca\xa3\x9f\x90\x88\xb8\xee\xa4\xd6\xe4',
|
||||
# 'TESTING': True,
|
||||
# 'DEBUG': True,
|
||||
# 'OIDC_CLIENT_SECRETS': 'client_secrets.json',
|
||||
# 'OIDC_ID_TOKEN_COOKIE_SECURE': False,
|
||||
# 'OIDC_REQUIRE_VERIFIED_EMAIL': False,
|
||||
# 'OIDC_VALID_ISSUERS': ['https://sso.santantoni.duckdns.org:8080/auth/realms/master'],
|
||||
# 'OIDC_OPENID_REALM': 'https://sso.santantoni.duckdns.org//custom_callback',
|
||||
# 'OVERWRITE_REDIRECT_URI': 'https://sso.santantoni.duckdns.org//custom_callback',
|
||||
# })
|
||||
# # 'OVERWRITE_REDIRECT_URI': 'https://sso.santantoni.duckdns.org//custom_callback',
|
||||
# # 'OIDC_CALLBACK_ROUTE': '//custom_callback'
|
||||
# oidc = OpenIDConnect(app)
|
||||
''' OIDC TESTS '''
|
||||
|
||||
|
||||
login_manager = LoginManager()
|
||||
login_manager.init_app(app)
|
||||
login_manager.login_view = "login"
|
||||
|
||||
|
||||
|
@ -33,12 +30,12 @@ ram_users={
|
|||
os.environ["ADMINAPP_USER"]: {
|
||||
'id': os.environ["ADMINAPP_USER"],
|
||||
'password': os.environ["ADMINAPP_PASSWORD"],
|
||||
'role': 'admin'
|
||||
'role': 'manager'
|
||||
},
|
||||
os.environ["KEYCLOAK_USER"]: {
|
||||
'id': os.environ["KEYCLOAK_USER"],
|
||||
'password': os.environ["KEYCLOAK_PASSWORD"],
|
||||
'role': 'admin-keycloak',
|
||||
'role': 'admin',
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -247,6 +247,7 @@ class Admin():
|
|||
"username":u['username'],
|
||||
"first": u.get('first_name',None),
|
||||
"last": u.get('last_name',None),
|
||||
"enabled": u['enabled'],
|
||||
"email": u.get('email',''),
|
||||
"groups": u['group'],
|
||||
"roles": filter_roles_list(u['role'])}
|
||||
|
@ -430,7 +431,7 @@ class Admin():
|
|||
'username': u['username'].strip(),
|
||||
'groups':user_groups,
|
||||
'roles':[u['role'].strip()],
|
||||
'password':diceware.get_passphrase(options=options)})
|
||||
'password': self.get_dice_pwd()})
|
||||
item+=1
|
||||
ev.increment({'name':u['username'].split('@')[0]})
|
||||
self.external['users']=users
|
||||
|
@ -447,13 +448,19 @@ class Admin():
|
|||
self.external['groups']=sysgroups
|
||||
return True
|
||||
|
||||
def get_dice_pwd(self):
|
||||
return diceware.get_passphrase(options=options)
|
||||
|
||||
def upload_json_ga(self,data):
|
||||
groups=[]
|
||||
log.warning('Processing uploaded groups...')
|
||||
ev=Events('Processing uploaded groups',total=len(data['data']['groups']))
|
||||
try:
|
||||
ev=Events('Processing uploaded groups','Group:',total=len(data['data']['groups']))
|
||||
except:
|
||||
log.error(traceback.format_exc())
|
||||
for g in data['data']['groups']:
|
||||
try:
|
||||
ev.increment({'name':g['name']})
|
||||
ev.increment({'name':g['name'],'data':g})
|
||||
groups.append({'provider':'external',
|
||||
"id": g['id'],
|
||||
"mailid": g['email'].split('@')[0],
|
||||
|
@ -467,10 +474,10 @@ class Admin():
|
|||
users=[]
|
||||
total=len(data['data']['users'])
|
||||
item=1
|
||||
ev=Events('Processing uploaded users',total=len(data['data']['users']))
|
||||
ev=Events('Processing uploaded users','User:',total=len(data['data']['users']))
|
||||
for u in data['data']['users']:
|
||||
log.warning('Processing ('+str(item)+'/'+str(total)+') uploaded user: '+u['primaryEmail'].split('@')[0])
|
||||
users.append({'provider':'external',
|
||||
new_user={'provider':'external',
|
||||
'id':u['id'],
|
||||
'email': u['primaryEmail'],
|
||||
'first': u['name']['givenName'],
|
||||
|
@ -478,9 +485,10 @@ class Admin():
|
|||
'username': u['primaryEmail'].split('@')[0],
|
||||
'groups':[u['orgUnitPath']], ## WARNING: Removing the first
|
||||
'roles':[],
|
||||
'password': diceware.get_passphrase(options=options)})
|
||||
'password': diceware.get_passphrase(options=options)}
|
||||
users.append(new_user)
|
||||
item+=1
|
||||
ev.increment({'name':u['primaryEmail'].split('@')[0]})
|
||||
ev.increment({'name':u['primaryEmail'].split('@')[0],'data':new_user})
|
||||
self.external['users']=users
|
||||
|
||||
## Add groups to users (now they only have their orgUnitPath)
|
||||
|
@ -495,14 +503,13 @@ class Admin():
|
|||
log.warning('Starting sync to keycloak')
|
||||
self.sync_to_keycloak()
|
||||
### Now we only sycn external to keycloak and then they can be updated to others with UI buttons
|
||||
# log.warning('Starting sync to moodle')
|
||||
# self.sync_to_moodle()
|
||||
# log.warning('Starting sync to nextcloud')
|
||||
# self.sync_to_nextcloud()
|
||||
# log.warning('All syncs finished')
|
||||
log.warning('Starting sync to moodle')
|
||||
self.sync_to_moodle()
|
||||
log.warning('Starting sync to nextcloud')
|
||||
self.sync_to_nextcloud()
|
||||
log.warning('All syncs finished')
|
||||
|
||||
def sync_to_keycloak(self): ### This one works from the external, moodle and nextcloud from the internal
|
||||
|
||||
groups=[]
|
||||
for u in self.external['users']:
|
||||
groups=groups+u['groups']
|
||||
|
@ -510,7 +517,7 @@ class Admin():
|
|||
|
||||
total=len(groups)
|
||||
i=0
|
||||
ev=Events('Syncing import groups to keycloak',total=len(groups))
|
||||
ev=Events('Syncing import groups to keycloak','Adding group:',total=len(groups))
|
||||
for g in groups:
|
||||
i=i+1
|
||||
log.warning(' KEYCLOAK GROUPS: Adding group ('+str(i)+'/'+str(total)+'): '+g)
|
||||
|
@ -519,12 +526,12 @@ class Admin():
|
|||
|
||||
total=len(self.external['users'])
|
||||
index=0
|
||||
ev=Events('Syncing import users to keycloak',total=len(self.external['users']))
|
||||
ev=Events('Syncing import users to keycloak','Adding user:',total=len(self.external['users']))
|
||||
for u in self.external['users']:
|
||||
index=index+1
|
||||
# Add user
|
||||
log.warning(' KEYCLOAK USERS: Adding user ('+str(index)+'/'+str(total)+'): '+u['username'])
|
||||
ev.increment({'name':u['username']})
|
||||
ev.increment({'name':u['username'],'data':u})
|
||||
uid=self.keycloak.add_user(u['username'],u['first'],u['last'],u['email'],u['password'])
|
||||
|
||||
# Add user to role and group rolename
|
||||
|
@ -538,11 +545,10 @@ class Admin():
|
|||
parts=g.split('/')
|
||||
sub=''
|
||||
if len(parts)==0:
|
||||
log.warning(' KEYCLOAK USERS: Skip assign user '+u['username']+' to any group as des not have one')
|
||||
log.warning(' KEYCLOAK USERS: Skip assign user '+u['username']+' to any group as does not have one')
|
||||
continue # NO GROUP
|
||||
for i in range(1,len(parts)):
|
||||
sub=sub+'/'+parts[i]
|
||||
|
||||
if sub=='/': continue # User with no path
|
||||
log.warning(' KEYCLOAK USERS: Assign user '+u['username']+' to group '+ str(sub))
|
||||
gid=self.keycloak.get_group_by_path(path=sub)['id']
|
||||
|
@ -588,7 +594,6 @@ class Admin():
|
|||
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'])
|
||||
|
@ -604,7 +609,6 @@ class Admin():
|
|||
for g in u['keycloak_groups']:
|
||||
parts=g.split('/')
|
||||
subpath=''
|
||||
# pprint(parts)
|
||||
for i in range(1,len(parts)):
|
||||
if parts[i] in ['admin','manager','teacher','student']:
|
||||
subpath=parts[i]
|
||||
|
@ -663,9 +667,24 @@ class Admin():
|
|||
except:
|
||||
log.error(traceback.format_exc())
|
||||
|
||||
def delete_keycloak_user(self,userid):
|
||||
user=[u for u in self.internal['users'] if u['id']==userid]
|
||||
if len(user) and user[0]['keycloak']:
|
||||
user=user[0]
|
||||
keycloak_id=user['id']
|
||||
else:
|
||||
return False
|
||||
log.warning('Removing keycloak user: '+user['username'])
|
||||
try:
|
||||
self.keycloak.delete_user(keycloak_id)
|
||||
except:
|
||||
log.error(traceback.format_exc())
|
||||
log.warning('Could not remove users: '+user['username'])
|
||||
|
||||
def delete_keycloak_users(self):
|
||||
total=len(self.internal['users'])
|
||||
i=0
|
||||
ev=Events('Deleting users from keycloak','Deleting user:',total=len(self.internal['users']))
|
||||
for u in self.internal['users']:
|
||||
i=i+1
|
||||
if not u['keycloak']: continue
|
||||
|
@ -673,29 +692,53 @@ class Admin():
|
|||
if ['admin'] in u['roles']: continue
|
||||
log.info(' KEYCLOAK USERS: Removing user ('+str(i)+'/'+str(total)+'): '+u['username'])
|
||||
try:
|
||||
ev.increment({'name':u['username'],'data':u})
|
||||
self.keycloak.delete_user(u['id'])
|
||||
app.socketio.emit('update',
|
||||
json.dumps({'status':True,'item':'user','action':'delete','itemdata':u}),
|
||||
namespace='/isard-sso-admin/sio',
|
||||
room='admin')
|
||||
except:
|
||||
log.warning(' KEYCLOAK USERS: Could not remove user: '+u['username'] +'. Probably already not exists.')
|
||||
|
||||
def delete_nextcloud_user(self,userid):
|
||||
user=[u for u in self.internal['users'] if u['id']==userid]
|
||||
if len(user) and user[0]['nextcloud']:
|
||||
user=user[0]
|
||||
nextcloud_id=user['nextcloud_id']
|
||||
else:
|
||||
return False
|
||||
log.warning('Removing nextcloud user: '+user['username'])
|
||||
try:
|
||||
self.nextcloud.delete_user(nextcloud_id)
|
||||
except:
|
||||
log.error(traceback.format_exc())
|
||||
log.warning('Could not remove users: '+user['username'])
|
||||
|
||||
def delete_nextcloud_users(self):
|
||||
ev=Events('Deleting users from nextcloud',total=len(self.internal['users']))
|
||||
for u in self.internal['users']:
|
||||
|
||||
if u['nextcloud'] and not u['keycloak']:
|
||||
if u['roles'] and 'admin' in u['roles']: continue
|
||||
log.info('Removing nextcloud user: '+u['username'])
|
||||
try:
|
||||
self.nextcloud.delete_user(u['nextcloud_id'])
|
||||
app.socketio.emit('update',
|
||||
json.dumps({'status':True,'item':'user','action':'delete','itemdata':u}),
|
||||
namespace='/isard-sso-admin/sio',
|
||||
room='admin')
|
||||
ev.increment({'name':u['username']})
|
||||
self.nextcloud.delete_user(u['nextcloud_id'])
|
||||
except:
|
||||
log.error(traceback.format_exc())
|
||||
log.warning('Could not remove user: '+u['username'])
|
||||
|
||||
def delete_moodle_user(self,userid):
|
||||
user=[u for u in self.internal['users'] if u['id']==userid]
|
||||
if len(user) and user[0]['moodle']:
|
||||
user=user[0]
|
||||
moodle_id=user['moodle_id']
|
||||
else:
|
||||
return False
|
||||
log.warning('Removing moodle user: '+user['username'])
|
||||
try:
|
||||
self.moodle.delete_users([moodle_id])
|
||||
except:
|
||||
log.error(traceback.format_exc())
|
||||
log.warning('Could not remove users: '+user['username'])
|
||||
|
||||
def delete_moodle_users(self):
|
||||
userids=[]
|
||||
usernames=[]
|
||||
|
@ -709,13 +752,14 @@ class Admin():
|
|||
self.moodle.delete_users(userids)
|
||||
app.socketio.emit('update',
|
||||
json.dumps({'status':True,'item':'user','action':'delete','itemdata':u}),
|
||||
namespace='/isard-sso-admin/sio',
|
||||
namespace='//sio',
|
||||
room='admin')
|
||||
except:
|
||||
log.error(traceback.format_exc())
|
||||
log.warning('Could not remove users: '+','.join(usernames))
|
||||
|
||||
|
||||
|
||||
def delete_keycloak_groups(self):
|
||||
for g in self.internal['groups']:
|
||||
if not g['keycloak']: continue
|
||||
|
@ -733,4 +777,18 @@ class Admin():
|
|||
for externaluser in self.external['users']:
|
||||
if externaluser['id'] == newuserid:
|
||||
externaluser['roles']=[data['action']]
|
||||
return True
|
||||
return True
|
||||
|
||||
def user_update_password(self,userid,password,temporary):
|
||||
return self.keycloak.update_user_pwd(userid,password,temporary)
|
||||
|
||||
def delete_user(self,userid):
|
||||
log.warning('deleting user moodle, nextcloud keycloak')
|
||||
self.delete_moodle_user(userid)
|
||||
self.delete_nextcloud_user(userid)
|
||||
self.delete_keycloak_user(userid)
|
||||
self.resync_data()
|
||||
return True
|
||||
|
||||
def get_user(self,userid):
|
||||
return [u for u in self.internal['users'] if u['id']==userid][0]
|
|
@ -52,4 +52,4 @@ class Avatars():
|
|||
log.error(" AVATARS: Error occured when deleting avatar object", error)
|
||||
|
||||
def get_users_without_image(self,users):
|
||||
return [u for u in users if u['id'] not in self.minio_get_objects()]
|
||||
return [u for u in users if u['id'] and u['id'] not in self.minio_get_objects()]
|
|
@ -23,51 +23,80 @@ class Events():
|
|||
self.create()
|
||||
|
||||
def create(self):
|
||||
log.info('START '+self.eid+': '+self.text)
|
||||
app.socketio.emit('notify-create',
|
||||
json.dumps({'id':self.eid,
|
||||
'title':self.title,
|
||||
'text':self.text}),
|
||||
namespace='/isard-sso-admin/sio',
|
||||
namespace='/sio',
|
||||
room='admin')
|
||||
sleep(0.1)
|
||||
sleep(0.001)
|
||||
|
||||
def __del__(self):
|
||||
log.info('END '+self.eid+': '+self.text)
|
||||
app.socketio.emit('notify-destroy',
|
||||
json.dumps({'id':self.eid}),
|
||||
namespace='/isard-sso-admin/sio',
|
||||
namespace='/sio',
|
||||
room='admin')
|
||||
sleep(0.1)
|
||||
sleep(0.001)
|
||||
|
||||
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',
|
||||
namespace='/sio',
|
||||
room='admin')
|
||||
sleep(0.1)
|
||||
sleep(0.001)
|
||||
|
||||
def increment(self,data={}):
|
||||
def append_text(self,text):
|
||||
self.text=self.text+'<br>'+text
|
||||
app.socketio.emit('notify-update',
|
||||
json.dumps({'id':self.eid,
|
||||
'text':self.text,}),
|
||||
namespace='/sio',
|
||||
room='admin')
|
||||
sleep(0.001)
|
||||
|
||||
def increment(self,data={'name':'','data':[]}):
|
||||
self.item+=1
|
||||
log.info('INCREMENT '+self.eid+': '+self.text)
|
||||
app.socketio.emit('notify-update',
|
||||
json.dumps({'id':self.eid,
|
||||
'text': '['+str(self.item)+'/'+str(self.total)+'] ',
|
||||
'title':self.title,
|
||||
'text': '['+str(self.item)+'/'+str(self.total)+'] '+self.text+' '+data['name'],
|
||||
'item':self.item,
|
||||
'total':self.total,
|
||||
'data':data}),
|
||||
namespace='/isard-sso-admin/sio',
|
||||
namespace='/sio',
|
||||
room='admin')
|
||||
sleep(0.1)
|
||||
sleep(0.0001)
|
||||
|
||||
def decrement(self,data={}):
|
||||
def decrement(self,data={'name':'','data':[]}):
|
||||
self.item-=1
|
||||
log.info('DECREMENT '+self.eid+': '+self.text)
|
||||
app.socketio.emit('notify-update',
|
||||
json.dumps({'id':self.eid,
|
||||
'text':'['+str(self.item)+'/'+str(self.total)+'] ',
|
||||
'title':self.title,
|
||||
'text': '['+str(self.item)+'/'+str(self.total)+'] '+self.text+' '+data['name'],
|
||||
'item':self.item,
|
||||
'total':self.total,
|
||||
'data':data}),
|
||||
namespace='/isard-sso-admin/sio',
|
||||
namespace='/sio',
|
||||
room='admin')
|
||||
sleep(0.1)
|
||||
sleep(0.001)
|
||||
|
||||
def reload(self):
|
||||
app.socketio.emit('reload',
|
||||
json.dumps({}),
|
||||
namespace='/sio',
|
||||
room='admin')
|
||||
sleep(0.0001)
|
||||
|
||||
def table(self,event,table,data={}):
|
||||
# refresh, add, delete, update
|
||||
app.socketio.emit('table_'+event,
|
||||
json.dumps({'table':table,'data':data}),
|
||||
namespace='/sio',
|
||||
room='admin')
|
||||
sleep(0.0001)
|
|
@ -60,7 +60,7 @@ class KeycloakClient():
|
|||
# self.add_role('superman')
|
||||
# pprint(self.get_roles())
|
||||
|
||||
## USERS
|
||||
''' USERS '''
|
||||
|
||||
def get_user_id(self,username):
|
||||
self.connect()
|
||||
|
@ -71,7 +71,7 @@ class KeycloakClient():
|
|||
return self.keycloak_admin.get_users({})
|
||||
|
||||
def get_users_with_groups_and_roles(self):
|
||||
q = """select u.id, u.username, u.email, u.first_name, u.last_name, u.realm_id, ua.value as quota
|
||||
q = """select u.id, u.username, u.email, u.first_name, u.last_name, u.realm_id, u.enabled, ua.value as quota
|
||||
,json_agg(g."name") as group, json_agg(g_parent."name") as group_parent1, json_agg(g_parent2."name") as group_parent2
|
||||
,json_agg(r.name) as role
|
||||
from user_entity as u
|
||||
|
@ -82,7 +82,7 @@ class KeycloakClient():
|
|||
left join keycloak_group as g_parent2 on g_parent.parent_group = g_parent2.id
|
||||
left join user_role_mapping as rm on rm.user_id = u.id
|
||||
left join keycloak_role as r on r.id = rm.role_id
|
||||
group by u.id,u.username,u.email,u.first_name,u.last_name, u.realm_id, ua.value
|
||||
group by u.id,u.username,u.email,u.first_name,u.last_name, u.realm_id, u.enabled, ua.value
|
||||
order by u.username"""
|
||||
|
||||
(headers,users)=self.keycloak_pg.select_with_headers(q)
|
||||
|
@ -103,6 +103,7 @@ class KeycloakClient():
|
|||
|
||||
|
||||
def getparent(self,group_id, data):
|
||||
# Recursively get full path from any group_id in the tree
|
||||
path = ""
|
||||
for item in data:
|
||||
if group_id == item[0]:
|
||||
|
@ -111,11 +112,15 @@ class KeycloakClient():
|
|||
return path
|
||||
|
||||
def get_group_path(self,group_id):
|
||||
# Get full path using getparent recursive func
|
||||
# RETURNS: String with full path
|
||||
q = """SELECT * FROM keycloak_group"""
|
||||
groups=self.keycloak_pg.select(q)
|
||||
return self.getparent(group_id,groups)
|
||||
|
||||
def get_user_groups_paths(self,user_id):
|
||||
# Get full paths for user grups
|
||||
# RETURNS list of paths
|
||||
q = """SELECT group_id FROM user_group_membership WHERE user_id = '%s'""" % (user_id)
|
||||
user_group_ids=self.keycloak_pg.select(q)
|
||||
|
||||
|
@ -124,7 +129,7 @@ class KeycloakClient():
|
|||
paths.append(self.get_group_path(g[0]))
|
||||
return paths
|
||||
|
||||
## Too slow
|
||||
## Too slow. Used the direct postgres
|
||||
# def get_users_with_groups_and_roles(self):
|
||||
# self.connect()
|
||||
# users=self.keycloak_admin.get_users({})
|
||||
|
@ -134,7 +139,7 @@ class KeycloakClient():
|
|||
# return users
|
||||
|
||||
def add_user(self,username,first,last,email,password,group=False,temporary=True):
|
||||
# Returns user id
|
||||
# RETURNS string with keycloak user id (the main id in this app)
|
||||
self.connect()
|
||||
username=username.lower()
|
||||
try:
|
||||
|
@ -159,12 +164,13 @@ class KeycloakClient():
|
|||
self.keycloak_admin.group_user_add(uid,gid)
|
||||
return uid
|
||||
|
||||
def update_user_pwd(self,user_id='61092e24-cd67-4b50-baf9-b60e01f12bff',payload={},temporary=True):
|
||||
def update_user_pwd(self,user_id,password,temporary=True):
|
||||
# Updates
|
||||
payload={"credentials":[{"type":"password",
|
||||
"value":'pepito',
|
||||
"value":password,
|
||||
"temporary":temporary}]}
|
||||
self.connect()
|
||||
self.keycloak_admin.update_user( user_id, payload)
|
||||
return self.keycloak_admin.update_user( user_id, payload)
|
||||
|
||||
def remove_user_group(self,user_id,group_id):
|
||||
self.connect()
|
||||
|
@ -219,7 +225,6 @@ class KeycloakClient():
|
|||
|
||||
def add_group(self,name,parent=None,skip_exists=False):
|
||||
self.connect()
|
||||
print('parent_path: '+str(parent))
|
||||
if parent is not None: parent=self.get_group_by_path(parent)['id']
|
||||
return self.keycloak_admin.create_group({"name":name}, parent=parent)
|
||||
|
||||
|
@ -286,11 +291,11 @@ class KeycloakClient():
|
|||
else:
|
||||
thepath=parent_path+'/'+parts[i]
|
||||
if thepath=='/':
|
||||
print('Not adding the user '+username+' to any group as does not have any...')
|
||||
log.warning('Not adding the user '+username+' to any group as does not have any...')
|
||||
continue
|
||||
gid=self.get_group_by_path(path=thepath)['id']
|
||||
|
||||
print('Adding '+username+' with uuid: '+uid+' to group '+g+' with uuid: '+gid)
|
||||
log.warning('Adding '+username+' with uuid: '+uid+' to group '+g+' with uuid: '+gid)
|
||||
self.keycloak_admin.group_user_add(uid,gid)
|
||||
|
||||
|
||||
|
@ -360,4 +365,4 @@ class KeycloakClient():
|
|||
|
||||
def add_client(self,client):
|
||||
self.connect()
|
||||
return self.keycloak_admin.create_client(client)
|
||||
return self.keycloak_admin.create_client(client)
|
||||
|
|
|
@ -88,15 +88,16 @@ class Moodle():
|
|||
def get_users_with_groups_and_roles(self):
|
||||
q = """select u.id as id, username, firstname as first, lastname as last, email, json_agg(h.name) as groups, json_agg(r.shortname) as roles
|
||||
from mdl_user as u
|
||||
LEFT JOIN mdl_cohort_members AS hm on hm.id = u.id
|
||||
LEFT JOIN mdl_cohort_members AS hm on hm.userid = u.id
|
||||
left join mdl_cohort AS h ON h.id = hm.cohortid
|
||||
left join mdl_role_assignments AS ra ON ra.id = u.id
|
||||
left join mdl_role as r on r.id = ra.roleid
|
||||
where u.deleted = 0
|
||||
group by u.id , username, first, last, email"""
|
||||
(headers,users)=self.moodle_pg.select_with_headers(q)
|
||||
users_with_lists = [list(l[:-2])+([[]] if l[-2] == [None] else [list(set(l[-2]))]) + ([[]] if l[-1] == [None] else [list(set(l[-1]))]) for l in users]
|
||||
list_dict_users = [dict(zip(headers, r)) for r in users_with_lists]
|
||||
# pprint(list_dict_users)
|
||||
pprint(list_dict_users)
|
||||
return list_dict_users
|
||||
|
||||
## NOT USED. Too slow
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
#Add this app service
|
||||
registres mdl_external_services
|
||||
registres mdl_external_services_functions
|
||||
registres mdl_external_services_users
|
||||
|
||||
# SAML
|
||||
mdl_auth_saml2_idps
|
||||
|
||||
/opt/digitaldemocratic/data/moodle/saml2# ls
|
||||
0f635d0e0f3874fff8b581c132e6c7a7.idp.xml moodle.santantoni.duckdns.org.crt moodle.santantoni.duckdns.org.pem
|
||||
|
||||
echo -n xml | md5sum
|
||||
0f635d0e0f3874fff8b581c132e6c7a7
|
||||
|
||||
SELECT * FROM "mdl_config" WHERE ("name" LIKE '%saml%' OR "value" LIKE '%saml%') LIMIT 50 (0.001 s) Edita
|
||||
Modify id name value
|
||||
edita 3 auth email,saml2
|
||||
|
||||
privatekey_pass = mdl_config siteidentifier
|
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 21 KiB |
|
@ -20,7 +20,7 @@ $(document).ready(function() {
|
|||
// console.log(ids)
|
||||
$.ajax({
|
||||
type: "PUT",
|
||||
url:"/isard-sso-admin/external",
|
||||
url:"/api/external",
|
||||
data: JSON.stringify(ids),
|
||||
success: function(data)
|
||||
{
|
||||
|
@ -58,7 +58,7 @@ $(document).ready(function() {
|
|||
}
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url:"/isard-sso-admin/external",
|
||||
url:"/api/external",
|
||||
data: JSON.stringify(formdata),
|
||||
success: function(data)
|
||||
{
|
||||
|
@ -111,7 +111,7 @@ $(document).ready(function() {
|
|||
}).get().on('pnotify.confirm', function() {
|
||||
$.ajax({
|
||||
type: "PUT",
|
||||
url:"/isard-sso-admin/external/roles",
|
||||
url:"/api/external/roles",
|
||||
data: JSON.stringify({'ids':ids,'action':action}),
|
||||
success: function(data)
|
||||
{
|
||||
|
@ -132,7 +132,7 @@ $(document).ready(function() {
|
|||
//DataTable Main renderer
|
||||
var users_table = $('#users').DataTable({
|
||||
"ajax": {
|
||||
"url": "/isard-sso-admin/external_users_list",
|
||||
"url": "/api/external/users",
|
||||
"dataSrc": ""
|
||||
},
|
||||
"language": {
|
||||
|
@ -171,7 +171,7 @@ $(document).ready(function() {
|
|||
|
||||
var groups_table = $('#groups').DataTable({
|
||||
"ajax": {
|
||||
"url": "/isard-sso-admin/external_groups_list",
|
||||
"url": "/api/external/groups",
|
||||
"dataSrc": ""
|
||||
},
|
||||
"language": {
|
||||
|
|
|
@ -8,7 +8,7 @@ $(document).ready(function() {
|
|||
$('.btn-global-resync').on('click', function () {
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url:"/isard-sso-admin/resync",
|
||||
url:"api/resync",
|
||||
success: function(data)
|
||||
{
|
||||
table.ajax.reload();
|
||||
|
@ -39,7 +39,7 @@ $(document).ready(function() {
|
|||
console.log(formdata)
|
||||
// $.ajax({
|
||||
// type: "POST",
|
||||
// "url": "/isard-sso-admin/groups_list",
|
||||
// "url": "/groups_list",
|
||||
// success: function(data)
|
||||
// {
|
||||
// console.log('SUCCESS')
|
||||
|
@ -55,7 +55,7 @@ $(document).ready(function() {
|
|||
$('.btn-delete_keycloak').on('click', function () {
|
||||
$.ajax({
|
||||
type: "DELETE",
|
||||
url:"/isard-sso-admin/groups/keycloak",
|
||||
url:"/api/groups/keycloak",
|
||||
success: function(data)
|
||||
{
|
||||
console.log('SUCCESS')
|
||||
|
@ -73,7 +73,7 @@ $(document).ready(function() {
|
|||
//DataTable Main renderer
|
||||
var table = $('#groups').DataTable({
|
||||
"ajax": {
|
||||
"url": "/isard-sso-admin/groups_list",
|
||||
"url": "/api/groups",
|
||||
"dataSrc": ""
|
||||
},
|
||||
"language": {
|
||||
|
|
|
@ -8,7 +8,7 @@ $(document).ready(function() {
|
|||
$('.btn-global-resync').on('click', function () {
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url:"/isard-sso-admin/resync",
|
||||
url:"/api/resync",
|
||||
success: function(data)
|
||||
{
|
||||
table.ajax.reload();
|
||||
|
@ -35,7 +35,7 @@ $(document).ready(function() {
|
|||
//DataTable Main renderer
|
||||
var table = $('#roles').DataTable({
|
||||
"ajax": {
|
||||
"url": "/isard-sso-admin/roles_list",
|
||||
"url": "/api/roles",
|
||||
"dataSrc": ""
|
||||
},
|
||||
"language": {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
notice={}
|
||||
$lost=0;
|
||||
|
||||
socket = io.connect(location.protocol+'//' + document.domain +'/isard-sso-admin/sio');
|
||||
console.log(location.protocol+'//' + document.domain +'/isard-sso-admin/sio')
|
||||
socket = io.connect(location.protocol+'//' + document.domain +'/sio');
|
||||
console.log(location.protocol+'//' + document.domain +'/sio')
|
||||
socket.on('connect', function() {
|
||||
if($lost){location.reload();}
|
||||
console.log('Listening status socket');
|
||||
|
@ -32,6 +32,13 @@ socket.on('notify-destroy', function(data) {
|
|||
|
||||
socket.on('notify-update', function(data) {
|
||||
var data = JSON.parse(data);
|
||||
if(!( data.id in notice)){
|
||||
notice[data.id] = new PNotify({
|
||||
title: data.title,
|
||||
text: data.text,
|
||||
hide: false
|
||||
});
|
||||
}
|
||||
// console.log(data.text)
|
||||
notice[data.id].update({
|
||||
text: data.text
|
||||
|
|
|
@ -0,0 +1,443 @@
|
|||
|
||||
$(document).on('shown.bs.modal', '#modalAddDesktop', function () {
|
||||
modal_add_desktops.columns.adjust().draw();
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
"url": "/api/groups",
|
||||
success: function(data)
|
||||
{
|
||||
data.forEach(element => {
|
||||
var groupOrigins = [];
|
||||
['keycloak', 'moodle', 'nextcloud'].forEach(o => {
|
||||
if (element[o]) {
|
||||
groupOrigins.push(o)
|
||||
}
|
||||
})
|
||||
$(".groups-select").append(
|
||||
'<option value=' + element.path + '>' + element.name + ' (' + groupOrigins.join(',') + ') </option>'
|
||||
)
|
||||
});
|
||||
$('.groups-select').select2();
|
||||
},
|
||||
error: function(data)
|
||||
{
|
||||
alert('Something went wrong on our side...')
|
||||
}
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
"url": "/api/roles",
|
||||
success: function(data)
|
||||
{
|
||||
console.log('ROLES')
|
||||
console.log(data)
|
||||
data.forEach(element => {
|
||||
$(".role-moodle-select, .role-nextcloud-select, .role-keycloak-select").append(
|
||||
'<option value=' + element.id + '>' + element.name + '</option>'
|
||||
)
|
||||
})
|
||||
},
|
||||
error: function(data)
|
||||
{
|
||||
alert('Something went wrong on our side...')
|
||||
}
|
||||
});
|
||||
|
||||
$('.btn-global-resync').on('click', function () {
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url:"/api/resync",
|
||||
success: function(data)
|
||||
{
|
||||
console.log('Reloaded')
|
||||
table.ajax.reload();
|
||||
// $("#modalImport").modal('hide');
|
||||
// users_table.ajax.reload();
|
||||
// groups_table.ajax.reload();
|
||||
},
|
||||
error: function(data)
|
||||
{
|
||||
alert('Something went wrong on our side...')
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Open new user modal
|
||||
$('.btn-new-user').on('click', function () {
|
||||
$('#modalAddUser').modal({
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
}).modal('show');
|
||||
});
|
||||
|
||||
// Send new user form
|
||||
$('#modalAddUser #send').on('click', function () {
|
||||
var form = $('#modalAddUserForm');
|
||||
formdata = form.serializeObject()
|
||||
console.log('NEW USER')
|
||||
console.log(formdata)
|
||||
// $.ajax({
|
||||
// type: "POST",
|
||||
// "url": "/groups_list",
|
||||
// success: function(data)
|
||||
// {
|
||||
// console.log('SUCCESS')
|
||||
// // $("#modalAddUser").modal('hide');
|
||||
// },
|
||||
// error: function(data)
|
||||
// {
|
||||
// alert('Something went wrong on our side...')
|
||||
// }
|
||||
// });
|
||||
});
|
||||
|
||||
$('.btn-delete_keycloak').on('click', function () {
|
||||
$.ajax({
|
||||
type: "DELETE",
|
||||
url:"/api/users/keycloak",
|
||||
success: function(data)
|
||||
{
|
||||
console.log('SUCCESS')
|
||||
// $("#modalImport").modal('hide');
|
||||
// users_table.ajax.reload();
|
||||
// groups_table.ajax.reload();
|
||||
},
|
||||
error: function(data)
|
||||
{
|
||||
alert('Something went wrong on our side...')
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('.btn-delete_nextcloud').on('click', function () {
|
||||
$.ajax({
|
||||
type: "DELETE",
|
||||
url:"/api/users/nextcloud",
|
||||
success: function(data)
|
||||
{
|
||||
console.log('SUCCESS')
|
||||
// $("#modalImport").modal('hide');
|
||||
// users_table.ajax.reload();
|
||||
// groups_table.ajax.reload();
|
||||
},
|
||||
error: function(data)
|
||||
{
|
||||
alert('Something went wrong on our side...')
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('.btn-delete_moodle').on('click', function () {
|
||||
$.ajax({
|
||||
type: "DELETE",
|
||||
url:"/api/users/moodle",
|
||||
success: function(data)
|
||||
{
|
||||
console.log('SUCCESS')
|
||||
// $("#modalImport").modal('hide');
|
||||
// users_table.ajax.reload();
|
||||
// groups_table.ajax.reload();
|
||||
},
|
||||
error: function(data)
|
||||
{
|
||||
alert('Something went wrong on our side...')
|
||||
}
|
||||
});
|
||||
});
|
||||
$('.btn-sync_to_moodle').on('click', function () {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url:"/api/users/moodle",
|
||||
success: function(data)
|
||||
{
|
||||
console.log('SUCCESS')
|
||||
// $("#modalImport").modal('hide');
|
||||
// users_table.ajax.reload();
|
||||
// groups_table.ajax.reload();
|
||||
},
|
||||
error: function(data)
|
||||
{
|
||||
alert('Something went wrong on our side...')
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('.btn-sync_to_nextcloud').on('click', function () {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url:"/api/users/nextcloud",
|
||||
success: function(data)
|
||||
{
|
||||
console.log('SUCCESS')
|
||||
// $("#modalImport").modal('hide');
|
||||
// users_table.ajax.reload();
|
||||
// groups_table.ajax.reload();
|
||||
},
|
||||
error: function(data)
|
||||
{
|
||||
alert('Something went wrong on our side...')
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//DataTable Main renderer
|
||||
var table = $('#users').DataTable({
|
||||
"ajax": {
|
||||
"url": "/api/users",
|
||||
"dataSrc": ""
|
||||
},
|
||||
"language": {
|
||||
"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>"
|
||||
},
|
||||
"rowId": "id",
|
||||
"deferRender": true,
|
||||
"columns": [
|
||||
{
|
||||
"className": 'details-control',
|
||||
"orderable": false,
|
||||
"data": null,
|
||||
"width": "10px",
|
||||
"defaultContent": '<button class="btn btn-xs btn-info" type="button" data-placement="top" ><i class="fa fa-plus"></i></button>'
|
||||
},
|
||||
{ "data": "id", "width": "10px" },
|
||||
{ "data": "username", "width": "10px"},
|
||||
{ "data": "first", "width": "10px"},
|
||||
{ "data": "last", "width": "10px"},
|
||||
{ "data": "email", "width": "10px"},
|
||||
{ "data": "keycloak", "width": "10px" },
|
||||
{ "data": "keycloak_groups", "width": "10px" },
|
||||
{ "data": "roles", "width": "10px" },
|
||||
{ "data": "moodle", "width": "10px" },
|
||||
{ "data": "moodle_groups", "width": "10px" },
|
||||
{ "data": "nextcloud", "width": "10px" },
|
||||
{ "data": "nextcloud_groups", "width": "10px" },
|
||||
],
|
||||
"order": [[4, 'asc']],
|
||||
"columnDefs": [ {
|
||||
"targets": 1,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
return '<object data="/static/img/missing.jpg" type="image/jpg" width="25" height="25"><img src="/avatar/'+full.id+'" title="'+full.id+'" width="25" height="25"></object>'
|
||||
}},
|
||||
{
|
||||
"targets": 6,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
if(full.keycloak){
|
||||
return '<i class="fa fa-check" style="color:lightgreen"></i>'
|
||||
}else{
|
||||
return '<i class="fa fa-close" style="color:darkred"></i>'
|
||||
};
|
||||
}},
|
||||
{
|
||||
"targets": 7,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
return "<li>" + full.keycloak_groups.join("</li><li>") + "</li>"
|
||||
}},
|
||||
{
|
||||
"targets": 9,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
if(full.moodle){
|
||||
return '<i class="fa fa-check" style="color:lightgreen"></i>'
|
||||
}else{
|
||||
return '<i class="fa fa-close" style="color:darkred"></i>'
|
||||
};
|
||||
}},
|
||||
{
|
||||
"targets": 10,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
return "<li>" + full.moodle_groups.join("</li><li>") + "</li>"
|
||||
}},
|
||||
{
|
||||
"targets": 11,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
if(full.nextcloud){
|
||||
return '<i class="fa fa-check" style="color:lightgreen"></i>'
|
||||
}else{
|
||||
return '<i class="fa fa-close" style="color:darkred"></i>'
|
||||
};
|
||||
}},
|
||||
{
|
||||
"targets": 12,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
return "<li>" + full.nextcloud_groups.join("</li><li>") + "</li>"
|
||||
}},
|
||||
]
|
||||
} );
|
||||
|
||||
$template = $(".template-detail-users");
|
||||
|
||||
$('#users').find('tbody').on('click', 'td.details-control', function () {
|
||||
var tr = $(this).closest('tr');
|
||||
var row = table.row( tr );
|
||||
|
||||
if ( row.child.isShown() ) {
|
||||
// This row is already open - close it
|
||||
row.child.hide();
|
||||
tr.removeClass('shown');
|
||||
}
|
||||
else {
|
||||
// Close other rows
|
||||
if ( table.row( '.shown' ).length ) {
|
||||
$('.details-control', table.row( '.shown' ).node()).click();
|
||||
}
|
||||
// Open this row
|
||||
row.child( addUserDetailPannel(row.data()) ).show();
|
||||
tr.addClass('shown');
|
||||
actionsUserDetail()
|
||||
}
|
||||
} );
|
||||
|
||||
function addUserDetailPannel ( d ) {
|
||||
$newPanel = $template.clone();
|
||||
$newPanel.html(function(i, oldHtml){
|
||||
return oldHtml.replace(/d.id/g, d.id).replace(/d.username/g, d.username);
|
||||
});
|
||||
return $newPanel
|
||||
}
|
||||
|
||||
function actionsUserDetail(){
|
||||
|
||||
$('.btn-passwd').on('click', function () {
|
||||
var closest=$(this).closest("div").parent();
|
||||
var pk=closest.attr("data-pk");
|
||||
$("#modalPasswdUserForm")[0].reset();
|
||||
$('#modalPasswdUser').modal({
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
}).modal('show');
|
||||
$('#modalPasswdUserForm #id').val(pk);
|
||||
});
|
||||
|
||||
$("#modalPasswdUser #send").on('click', function(e){
|
||||
var form = $('#modalPasswdUserForm');
|
||||
form.parsley().validate();
|
||||
if (form.parsley().isValid()){
|
||||
data=$('#modalPasswdUserForm').serializeObject();
|
||||
data['id']=$('#modalPasswdUserForm #id').val();
|
||||
new PNotify({
|
||||
title: 'Confirmation Needed',
|
||||
text: "Are you sure you want to update password for the user "+ username+"?",
|
||||
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({
|
||||
type: "PUT",
|
||||
url:"/api/user" + id,
|
||||
success: function(data)
|
||||
{
|
||||
$(div_id + ' #id').val(data.id);
|
||||
$(div_id + ' #username').val(data.username);
|
||||
$(div_id + ' #email').val(data.email);
|
||||
$(div_id + ' #firstname').val(data.firstname);
|
||||
$(div_id + ' #lastname').val(data.lastname);
|
||||
$(div_id + ' .groups-select').val(data.groups);
|
||||
$(div_id + ' .role-moodle-select').val(data.roles);
|
||||
$(div_id + ' .role-nextcloud-select').val(data.roles);
|
||||
$(div_id + ' .role-keycloak-select').val(data.roles);
|
||||
$('.groups-select, .role-moodle-select, .role-nextcloud-select, .role-keycloak-select').trigger('change');
|
||||
}
|
||||
});
|
||||
}).on('pnotify.cancel', function() {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('.btn-edit').on('click', function () {
|
||||
var closest=$(this).closest("div").parent();
|
||||
var pk=closest.attr("data-pk");
|
||||
$("#modalEditUserForm")[0].reset();
|
||||
$('#modalEditUser').modal({
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
}).modal('show');
|
||||
setUserDefault('#modalEditUser', pk);
|
||||
$('#modalEdit').parsley();
|
||||
});
|
||||
|
||||
$("#modalEditUser #send").on('click', function(e){
|
||||
var form = $('#modalEditUserForm');
|
||||
form.parsley().validate();
|
||||
if (form.parsley().isValid()){
|
||||
data=$('#modalEditUserForm').serializeObject();
|
||||
data['id']=$('#modalEditUserForm #id').val();
|
||||
console.log('Editing user...')
|
||||
console.log(data)
|
||||
}
|
||||
});
|
||||
|
||||
$('.btn-delete').on('click', function () {
|
||||
var closest=$(this).closest("div").parent();
|
||||
var pk=closest.attr("data-pk");
|
||||
var username=closest.attr("data-username");
|
||||
console.log(username)
|
||||
new PNotify({
|
||||
title: 'Confirmation Needed',
|
||||
text: "Are you sure you want to delete the user: "+ username+"?",
|
||||
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('Deleting user...')
|
||||
}).on('pnotify.cancel', function() {
|
||||
});
|
||||
});
|
||||
}
|
||||
function setUserDefault(div_id, user_id) {
|
||||
// $.ajax({
|
||||
// type: "GET",
|
||||
// url:"/api/user/" + id,
|
||||
// success: function(data)
|
||||
// {
|
||||
// $(div_id + ' #id').val(data.id);
|
||||
// $(div_id + ' #username').val(data.username);
|
||||
// $(div_id + ' #email').val(data.email);
|
||||
// $(div_id + ' #firstname').val(data.firstname);
|
||||
// $(div_id + ' #lastname').val(data.lastname);
|
||||
// $(div_id + ' .groups-select').val(data.groups);
|
||||
// $(div_id + ' .role-moodle-select').val(data.roles);
|
||||
// $(div_id + ' .role-nextcloud-select').val(data.roles);
|
||||
// $(div_id + ' .role-keycloak-select').val(data.roles);
|
||||
// $('.groups-select, .role-moodle-select, .role-nextcloud-select, .role-keycloak-select').trigger('change');
|
||||
// }
|
||||
// });
|
||||
// MOCK
|
||||
$(div_id + ' #id').val('b57c8d3f-ee08-4a1d-9873-f40c082b9c69');
|
||||
$(div_id + ' #user-avatar').attr('src', '/static/img/usera.jpg');
|
||||
$(div_id + ' #username').val('yedcaqwvt');
|
||||
$(div_id + ' #email').val('yedcaqwvt@institutmariaespinalt.cat');
|
||||
$(div_id + ' #firstname').val('Ymisno');
|
||||
$(div_id + ' #lastname').val('Edcaqwvt tavnuoes');
|
||||
$(div_id + ' .groups-select').val(['student', 'manager']);
|
||||
$(div_id + ' .role-moodle-select').val('51cc1a95-94b7-48eb-aebb-1eba6745e09f');
|
||||
$(div_id + ' .role-nextcloud-select').val('1e21ec95-b8c7-43b8-baad-1a31ad33f388');
|
||||
$(div_id + ' .role-keycloak-select').val('13da53d5-c50b-42d9-8fbf-84f2ed7cbf9e');
|
||||
$('.groups-select, .role-moodle-select, .role-nextcloud-select, .role-keycloak-select').trigger('change');
|
||||
}
|
||||
});
|
|
@ -7,18 +7,18 @@ $(document).ready(function() {
|
|||
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
"url": "/isard-sso-admin/groups_list",
|
||||
"url": "/api/groups",
|
||||
success: function(data)
|
||||
{
|
||||
data.forEach(element => {
|
||||
var groupOrigins = [];
|
||||
['keycloak', 'moodle', 'nextcloud'].forEach(o => {
|
||||
['keycloak'].forEach(o => {
|
||||
if (element[o]) {
|
||||
groupOrigins.push(o)
|
||||
}
|
||||
})
|
||||
$(".groups-select").append(
|
||||
'<option value=' + element.path + '>' + element.name + ' (' + groupOrigins.join(',') + ') </option>'
|
||||
'<option value=' + element.path + '>' + element.name + '</option>'
|
||||
)
|
||||
});
|
||||
$('.groups-select').select2();
|
||||
|
@ -29,13 +29,35 @@ $(document).ready(function() {
|
|||
}
|
||||
});
|
||||
|
||||
// $.ajax({
|
||||
// type: "GET",
|
||||
// "url": "/api/groups",
|
||||
// success: function(data)
|
||||
// {
|
||||
// data.forEach(element => {
|
||||
// var groupOrigins = [];
|
||||
// ['keycloak', 'moodle', 'nextcloud'].forEach(o => {
|
||||
// if (element[o]) {
|
||||
// groupOrigins.push(o)
|
||||
// }
|
||||
// })
|
||||
// $(".groups-select").append(
|
||||
// '<option value=' + element.path + '>' + element.name + ' (' + groupOrigins.join(',') + ') </option>'
|
||||
// )
|
||||
// });
|
||||
// $('.groups-select').select2();
|
||||
// },
|
||||
// error: function(data)
|
||||
// {
|
||||
// alert('Something went wrong on our side...')
|
||||
// }
|
||||
// });
|
||||
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
"url": "/isard-sso-admin/roles_list",
|
||||
"url": "/api/roles",
|
||||
success: function(data)
|
||||
{
|
||||
console.log('ROLES')
|
||||
console.log(data)
|
||||
data.forEach(element => {
|
||||
$(".role-moodle-select, .role-nextcloud-select, .role-keycloak-select").append(
|
||||
'<option value=' + element.id + '>' + element.name + '</option>'
|
||||
|
@ -51,10 +73,9 @@ $(document).ready(function() {
|
|||
$('.btn-global-resync').on('click', function () {
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url:"/isard-sso-admin/resync",
|
||||
url:"/api/resync",
|
||||
success: function(data)
|
||||
{
|
||||
console.log('Reloaded')
|
||||
table.ajax.reload();
|
||||
// $("#modalImport").modal('hide');
|
||||
// users_table.ajax.reload();
|
||||
|
@ -83,7 +104,7 @@ $(document).ready(function() {
|
|||
console.log(formdata)
|
||||
// $.ajax({
|
||||
// type: "POST",
|
||||
// "url": "/isard-sso-admin/groups_list",
|
||||
// "url": "/groups_list",
|
||||
// success: function(data)
|
||||
// {
|
||||
// console.log('SUCCESS')
|
||||
|
@ -99,7 +120,7 @@ $(document).ready(function() {
|
|||
$('.btn-delete_keycloak').on('click', function () {
|
||||
$.ajax({
|
||||
type: "DELETE",
|
||||
url:"/isard-sso-admin/users/keycloak",
|
||||
url:"/api/users/keycloak",
|
||||
success: function(data)
|
||||
{
|
||||
console.log('SUCCESS')
|
||||
|
@ -117,7 +138,7 @@ $(document).ready(function() {
|
|||
$('.btn-delete_nextcloud').on('click', function () {
|
||||
$.ajax({
|
||||
type: "DELETE",
|
||||
url:"/isard-sso-admin/users/nextcloud",
|
||||
url:"/api/users/nextcloud",
|
||||
success: function(data)
|
||||
{
|
||||
console.log('SUCCESS')
|
||||
|
@ -135,7 +156,7 @@ $(document).ready(function() {
|
|||
$('.btn-delete_moodle').on('click', function () {
|
||||
$.ajax({
|
||||
type: "DELETE",
|
||||
url:"/isard-sso-admin/users/moodle",
|
||||
url:"/api/users/moodle",
|
||||
success: function(data)
|
||||
{
|
||||
console.log('SUCCESS')
|
||||
|
@ -152,7 +173,7 @@ $(document).ready(function() {
|
|||
$('.btn-sync_to_moodle').on('click', function () {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url:"/isard-sso-admin/users/moodle",
|
||||
url:"/api/users/moodle",
|
||||
success: function(data)
|
||||
{
|
||||
console.log('SUCCESS')
|
||||
|
@ -170,7 +191,7 @@ $(document).ready(function() {
|
|||
$('.btn-sync_to_nextcloud').on('click', function () {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url:"/isard-sso-admin/users/nextcloud",
|
||||
url:"/api/users/nextcloud",
|
||||
success: function(data)
|
||||
{
|
||||
console.log('SUCCESS')
|
||||
|
@ -188,84 +209,68 @@ $(document).ready(function() {
|
|||
//DataTable Main renderer
|
||||
var table = $('#users').DataTable({
|
||||
"ajax": {
|
||||
"url": "/isard-sso-admin/users_list",
|
||||
"url": "/api/users",
|
||||
"dataSrc": ""
|
||||
},
|
||||
"language": {
|
||||
"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>"
|
||||
},
|
||||
},
|
||||
"rowId": "id",
|
||||
"deferRender": true,
|
||||
"columns": [
|
||||
{
|
||||
"className": 'details-control',
|
||||
"orderable": false,
|
||||
"data": null,
|
||||
"width": "10px",
|
||||
"defaultContent": '<button class="btn btn-xs btn-info" type="button" data-placement="top" ><i class="fa fa-plus"></i></button>'
|
||||
},
|
||||
{"data": null, "defaultContent":'',"width": "1px"},
|
||||
// {
|
||||
// "className": 'details-control',
|
||||
// "orderable": false,
|
||||
// "data": null,
|
||||
// "width": "10px",
|
||||
// "defaultContent": '<button class="btn btn-xs btn-info" type="button" data-placement="top" ><i class="fa fa-plus"></i></button>'
|
||||
// },
|
||||
{ "data": "id", "width": "10px" },
|
||||
{ "data": "username", "width": "10px"},
|
||||
{ "data": "enabled", "width": "10px" },
|
||||
{ "data": "username", "width": "10px"},
|
||||
{
|
||||
"className": 'actions-control',
|
||||
"orderable": false,
|
||||
"data": null,
|
||||
"width": "80px",
|
||||
"defaultContent": '<button id="btn-edit" class="btn btn-xs" type="button" data-placement="top" ><i class="fa fa-pencil" style="color:darkblue"></i></button> \
|
||||
<button id="btn-delete" class="btn btn-xs" type="button" data-placement="top" ><i class="fa fa-times" style="color:darkred"></i></button> \
|
||||
<button id="btn-password" class="btn btn-xs" type="button" data-placement="top" ><i class="fa fa-lock" style="color:orange"></i></button>'
|
||||
},
|
||||
{ "data": "first", "width": "10px"},
|
||||
{ "data": "last", "width": "10px"},
|
||||
{ "data": "last", "width": "200px"},
|
||||
{ "data": "email", "width": "10px"},
|
||||
{ "data": "keycloak", "width": "10px" },
|
||||
{ "data": "keycloak_groups", "width": "10px" },
|
||||
{ "data": "roles", "width": "10px" },
|
||||
{ "data": "moodle", "width": "10px" },
|
||||
{ "data": "moodle_groups", "width": "10px" },
|
||||
{ "data": "nextcloud", "width": "10px" },
|
||||
{ "data": "nextcloud_groups", "width": "10px" },
|
||||
],
|
||||
"order": [[4, 'asc']],
|
||||
"order": [[6, 'asc']],
|
||||
"columnDefs": [ {
|
||||
"targets": 1,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
return '<img src="/isard-sso-admin/avatars/'+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">'
|
||||
}},
|
||||
{
|
||||
"targets": 6,
|
||||
"targets": 2,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
if(full.keycloak){
|
||||
if(full.enabled){
|
||||
return '<i class="fa fa-check" style="color:lightgreen"></i>'
|
||||
}else{
|
||||
return '<i class="fa fa-close" style="color:darkred"></i>'
|
||||
};
|
||||
}},
|
||||
{
|
||||
"targets": 7,
|
||||
"targets": 3,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
return '<b>'+full.username+'</b>'
|
||||
}},
|
||||
{
|
||||
"targets": 8,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
return "<li>" + full.keycloak_groups.join("</li><li>") + "</li>"
|
||||
}},
|
||||
{
|
||||
"targets": 9,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
if(full.moodle){
|
||||
return '<i class="fa fa-check" style="color:lightgreen"></i>'
|
||||
}else{
|
||||
return '<i class="fa fa-close" style="color:darkred"></i>'
|
||||
};
|
||||
}},
|
||||
{
|
||||
"targets": 10,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
return "<li>" + full.moodle_groups.join("</li><li>") + "</li>"
|
||||
}},
|
||||
{
|
||||
"targets": 11,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
if(full.nextcloud){
|
||||
return '<i class="fa fa-check" style="color:lightgreen"></i>'
|
||||
}else{
|
||||
return '<i class="fa fa-close" style="color:darkred"></i>'
|
||||
};
|
||||
}},
|
||||
{
|
||||
"targets": 12,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
return "<li>" + full.nextcloud_groups.join("</li><li>") + "</li>"
|
||||
}},
|
||||
]
|
||||
} );
|
||||
|
||||
|
@ -292,6 +297,117 @@ $(document).ready(function() {
|
|||
}
|
||||
} );
|
||||
|
||||
$('#users').find(' tbody').on( 'click', 'button', function () {
|
||||
var data = table.row( $(this).parents('tr') ).data();
|
||||
// var closest=$(this).closest("div").parent();
|
||||
// var pk=closest.attr("data-pk");
|
||||
// console.log(pk)
|
||||
switch($(this).attr('id')){
|
||||
case 'btn-edit':
|
||||
$("#modalEditUserForm")[0].reset();
|
||||
$('#modalEditUser').modal({
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
}).modal('show');
|
||||
$('#modalEditUser #user-avatar').attr("src","/avatar/"+data.id)
|
||||
setUserDefault('#modalEditUser', data.id);
|
||||
$('#modalEdit').parsley();
|
||||
break;
|
||||
case 'btn-delete':
|
||||
new PNotify({
|
||||
title: 'Confirmation Needed',
|
||||
text: "Are you sure you want to delete user: "+data['username']+"?",
|
||||
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/user/"+data.id,
|
||||
success: function(data)
|
||||
{
|
||||
table.ajax.reload();
|
||||
},
|
||||
error: function(data)
|
||||
{
|
||||
alert('Something went wrong on our side...')
|
||||
}
|
||||
});
|
||||
}).on('pnotify.cancel', function() {
|
||||
});
|
||||
break;
|
||||
case 'btn-password':
|
||||
$("#modalPasswdUserForm")[0].reset();
|
||||
$('#modalPasswdUser').modal({
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
}).modal('show');
|
||||
$('#modalPasswdUserForm #id').val(data.id);
|
||||
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url:"/api/user_password",
|
||||
success: function(data)
|
||||
{
|
||||
$('#modalPasswdUserForm #password').val(data);
|
||||
},
|
||||
error: function(data)
|
||||
{
|
||||
alert('Something went wrong on our side...')
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
$("#modalPasswdUser #send").on('click', function(e){
|
||||
var form = $('#modalPasswdUserForm');
|
||||
form.parsley().validate();
|
||||
if (form.parsley().isValid()){
|
||||
formdata=$('#modalPasswdUserForm').serializeObject();
|
||||
|
||||
id=$('#modalPasswdUserForm #id').val();
|
||||
$.ajax({
|
||||
type: "PUT",
|
||||
url:"/api/user//+" + id,
|
||||
data: JSON.stringify(formdata),
|
||||
success: function(data)
|
||||
{
|
||||
$("#modalPasswdUser").modal('hide');
|
||||
table.ajax.reload();
|
||||
// groups_table.ajax.reload();
|
||||
},
|
||||
error: function(data)
|
||||
{
|
||||
alert('Something went wrong on our side...')
|
||||
}
|
||||
// statusCode: {
|
||||
// 404: function(data) {
|
||||
// // {'error': 'description}. Not able to get responseJSON from received object
|
||||
// alert('User not exists in system!')
|
||||
// },
|
||||
// 200: function() {
|
||||
// console.log("Success");
|
||||
// }
|
||||
// },
|
||||
// error: function(data)
|
||||
// {
|
||||
// alert('Something went wrong on our side...')
|
||||
// }
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function addUserDetailPannel ( d ) {
|
||||
$newPanel = $template.clone();
|
||||
$newPanel.html(function(i, oldHtml){
|
||||
|
@ -302,39 +418,30 @@ $(document).ready(function() {
|
|||
|
||||
function actionsUserDetail(){
|
||||
|
||||
$('.btn-passwd').on('click', function () {
|
||||
var closest=$(this).closest("div").parent();
|
||||
var pk=closest.attr("data-pk");
|
||||
$("#modalPasswdUserForm")[0].reset();
|
||||
$('#modalPasswdUser').modal({
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
}).modal('show');
|
||||
$('#modalPasswdUserForm #id').val(pk);
|
||||
});
|
||||
// $('.btn-passwd').on('click', function () {
|
||||
// var closest=$(this).closest("div").parent();
|
||||
// var pk=closest.attr("data-pk");
|
||||
// $("#modalPasswdUserForm")[0].reset();
|
||||
// $('#modalPasswdUser').modal({
|
||||
// backdrop: 'static',
|
||||
// keyboard: false
|
||||
// }).modal('show');
|
||||
// $('#modalPasswdUserForm #id').val(pk);
|
||||
// });
|
||||
|
||||
$("#modalPasswdUser #send").on('click', function(e){
|
||||
var form = $('#modalPasswdUserForm');
|
||||
form.parsley().validate();
|
||||
if (form.parsley().isValid()){
|
||||
data=$('#modalPasswdUserForm').serializeObject();
|
||||
data['id']=$('#modalPasswdUserForm #id').val();
|
||||
console.log('Editing user password...')
|
||||
console.log(data)
|
||||
}
|
||||
});
|
||||
|
||||
$('.btn-edit').on('click', function () {
|
||||
var closest=$(this).closest("div").parent();
|
||||
var pk=closest.attr("data-pk");
|
||||
$("#modalEditUserForm")[0].reset();
|
||||
$('#modalEditUser').modal({
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
}).modal('show');
|
||||
setUserDefault('#modalEditUser', pk);
|
||||
$('#modalEdit').parsley();
|
||||
});
|
||||
|
||||
// $('.btn-edit').on('click', function () {
|
||||
// var closest=$(this).closest("div").parent();
|
||||
// var pk=closest.attr("data-pk");
|
||||
// $("#modalEditUserForm")[0].reset();
|
||||
// $('#modalEditUser').modal({
|
||||
// backdrop: 'static',
|
||||
// keyboard: false
|
||||
// }).modal('show');
|
||||
// setUserDefault('#modalEditUser', pk);
|
||||
// $('#modalEdit').parsley();
|
||||
// });
|
||||
|
||||
$("#modalEditUser #send").on('click', function(e){
|
||||
var form = $('#modalEditUserForm');
|
||||
|
@ -347,62 +454,64 @@ $(document).ready(function() {
|
|||
}
|
||||
});
|
||||
|
||||
$('.btn-delete').on('click', function () {
|
||||
var closest=$(this).closest("div").parent();
|
||||
var pk=closest.attr("data-pk");
|
||||
var username=closest.attr("data-username");
|
||||
console.log(username)
|
||||
new PNotify({
|
||||
title: 'Confirmation Needed',
|
||||
text: "Are you sure you want to delete the user: "+ username+"?",
|
||||
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('Deleting user...')
|
||||
}).on('pnotify.cancel', function() {
|
||||
});
|
||||
});
|
||||
// $('.btn-delete').on('click', function () {
|
||||
// var closest=$(this).closest("div").parent();
|
||||
// var pk=closest.attr("data-pk");
|
||||
// var username=closest.attr("data-username");
|
||||
// console.log(username)
|
||||
// new PNotify({
|
||||
// title: 'Confirmation Needed',
|
||||
// text: "Are you sure you want to delete the user: "+ username+"?",
|
||||
// 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('Deleting user...')
|
||||
// }).on('pnotify.cancel', function() {
|
||||
// });
|
||||
// });
|
||||
}
|
||||
function setUserDefault(div_id, user_id) {
|
||||
// $.ajax({
|
||||
// type: "GET",
|
||||
// url:"/isard-sso-admin/user/" + id,
|
||||
// success: function(data)
|
||||
// {
|
||||
// $(div_id + ' #id').val(data.id);
|
||||
// $(div_id + ' #username').val(data.username);
|
||||
// $(div_id + ' #email').val(data.email);
|
||||
// $(div_id + ' #firstname').val(data.firstname);
|
||||
// $(div_id + ' #lastname').val(data.lastname);
|
||||
// $(div_id + ' .groups-select').val(data.groups);
|
||||
// $(div_id + ' .role-moodle-select').val(data.roles);
|
||||
// $(div_id + ' .role-nextcloud-select').val(data.roles);
|
||||
// $(div_id + ' .role-keycloak-select').val(data.roles);
|
||||
// $('.groups-select, .role-moodle-select, .role-nextcloud-select, .role-keycloak-select').trigger('change');
|
||||
// }
|
||||
// });
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url:"/api/user/" + user_id,
|
||||
success: function(data)
|
||||
{
|
||||
$(div_id + ' #id').val(data.id);
|
||||
$(div_id + ' #username').val(data.username);
|
||||
$(div_id + ' #email').val(data.email);
|
||||
$(div_id + ' #firstname').val(data.first);
|
||||
$(div_id + ' #lastname').val(data.last);
|
||||
console.log(data.keycloak_groups)
|
||||
$(div_id + ' .groups-select').val(data.keycloak_groups);
|
||||
// $(div_id + ' .role-moodle-select').val(data.keycloak_roles);
|
||||
// $(div_id + ' .role-nextcloud-select').val(data.roles);
|
||||
$(div_id + ' .role-keycloak-select').val(data.keycloak_roles);
|
||||
$('.groups-select, .role-keycloak-select').trigger('change');
|
||||
// $('.groups-select, .role-moodle-select, .role-nextcloud-select, .role-keycloak-select').trigger('change');
|
||||
}
|
||||
});
|
||||
// MOCK
|
||||
$(div_id + ' #id').val('b57c8d3f-ee08-4a1d-9873-f40c082b9c69');
|
||||
$(div_id + ' #user-avatar').attr('src', 'static/img/usera.jpg');
|
||||
$(div_id + ' #username').val('yedcaqwvt');
|
||||
$(div_id + ' #email').val('yedcaqwvt@institutmariaespinalt.cat');
|
||||
$(div_id + ' #firstname').val('Ymisno');
|
||||
$(div_id + ' #lastname').val('Edcaqwvt tavnuoes');
|
||||
$(div_id + ' .groups-select').val(['student', 'manager']);
|
||||
$(div_id + ' .role-moodle-select').val('51cc1a95-94b7-48eb-aebb-1eba6745e09f');
|
||||
$(div_id + ' .role-nextcloud-select').val('1e21ec95-b8c7-43b8-baad-1a31ad33f388');
|
||||
$(div_id + ' .role-keycloak-select').val('13da53d5-c50b-42d9-8fbf-84f2ed7cbf9e');
|
||||
$('.groups-select, .role-moodle-select, .role-nextcloud-select, .role-keycloak-select').trigger('change');
|
||||
// $(div_id + ' #id').val('b57c8d3f-ee08-4a1d-9873-f40c082b9c69');
|
||||
// $(div_id + ' #user-avatar').attr('src', 'static/img/usera.jpg');
|
||||
// $(div_id + ' #username').val('yedcaqwvt');
|
||||
// $(div_id + ' #email').val('yedcaqwvt@institutmariaespinalt.cat');
|
||||
// $(div_id + ' #firstname').val('Ymisno');
|
||||
// $(div_id + ' #lastname').val('Edcaqwvt tavnuoes');
|
||||
// $(div_id + ' .groups-select').val(['student', 'manager']);
|
||||
// $(div_id + ' .role-moodle-select').val('51cc1a95-94b7-48eb-aebb-1eba6745e09f');
|
||||
// $(div_id + ' .role-nextcloud-select').val('1e21ec95-b8c7-43b8-baad-1a31ad33f388');
|
||||
// $(div_id + ' .role-keycloak-select').val('13da53d5-c50b-42d9-8fbf-84f2ed7cbf9e');
|
||||
// $('.groups-select, .role-moodle-select, .role-nextcloud-select, .role-keycloak-select').trigger('change');
|
||||
}
|
||||
});
|
|
@ -14,27 +14,27 @@
|
|||
<link rel="icon" type="image/png" href="favicon-32x32.png" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="favicon-16x16.png" sizes="16x16" />
|
||||
<!-- Fancytree -->
|
||||
<link href="/isard-sso-admin/static/vendor/fancytree/dist/skin-win8/ui.fancytree.css" rel="stylesheet">
|
||||
<link href="/static/vendor/fancytree/dist/skin-win8/ui.fancytree.css" rel="stylesheet">
|
||||
<!-- Bootstrap -->
|
||||
<link href="/isard-sso-admin/vendors/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/vendors/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<!-- Font Awesome -->
|
||||
<link href="/isard-sso-admin/vendors/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="/vendors/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||
<!-- ion.rangeSlider -->
|
||||
<link href="/isard-sso-admin/vendors/ion.rangeSlider/css/ion.rangeSlider.css" rel="stylesheet">
|
||||
<link href="/isard-sso-admin/vendors/ion.rangeSlider/css/ion.rangeSlider.skinFlat.css" rel="stylesheet">
|
||||
<link href="/vendors/ion.rangeSlider/css/ion.rangeSlider.css" rel="stylesheet">
|
||||
<link href="/vendors/ion.rangeSlider/css/ion.rangeSlider.skinFlat.css" rel="stylesheet">
|
||||
<!-- Datatables -->
|
||||
<link href="/isard-sso-admin/vendors/datatables.net-bs/css/dataTables.bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/vendors/datatables.net-bs/css/dataTables.bootstrap.min.css" rel="stylesheet">
|
||||
<!-- PNotify -->
|
||||
<link href="/isard-sso-admin/vendors/pnotify/dist/pnotify.css" media="all" rel="stylesheet" type="text/css" />
|
||||
<link href="/isard-sso-admin/vendors/pnotify/dist/pnotify.buttons.css" media="all" rel="stylesheet" type="text/css" />
|
||||
<link href="/vendors/pnotify/dist/pnotify.css" media="all" rel="stylesheet" type="text/css" />
|
||||
<link href="/vendors/pnotify/dist/pnotify.buttons.css" media="all" rel="stylesheet" type="text/css" />
|
||||
<!-- iCheck -->
|
||||
<link href="/isard-sso-admin/vendors/iCheck/skins/flat/green.css" rel="stylesheet">
|
||||
<link href="/isard-sso-admin/vendors/select2/dist/css/select2.min.css" rel="stylesheet">
|
||||
<link href="/vendors/iCheck/skins/flat/green.css" rel="stylesheet">
|
||||
<link href="/vendors/select2/dist/css/select2.min.css" rel="stylesheet">
|
||||
{% block css %}{% endblock %}
|
||||
<!-- Custom Theme Style -->
|
||||
<link href="/isard-sso-admin/build/css/custom.css" rel="stylesheet">
|
||||
<link href="/build/css/custom.css" rel="stylesheet">
|
||||
<!-- Isard Style Sheet-->
|
||||
<link href="/isard-sso-admin/static/dd.css" rel="stylesheet">
|
||||
<link href="/static/dd.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body class="nav-md">
|
||||
|
@ -64,44 +64,44 @@
|
|||
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="/isard-sso-admin/vendors/jquery/dist/jquery.js"></script>
|
||||
<script src="/vendors/jquery/dist/jquery.js"></script>
|
||||
<!-- Bootstrap -->
|
||||
<script src="/isard-sso-admin/vendors/bootstrap/dist/js/bootstrap.min.js"></script>
|
||||
<script src="/vendors/bootstrap/dist/js/bootstrap.min.js"></script>
|
||||
<!-- NProgress -->
|
||||
<script src="/isard-sso-admin/vendors/nprogress/nprogress.js"></script>
|
||||
<script src="/vendors/nprogress/nprogress.js"></script>
|
||||
<!-- Datatables -->
|
||||
<script src="/isard-sso-admin/vendors/datatables.net/js/jquery.dataTables.min.js"></script>
|
||||
<script src="/isard-sso-admin/vendors/datatables.net-bs/js/dataTables.bootstrap.min.js"></script>
|
||||
<script src="/vendors/datatables.net/js/jquery.dataTables.min.js"></script>
|
||||
<script src="/vendors/datatables.net-bs/js/dataTables.bootstrap.min.js"></script>
|
||||
<!-- Ion.RangeSlider -->
|
||||
<script src="/isard-sso-admin/vendors/ion.rangeSlider/js/ion.rangeSlider.min.js"></script>
|
||||
<script src="/vendors/ion.rangeSlider/js/ion.rangeSlider.min.js"></script>
|
||||
<!-- PNotify -->
|
||||
<script type="text/javascript" src="/isard-sso-admin/vendors/pnotify/dist/pnotify.js"></script>
|
||||
<script type="text/javascript" src="/isard-sso-admin/vendors/pnotify/dist/pnotify.confirm.js"></script>
|
||||
<script type="text/javascript" src="/isard-sso-admin/vendors/pnotify/dist/pnotify.buttons.js"></script>
|
||||
<script type="text/javascript" src="/vendors/pnotify/dist/pnotify.js"></script>
|
||||
<script type="text/javascript" src="/vendors/pnotify/dist/pnotify.confirm.js"></script>
|
||||
<script type="text/javascript" src="/vendors/pnotify/dist/pnotify.buttons.js"></script>
|
||||
<!-- validator -->
|
||||
<script src="/isard-sso-admin/vendors/validator/validator.js"></script>
|
||||
<script src="/vendors/validator/validator.js"></script>
|
||||
<!-- Parsley -->
|
||||
<script src="/isard-sso-admin/vendors/parsleyjs/dist/parsley.min.js"></script>
|
||||
<script src="/vendors/parsleyjs/dist/parsley.min.js"></script>
|
||||
<!-- moment -->
|
||||
<script src="/isard-sso-admin/vendors/moment/min/moment.min.js"></script>
|
||||
<script src="/vendors/moment/min/moment.min.js"></script>
|
||||
<!-- validator -->
|
||||
<script src="/isard-sso-admin/vendors/iCheck/icheck.min.js"></script>
|
||||
<script src="/vendors/iCheck/icheck.min.js"></script>
|
||||
<!-- bootstrap-progressbar -->
|
||||
<script src="/isard-sso-admin/vendors/bootstrap-progressbar/bootstrap-progressbar.min.js"></script>
|
||||
<script src="/vendors/bootstrap-progressbar/bootstrap-progressbar.min.js"></script>
|
||||
<!-- ECharts -->
|
||||
<script src="/isard-sso-admin/vendors/echarts/dist/echarts.min.js"></script>
|
||||
<script src="/vendors/echarts/dist/echarts.min.js"></script>
|
||||
<!-- Select2 -->
|
||||
<script src="/isard-sso-admin/vendors/select2/dist/js/select2.full.min.js"></script>
|
||||
<script src="/vendors/select2/dist/js/select2.full.min.js"></script>
|
||||
<!-- SocketIO -->
|
||||
<script src="/isard-sso-admin/static/vendor/socket.io-2.3.1.slim.js"></script>
|
||||
<script src="/isard-sso-admin/static/js/status_socket.js"></script>
|
||||
<script src="/static/vendor/socket.io-2.3.1.slim.js"></script>
|
||||
<script src="/static/js/status_socket.js"></script>
|
||||
|
||||
<!-- isard initializers -->
|
||||
<script src="/isard-sso-admin/static/dd.js"></script>
|
||||
<script src="/static/dd.js"></script>
|
||||
<!-- Requirements for fancy tree -->
|
||||
<script src="/isard-sso-admin/static/vendor/fancytree/src/jquery-ui-dependencies/jquery-ui.min.js"></script>
|
||||
<script src="/isard-sso-admin/static/vendor/fancytree/dist/jquery.fancytree.min.js"></script>
|
||||
<script src="/isard-sso-admin/static/vendor/fancytree/src/jquery.fancytree.table.js"></script>
|
||||
<script src="/static/vendor/fancytree/src/jquery-ui-dependencies/jquery-ui.min.js"></script>
|
||||
<script src="/static/vendor/fancytree/dist/jquery.fancytree.min.js"></script>
|
||||
<script src="/static/vendor/fancytree/src/jquery.fancytree.table.js"></script>
|
||||
<!-- flashed messages with pnotify -->
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
|
@ -112,7 +112,7 @@
|
|||
text: "{{ message }}",
|
||||
hide: true,
|
||||
delay: 2000,
|
||||
//~ icon: 'fa fa-alert-sign',
|
||||
/~ icon: 'fa fa-alert-sign',
|
||||
opacity: 1,
|
||||
type: "{{ category }}",
|
||||
addclass: "pnotify-center"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<footer>
|
||||
<div class="pull-right">
|
||||
Digital Democratic - Administration | <a href="https://gitlab.com/digitaldemocratic/digitaldemocratic">gitlab</a>
|
||||
Digital Democratic - Administration | <a href="https:/gitlab.com/digitaldemocratic/digitaldemocratic">gitlab</a>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</footer>
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="">
|
||||
<a href="javascript:" class="user-profile dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
|
||||
<img src="/isard-sso-admin/static/img/user.png" alt="..." >
|
||||
<img src="/static/img/user.png" alt="..." >
|
||||
<span class=" fa fa-angle-down"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-usermenu pull-right">
|
||||
<li><a href="/isard-sso-admin/profile"><i class="fa fa-gear pull-right"></i> Profile</a></li>
|
||||
<li><a href="/isard-sso-admin/logout"><i class="fa fa-sign-out pull-right"></i> Log Out</a></li>
|
||||
<li><a href="/profile"><i class="fa fa-gear pull-right"></i> Profile</a></li>
|
||||
<li><a href="/logout"><i class="fa fa-sign-out pull-right"></i> Log Out</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
|
|
@ -10,16 +10,16 @@
|
|||
<title>Login | Digital Democratic</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link href="/isard-sso-admin/vendors/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/vendors/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<!-- Font Awesome -->
|
||||
<link href="/isard-sso-admin/vendors/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="/vendors/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||
<!-- Animate.css -->
|
||||
<link href="/isard-sso-admin/vendors/animate.css/animate.min.css" rel="stylesheet">
|
||||
<link href="/vendors/animate.css/animate.min.css" rel="stylesheet">
|
||||
<!-- PNotify -->
|
||||
<link href="/isard-sso-admin/vendors/pnotify/dist/pnotify.css" media="all" rel="stylesheet" type="text/css" />
|
||||
<link href="/isard-sso-admin/vendors/pnotify/dist/pnotify.buttons.css" media="all" rel="stylesheet" type="text/css" />
|
||||
<link href="/vendors/pnotify/dist/pnotify.css" media="all" rel="stylesheet" type="text/css" />
|
||||
<link href="/vendors/pnotify/dist/pnotify.buttons.css" media="all" rel="stylesheet" type="text/css" />
|
||||
<!-- Custom Theme Style -->
|
||||
<link href="/isard-sso-admin/build/css/custom.min.css" rel="stylesheet">
|
||||
<link href="/build/css/custom.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body class="login">
|
||||
|
@ -47,7 +47,7 @@
|
|||
|
||||
<div>
|
||||
<h1><i class="fa fa-user"></i> Digital Democratic</h1>
|
||||
<p>©2020 All Rights Reserved. <a href="https://gitlab.com/digitaldemocratic/digitaldemocratic/LICENSE" target="_blank">AGPLv3</a></p>
|
||||
<p>©2020 All Rights Reserved. <a href="https:/gitlab.com/digitaldemocratic/digitaldemocratic/LICENSE" target="_blank">AGPLv3</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -58,11 +58,11 @@
|
|||
</body>
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="/isard-sso-admin/vendors/jquery/dist/jquery.min.js"></script>
|
||||
<script src="/vendors/jquery/dist/jquery.min.js"></script>
|
||||
<!-- PNotify -->
|
||||
<script type="text/javascript" src="/isard-sso-admin/vendors/pnotify/dist/pnotify.js"></script>
|
||||
<script type="text/javascript" src="/isard-sso-admin/vendors/pnotify/dist/pnotify.confirm.js"></script>
|
||||
<script type="text/javascript" src="/isard-sso-admin/vendors/pnotify/dist/pnotify.buttons.js"></script>
|
||||
<script type="text/javascript" src="/vendors/pnotify/dist/pnotify.js"></script>
|
||||
<script type="text/javascript" src="/vendors/pnotify/dist/pnotify.confirm.js"></script>
|
||||
<script type="text/javascript" src="/vendors/pnotify/dist/pnotify.buttons.js"></script>
|
||||
<script>PNotify.prototype.options.styling = "bootstrap3";</script>
|
||||
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
|
@ -73,7 +73,7 @@
|
|||
title: "{{ nav }}",
|
||||
text: "{{ message }}",
|
||||
hide: true,
|
||||
//~ icon: 'fa fa-alert-sign',
|
||||
/~ icon: 'fa fa-alert-sign',
|
||||
opacity: 1,
|
||||
type: "error",
|
||||
addclass: "pnotify-center"
|
||||
|
@ -83,5 +83,5 @@
|
|||
{% endif %}
|
||||
{% endwith %}
|
||||
<!-- Isard restful ajax calls -->
|
||||
<script src="/isard-sso-admin/static/js/restful.js"></script>
|
||||
<script src="/static/js/restful.js"></script>
|
||||
</html>
|
||||
|
|
|
@ -10,14 +10,14 @@
|
|||
<title>Page not found! | Digital Democratic</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link href="../isard-sso-admin/vendors/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../vendors/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<!-- Font Awesome -->
|
||||
<link href="../isard-sso-admin/vendors/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="../vendors/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||
<!-- NProgress -->
|
||||
<link href="../isard-sso-admin/vendors/nprogress/nprogress.css" rel="stylesheet">
|
||||
<link href="../vendors/nprogress/nprogress.css" rel="stylesheet">
|
||||
|
||||
<!-- Custom Theme Style -->
|
||||
<link href="../isard-sso-admin/build/css/custom.min.css" rel="stylesheet">
|
||||
<link href="../build/css/custom.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body class="nav-md">
|
||||
|
@ -29,8 +29,8 @@
|
|||
<div class="text-center text-center">
|
||||
<h1 class="error-number">404</h1>
|
||||
<h2>Sorry but we couldn't find this page</h2>
|
||||
<p>This page you are looking for does not exist <a href="https://gitlab.com/digitaldemocratic/digitaldemocratic">Report this?</a>
|
||||
<a href="/isard-sso-admin/login">Go back to login page</a>
|
||||
<p>This page you are looking for does not exist <a href="https:/gitlab.com/digitaldemocratic/digitaldemocratic">Report this?</a>
|
||||
<a href="/login">Go back to login page</a>
|
||||
</p>
|
||||
<!--
|
||||
<div class="mid_center">
|
||||
|
@ -55,15 +55,15 @@
|
|||
</div>
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="../isard-sso-admin/vendors/jquery/dist/jquery.min.js"></script>
|
||||
<script src="../vendors/jquery/dist/jquery.min.js"></script>
|
||||
<!-- Bootstrap -->
|
||||
<script src="../isard-sso-admin/vendors/bootstrap/dist/js/bootstrap.min.js"></script>
|
||||
<script src="../vendors/bootstrap/dist/js/bootstrap.min.js"></script>
|
||||
<!-- FastClick -->
|
||||
<script src="../isard-sso-admin/vendors/fastclick/lib/fastclick.js"></script>
|
||||
<script src="../vendors/fastclick/lib/fastclick.js"></script>
|
||||
<!-- NProgress -->
|
||||
<script src="../isard-sso-admin/vendors/nprogress/nprogress.js"></script>
|
||||
<script src="../vendors/nprogress/nprogress.js"></script>
|
||||
|
||||
<!-- Custom Theme Scripts -->
|
||||
<script src="../isard-sso-admin/build/js/custom.min.js"></script>
|
||||
<script src="../build/js/custom.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -10,14 +10,14 @@
|
|||
<title>Page not allowed! | Digital Democratic</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link href="../isard-sso-admin/vendors/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../vendors/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<!-- Font Awesome -->
|
||||
<link href="../isard-sso-admin/vendors/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="../vendors/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||
<!-- NProgress -->
|
||||
<link href="../isard-sso-admin/vendors/nprogress/nprogress.css" rel="stylesheet">
|
||||
<link href="../vendors/nprogress/nprogress.css" rel="stylesheet">
|
||||
|
||||
<!-- Custom Theme Style -->
|
||||
<link href="../isard-sso-admin/build/css/custom.min.css" rel="stylesheet">
|
||||
<link href="../build/css/custom.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body class="nav-md">
|
||||
|
@ -29,8 +29,8 @@
|
|||
<div class="text-center">
|
||||
<h1 class="error-number">500</h1>
|
||||
<h2>Internal Server Error</h2>
|
||||
<p>We track these errors automatically, but if the problem persists feel free to contact us. In the meantime, try refreshing. <a href="https://gitlab.com/digitaldemocratic/digitaldemocratic">Report this?</a>
|
||||
<a href="/isard-sso-admin/login">Go back to login page</a>
|
||||
<p>We track these errors automatically, but if the problem persists feel free to contact us. In the meantime, try refreshing. <a href="https:/gitlab.com/digitaldemocratic/digitaldemocratic">Report this?</a>
|
||||
<a href="/login">Go back to login page</a>
|
||||
</p>
|
||||
<!--
|
||||
<div class="mid_center">
|
||||
|
@ -55,15 +55,15 @@
|
|||
</div>
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="../isard-sso-admin/vendors/jquery/dist/jquery.min.js"></script>
|
||||
<script src="../vendors/jquery/dist/jquery.min.js"></script>
|
||||
<!-- Bootstrap -->
|
||||
<script src="../isard-sso-admin/vendors/bootstrap/dist/js/bootstrap.min.js"></script>
|
||||
<script src="../vendors/bootstrap/dist/js/bootstrap.min.js"></script>
|
||||
<!-- FastClick -->
|
||||
<script src="../isard-sso-admin/vendors/fastclick/lib/fastclick.js"></script>
|
||||
<script src="../vendors/fastclick/lib/fastclick.js"></script>
|
||||
<!-- NProgress -->
|
||||
<script src="../isard-sso-admin/vendors/nprogress/nprogress.js"></script>
|
||||
<script src="../vendors/nprogress/nprogress.js"></script>
|
||||
|
||||
<!-- Custom Theme Scripts -->
|
||||
<script src="../isard-sso-admin/build/js/custom.min.js"></script>
|
||||
<script src="../build/js/custom.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -6,19 +6,19 @@
|
|||
<div class="col-md-12 col-sm-12 col-xs-12">
|
||||
<div class="x_panel">
|
||||
<div class="container for-about text-center" style="margin-top: 15px;">
|
||||
<img src="/isard-sso-admin/static/img/dd.svg" width="250px" height="250px">
|
||||
<img src="/static/img/dd.svg" width="250px" height="250px">
|
||||
<h1>Digital Democratic</h1>
|
||||
<h1><small>Schools apps integrations</small></h1>
|
||||
<div class="row" style="margin-top: 40px;">
|
||||
<div class="col-lg-2 col-md-12 col-sm-12 col-xs-12"></div>
|
||||
<div class="col-lg-2 col-md-6 col-sm-6 col-xs-12">
|
||||
<a href="https://gitlab.com/digitaldemocratic/digitaldemocratic" target="_blank" style="color: deepskyblue">
|
||||
<a href="https:/gitlab.com/digitaldemocratic/digitaldemocratic" target="_blank" style="color: deepskyblue">
|
||||
<i class="fa fa-globe" style="font-size: 125px;" aria-hidden="true"></i>
|
||||
<h1><small>Visit website</small></h1>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-lg-2 col-md-6 col-sm-6 col-xs-12">
|
||||
<a href="https://gitlab.com/digitaldemocratic/digitaldemocratic/-/issues" target="_blank" style="color: orange">
|
||||
<a href="https:/gitlab.com/digitaldemocratic/digitaldemocratic/-/issues" target="_blank" style="color: orange">
|
||||
<i class="fa fa-gitlab fa-5x" style="font-size: 125px;" aria-hidden="true"></i>
|
||||
<h1><small>Open an issue</small></h1>
|
||||
</a>
|
||||
|
@ -38,7 +38,7 @@
|
|||
</h1>
|
||||
</div>
|
||||
<div class="col-md-2 col-sm-6 col-xs-12">
|
||||
<p><img src="/isard-sso-admin/static/img/agplv3-155x51.png" style="margin-top: 60px;"></p>
|
||||
<p><img src="/static/img/agplv3-155x51.png" style="margin-top: 60px;"></p>
|
||||
<h1 style="margin-top: 25px;"><small>License</small></h1>
|
||||
</div>
|
||||
<div class="col-md-4 col-sm-4 col-xs-4"></div>
|
||||
|
@ -51,7 +51,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block pagescript %}
|
||||
<script src="/isard-sso-admin/static/js/restful.js"></script>
|
||||
<script src="/static/js/restful.js"></script>
|
||||
|
||||
<script src="/isard-sso-admin/static/js/status_socket.js"></script>
|
||||
<script src="/static/js/status_socket.js"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
{% extends "base.html" %}
|
||||
{% block css %}
|
||||
<!-- Ion.RangeSlider -->
|
||||
<link href="/isard-sso-admin/vendors/normalize-css/normalize.css" rel="stylesheet">
|
||||
<link href="/vendors/normalize-css/normalize.css" rel="stylesheet">
|
||||
<!-- Switchery -->
|
||||
<link href="/isard-sso-admin/vendors/switchery/dist/switchery.min.css" rel="stylesheet">
|
||||
<link href="/vendors/switchery/dist/switchery.min.css" rel="stylesheet">
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
|
@ -49,11 +49,11 @@
|
|||
|
||||
{% block pagescript %}
|
||||
<!-- Ion.RangeSlider -->
|
||||
<script src="/isard-sso-admin/vendors/ion.rangeSlider/js/ion.rangeSlider.min.js"></script>
|
||||
<script src="/vendors/ion.rangeSlider/js/ion.rangeSlider.min.js"></script>
|
||||
<!-- iCheck -->
|
||||
<script src="/isard-sso-admin/vendors/iCheck/icheck.min.js"></script>
|
||||
<script src="/vendors/iCheck/icheck.min.js"></script>
|
||||
<!-- Switchery -->
|
||||
<script src="/isard-sso-admin/vendors/switchery/dist/switchery.min.js"></script>
|
||||
<script src="/vendors/switchery/dist/switchery.min.js"></script>
|
||||
<!-- Desktops sse & modals -->
|
||||
<script src="/isard-sso-admin/static/js/groups.js"></script>
|
||||
<script src="/static/js/groups.js"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -115,6 +115,11 @@
|
|||
<div class="modal-body">
|
||||
<form id="modalPasswdUserForm" class="form-inline form-label-left">
|
||||
<div class="x_content" style="padding: 0px;">
|
||||
<div class="row">
|
||||
This is a proposed password.<br>
|
||||
Change it for the one desired for this user. <br>
|
||||
REMEMBER TO COPY THIS PASSWORD AS IT IS THE ONLY TIME YOU WILL SEE IT
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12 col-xs-12">
|
||||
<input id="id" hidden/>
|
||||
|
@ -211,7 +216,7 @@
|
|||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12 col-xs-12">
|
||||
<label class="control-label" for="id">Group</label>
|
||||
<label class="control-label" for="id">Groups</label>
|
||||
<select class="groups-select roundbox" name="groups[]" multiple="multiple" style="width:100%">
|
||||
</select>
|
||||
</div>
|
||||
|
@ -225,7 +230,7 @@
|
|||
</div>
|
||||
<div class="x_content" style="padding: 0px;">
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-xs-12">
|
||||
<!-- <div class="col-md-4 col-xs-12">
|
||||
<label class="control-label" for="id">Moodle</label>
|
||||
<select class="role-moodle-select" name="moodle" style="width:100%">
|
||||
</select>
|
||||
|
@ -234,9 +239,9 @@
|
|||
<label class="control-label" for="id">Nextcloud</label>
|
||||
<select class="role-nextcloud-select" name="nextcloud" style="width:100%">
|
||||
</select>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="col-md-4 col-xs-12">
|
||||
<label class="control-label" for="id">Keycloak</label>
|
||||
<label class="control-label" for="id">Role</label>
|
||||
<select class="role-keycloak-select" name="keycloak" style="width:100%">
|
||||
</select>
|
||||
</div>
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
{% extends "base.html" %}
|
||||
{% block css %}
|
||||
<!-- Ion.RangeSlider -->
|
||||
<link href="/isard-sso-admin/vendors/normalize-css/normalize.css" rel="stylesheet">
|
||||
<link href="/vendors/normalize-css/normalize.css" rel="stylesheet">
|
||||
<!-- Switchery -->
|
||||
<link href="/isard-sso-admin/vendors/switchery/dist/switchery.min.css" rel="stylesheet">
|
||||
<link href="/vendors/switchery/dist/switchery.min.css" rel="stylesheet">
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
|
@ -42,11 +42,11 @@
|
|||
|
||||
{% block pagescript %}
|
||||
<!-- Ion.RangeSlider -->
|
||||
<script src="/isard-sso-admin/vendors/ion.rangeSlider/js/ion.rangeSlider.min.js"></script>
|
||||
<script src="/vendors/ion.rangeSlider/js/ion.rangeSlider.min.js"></script>
|
||||
<!-- iCheck -->
|
||||
<script src="/isard-sso-admin/vendors/iCheck/icheck.min.js"></script>
|
||||
<script src="/vendors/iCheck/icheck.min.js"></script>
|
||||
<!-- Switchery -->
|
||||
<script src="/isard-sso-admin/vendors/switchery/dist/switchery.min.js"></script>
|
||||
<script src="/vendors/switchery/dist/switchery.min.js"></script>
|
||||
<!-- Desktops sse & modals -->
|
||||
<script src="/isard-sso-admin/static/js/roles.js"></script>
|
||||
<script src="/static/js/roles.js"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
{% extends "base.html" %}
|
||||
{% block css %}
|
||||
<!-- Ion.RangeSlider -->
|
||||
<link href="/isard-sso-admin/vendors/normalize-css/normalize.css" rel="stylesheet">
|
||||
<link href="/vendors/normalize-css/normalize.css" rel="stylesheet">
|
||||
<!-- Switchery -->
|
||||
<link href="/isard-sso-admin/vendors/switchery/dist/switchery.min.css" rel="stylesheet">
|
||||
<link href="/vendors/switchery/dist/switchery.min.css" rel="stylesheet">
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
|
@ -72,16 +72,16 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{% include 'pages/modals/external_modals.html' %}
|
||||
{% include 'pages/sysadmin/modals/external_modals.html' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block pagescript %}
|
||||
<!-- Ion.RangeSlider -->
|
||||
<script src="/isard-sso-admin/vendors/ion.rangeSlider/js/ion.rangeSlider.min.js"></script>
|
||||
<script src="/vendors/ion.rangeSlider/js/ion.rangeSlider.min.js"></script>
|
||||
<!-- iCheck -->
|
||||
<script src="/isard-sso-admin/vendors/iCheck/icheck.min.js"></script>
|
||||
<script src="/vendors/iCheck/icheck.min.js"></script>
|
||||
<!-- Switchery -->
|
||||
<script src="/isard-sso-admin/vendors/switchery/dist/switchery.min.js"></script>
|
||||
<script src="/vendors/switchery/dist/switchery.min.js"></script>
|
||||
<!-- Desktops sse & modals -->
|
||||
<script src="/isard-sso-admin/static/js/external.js"></script>
|
||||
<script src="/static/js/external.js"></script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,81 @@
|
|||
<!-- extend base layout -->
|
||||
{% extends "base.html" %}
|
||||
{% block css %}
|
||||
<!-- Ion.RangeSlider -->
|
||||
<link href="/vendors/normalize-css/normalize.css" rel="stylesheet">
|
||||
<!-- Switchery -->
|
||||
<link href="/vendors/switchery/dist/switchery.min.css" rel="stylesheet">
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12 col-sm-12 col-xs-12">
|
||||
<div class="x_panel">
|
||||
<div class="x_title">
|
||||
<h3><i class="fa fa-user"></i> Users</h3>
|
||||
<ul class="nav navbar-right panel_toolbox">
|
||||
<li>
|
||||
<a class="btn-new-user"><span style="color: #5499c7; "><i class="fa fa-plus"></i> Add new</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="x_content">
|
||||
<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>
|
||||
{% if current_user.role =='sysadmin' %}
|
||||
<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%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Avatar</th>
|
||||
<th>Username</th>
|
||||
<th>First</th>
|
||||
<th>Last</th>
|
||||
<th>email</th>
|
||||
<th>Keycloak</th>
|
||||
<th>K.Groups</th>
|
||||
<th>K.Roles</th>
|
||||
<th>Moodle</th>
|
||||
<th>M.Groups</th>
|
||||
<th>Nextcloud</th>
|
||||
<th>N.Groups</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'pages/modals/users_modals.html' %}
|
||||
{% include 'pages/users_detail.html' %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block pagescript %}
|
||||
<!-- Ion.RangeSlider -->
|
||||
<script src="/vendors/ion.rangeSlider/js/ion.rangeSlider.min.js"></script>
|
||||
<!-- iCheck -->
|
||||
<script src="/vendors/iCheck/icheck.min.js"></script>
|
||||
<!-- Switchery -->
|
||||
<script src="/vendors/switchery/dist/switchery.min.js"></script>
|
||||
<!-- Desktops sse & modals -->
|
||||
<script src="/static/js/sysadmin/users.js"></script>
|
||||
{% endblock %}
|
|
@ -2,9 +2,9 @@
|
|||
{% extends "base.html" %}
|
||||
{% block css %}
|
||||
<!-- Ion.RangeSlider -->
|
||||
<link href="/isard-sso-admin/vendors/normalize-css/normalize.css" rel="stylesheet">
|
||||
<link href="/vendors/normalize-css/normalize.css" rel="stylesheet">
|
||||
<!-- Switchery -->
|
||||
<link href="/isard-sso-admin/vendors/switchery/dist/switchery.min.css" rel="stylesheet">
|
||||
<link href="/vendors/switchery/dist/switchery.min.css" rel="stylesheet">
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
|
@ -21,13 +21,13 @@
|
|||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<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>
|
||||
{% if current_user.role =='admin-keycloak' %}
|
||||
<button class="btn btn-danger btn-xs btn-delete_keycloak">
|
||||
<i class="fa fa-trash"></i> Delete all keycloak
|
||||
</button>
|
||||
|
@ -43,17 +43,15 @@
|
|||
<tr>
|
||||
<th></th>
|
||||
<th>Avatar</th>
|
||||
<th>Enabled</th>
|
||||
<th>Username</th>
|
||||
<th>Actions</th>
|
||||
<th>First</th>
|
||||
<th>Last</th>
|
||||
<th>email</th>
|
||||
<th>Keycloak</th>
|
||||
<th>K.Groups</th>
|
||||
<th>K.Roles</th>
|
||||
<th>Moodle</th>
|
||||
<th>M.Groups</th>
|
||||
<th>Nextcloud</th>
|
||||
<th>N.Groups</th>
|
||||
<th>Email</th>
|
||||
<th>Groups</th>
|
||||
<th>Roles</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -71,11 +69,11 @@
|
|||
|
||||
{% block pagescript %}
|
||||
<!-- Ion.RangeSlider -->
|
||||
<script src="/isard-sso-admin/vendors/ion.rangeSlider/js/ion.rangeSlider.min.js"></script>
|
||||
<script src="/vendors/ion.rangeSlider/js/ion.rangeSlider.min.js"></script>
|
||||
<!-- iCheck -->
|
||||
<script src="/isard-sso-admin/vendors/iCheck/icheck.min.js"></script>
|
||||
<script src="/vendors/iCheck/icheck.min.js"></script>
|
||||
<!-- Switchery -->
|
||||
<script src="/isard-sso-admin/vendors/switchery/dist/switchery.min.js"></script>
|
||||
<script src="/vendors/switchery/dist/switchery.min.js"></script>
|
||||
<!-- Desktops sse & modals -->
|
||||
<script src="/isard-sso-admin/static/js/users.js"></script>
|
||||
<script src="/static/js/users.js"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="navbar nav_title" style="border: 0;">
|
||||
<a href="/isard-sso-admin/about" class="site_title">
|
||||
<img src="/isard-sso-admin/static/img/dd.svg" class="sidebar_logo logo_white" alt="dd">
|
||||
<a href="/about" class="site_title">
|
||||
<img src="/custom/img/logo.png" class="sidebar_logo logo_white" alt="dd">
|
||||
<span>Digital Democratic</span>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -13,13 +13,19 @@
|
|||
<div class="clearfix"></div>
|
||||
<ul class="nav side-menu">
|
||||
<li><a class="btn-global-resync"><span style="color: #c75454; "><i class="fa fa-refresh"></i> Resync</span></a></li>
|
||||
<li><a href="/isard-sso-admin/users"><i class="fa fa-user"></i> Users</a></li>
|
||||
<li><a href="/isard-sso-admin/groups"><i class="fa fa-users"></i> Groups</a></li>
|
||||
<li><a href="/isard-sso-admin/roles"><i class="fa fa-user-secret"></i> Roles</a></li>
|
||||
<li><a href="/isard-sso-admin/external"><i class="fa fa-external-link"></i> External</a></li>
|
||||
<li><a href="/users"><i class="fa fa-user"></i> Users</a></li>
|
||||
<li><a href="/groups"><i class="fa fa-users"></i> Groups</a></li>
|
||||
<li><a href="/roles"><i class="fa fa-user-secret"></i> Roles</a></li>
|
||||
|
||||
{% if current_user.role == 'admin' %}
|
||||
<h3>System Admin</h3>
|
||||
<div class="clearfix"></div>
|
||||
<li><a href="/sysadmin/users"><i class="fa fa-user"></i> SysAdminUsers</span></a></li>
|
||||
<li><a href="/sysadmin/external"><i class="fa fa-external-link"></i> External</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<ul class="nav side-menu">
|
||||
<li><a href="/isard-sso-admin/about"><i class="fa fa-question"></i> About</span></a>
|
||||
<li><a href="/about"><i class="fa fa-question"></i> About</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
#!flask/bin/python
|
||||
# coding=utf-8
|
||||
from admin import app
|
||||
import logging as log
|
||||
import traceback
|
||||
|
||||
from uuid import uuid4
|
||||
import time,json
|
||||
import sys,os
|
||||
from flask import render_template, Response, request, redirect, url_for, jsonify
|
||||
import concurrent.futures
|
||||
from flask_login import login_required
|
||||
# import Queue
|
||||
import threading
|
||||
threads={}
|
||||
# q = Queue.Queue()
|
||||
|
||||
from pprint import pprint
|
||||
|
||||
from keycloak.exceptions import KeycloakGetError
|
||||
|
||||
@app.route('/api/resync')
|
||||
@login_required
|
||||
def resync():
|
||||
return json.dumps(app.admin.resync_data()), 200, {'Content-Type': 'application/json'}
|
||||
|
||||
@app.route('/api/users', methods=['GET'])
|
||||
@app.route('/api/users/<provider>', methods=['POST', 'PUT', 'GET', 'DELETE'])
|
||||
@login_required
|
||||
def users(provider=False):
|
||||
if request.method == 'DELETE':
|
||||
if provider == 'keycloak':
|
||||
return json.dumps(app.admin.delete_keycloak_users()), 200, {'Content-Type': 'application/json'}
|
||||
if provider == 'nextcloud':
|
||||
return json.dumps(app.admin.delete_nextcloud_users()), 200, {'Content-Type': 'application/json'}
|
||||
if provider == 'moodle':
|
||||
return json.dumps(app.admin.delete_moodle_users()), 200, {'Content-Type': 'application/json'}
|
||||
if request.method == 'POST':
|
||||
if provider == 'moodle':
|
||||
return json.dumps(app.admin.sync_to_moodle()), 200, {'Content-Type': 'application/json'}
|
||||
if provider == 'nextcloud':
|
||||
return json.dumps(app.admin.sync_to_nextcloud()), 200, {'Content-Type': 'application/json'}
|
||||
return json.dumps(app.admin.get_mix_users()), 200, {'Content-Type': 'application/json'}
|
||||
|
||||
|
||||
# Update pwd
|
||||
@app.route('/api/user_password', methods=['GET'])
|
||||
@app.route('/api/user_password/<userid>', methods=['PUT'])
|
||||
@login_required
|
||||
def user_password(userid=False):
|
||||
if request.method == 'GET':
|
||||
return json.dumps(app.admin.get_dice_pwd()), 200, {'Content-Type': 'application/json'}
|
||||
if request.method == 'PUT':
|
||||
data=request.get_json(force=True)
|
||||
password=data['password']
|
||||
temporary=data.get('temporary',True)
|
||||
try:
|
||||
res = app.admin.user_update_password(userid,password,temporary)
|
||||
return json.dumps({}), 200, {'Content-Type': 'application/json'}
|
||||
except KeycloakGetError as e:
|
||||
print(e.error_message.decode("utf-8"))
|
||||
return e.error_message, e.response_code, {'Content-Type': 'application/json'}
|
||||
|
||||
return json.dumps({}), 301, {'Content-Type': 'application/json'}
|
||||
|
||||
# User
|
||||
@app.route('/api/user/<userid>', methods=['POST', 'PUT', 'GET', 'DELETE'])
|
||||
@login_required
|
||||
def user(userid=None):
|
||||
if request.method == 'DELETE':
|
||||
res = app.admin.delete_user(userid)
|
||||
return json.dumps({}), 200, {'Content-Type': 'application/json'}
|
||||
# return json.dumps(), 301, {'Content-Type': 'application/json'}
|
||||
if request.method == 'POST':
|
||||
pass
|
||||
if request.method == 'PUT':
|
||||
pass
|
||||
if request.method == 'DELETE':
|
||||
pass
|
||||
if request.method == 'GET':
|
||||
res = app.admin.get_user(userid)
|
||||
return json.dumps(res), 200, {'Content-Type': 'application/json'}
|
||||
|
||||
@app.route('/api/roles')
|
||||
@login_required
|
||||
def roles():
|
||||
sorted_roles = sorted(app.admin.get_roles(), key=lambda k: k['name'])
|
||||
return json.dumps(sorted_roles), 200, {'Content-Type': 'application/json'}
|
||||
|
||||
|
||||
@app.route('/api/groups')
|
||||
@app.route('/api/groups/<provider>', methods=['POST', 'PUT', 'GET', 'DELETE'])
|
||||
@login_required
|
||||
def groups(provider=False):
|
||||
if request.method == 'GET':
|
||||
sorted_groups = sorted(app.admin.get_mix_groups(), key=lambda k: k['name'])
|
||||
return json.dumps(sorted_groups), 200, {'Content-Type': 'application/json'}
|
||||
if request.method == 'DELETE':
|
||||
if provider == 'keycloak':
|
||||
return json.dumps(app.admin.delete_keycloak_groups()), 200, {'Content-Type': 'application/json'}
|
||||
|
||||
|
||||
|
||||
### SYSADM USERS ONLY
|
||||
|
||||
@app.route('/api/external', methods=['POST', 'PUT', 'GET'])
|
||||
@login_required
|
||||
def external():
|
||||
if 'external' in threads.keys():
|
||||
if threads['external'] is not None and threads['external'].is_alive():
|
||||
return json.dumps({}), 301, {'Content-Type': 'application/json'}
|
||||
else:
|
||||
threads['external']=None
|
||||
|
||||
data=request.get_json(force=True)
|
||||
if request.method == 'POST':
|
||||
if data['format']=='json-ga':
|
||||
threads['external'] = threading.Thread(target=app.admin.upload_json_ga, args=(data,))
|
||||
threads['external'].start()
|
||||
return json.dumps({}), 200, {'Content-Type': 'application/json'}
|
||||
if data['format']=='csv-ug':
|
||||
threads['external'] = threading.Thread(target=app.admin.upload_csv_ug, args=(data,))
|
||||
threads['external'].start()
|
||||
return json.dumps({}), 200, {'Content-Type': 'application/json'}
|
||||
if request.method == 'PUT':
|
||||
threads['external'] = threading.Thread(target=app.admin.sync_external, args=(data,))
|
||||
threads['external'].start()
|
||||
return json.dumps({}), 200, {'Content-Type': 'application/json'}
|
||||
return json.dumps({}), 500, {'Content-Type': 'application/json'}
|
||||
|
||||
@app.route('/api/external/users')
|
||||
@login_required
|
||||
def external_users_list():
|
||||
return json.dumps(app.admin.get_external_users()), 200, {'Content-Type': 'application/json'}
|
||||
|
||||
@app.route('/api/external/groups')
|
||||
@login_required
|
||||
def external_groups_list():
|
||||
return json.dumps(app.admin.get_external_groups()), 200, {'Content-Type': 'application/json'}
|
||||
|
||||
@app.route('/api/external/roles', methods=['PUT'])
|
||||
@login_required
|
||||
def external_roles():
|
||||
if request.method == 'PUT':
|
||||
return json.dumps(app.admin.external_roleassign(request.get_json(force=True))), 200, {'Content-Type': 'application/json'}
|
|
@ -1,25 +0,0 @@
|
|||
#!flask/bin/python
|
||||
# coding=utf-8
|
||||
from admin import app
|
||||
import logging as log
|
||||
import traceback
|
||||
|
||||
from uuid import uuid4
|
||||
import time,json
|
||||
import sys,os
|
||||
from flask import render_template, Response, request, redirect, url_for, jsonify, send_file
|
||||
from flask_login import login_required
|
||||
|
||||
from pprint import pprint
|
||||
|
||||
from ..lib.avatars import Avatars
|
||||
|
||||
avatars=Avatars()
|
||||
|
||||
@app.route('/isard-sso-admin/avatar/<username>', methods=['GET'])
|
||||
@login_required
|
||||
def avatar(username):
|
||||
userid=avatars.username2id(username)
|
||||
if userid:
|
||||
return send_file('../avatars/master-avatars/'+userid, mimetype='image/jpeg')
|
||||
return send_file('static/img/usera.jpg', mimetype='image/jpeg')
|
|
@ -5,7 +5,8 @@ from flask import render_template, flash, request, redirect, url_for
|
|||
from ..auth.authentication import *
|
||||
from flask_login import login_required, current_user, login_user, logout_user
|
||||
|
||||
@app.route('/isard-sso-admin/login', methods=['GET', 'POST'])
|
||||
@app.route('/', methods=['GET', 'POST'])
|
||||
@app.route('/login', methods=['GET', 'POST'])
|
||||
def login():
|
||||
if request.method == 'POST':
|
||||
if request.form['user'] == '' or request.form['password'] == '':
|
||||
|
@ -18,12 +19,12 @@ def login():
|
|||
user=User({'id': ram_user['id'], 'password': ram_user['password'], 'role': ram_user['role'], 'active': True})
|
||||
login_user(user)
|
||||
flash('Logged in successfully.','success')
|
||||
return redirect(url_for('users'))
|
||||
return redirect(url_for('web_users'))
|
||||
else:
|
||||
flash('Username not found or incorrect password.','warning')
|
||||
return render_template('login.html')
|
||||
|
||||
@app.route('/isard-sso-admin/logout', methods=['GET'])
|
||||
@app.route('/logout', methods=['GET'])
|
||||
@login_required
|
||||
def logout():
|
||||
logout_user()
|
||||
|
|
|
@ -1,144 +0,0 @@
|
|||
#!flask/bin/python
|
||||
# coding=utf-8
|
||||
from admin import app
|
||||
import logging as log
|
||||
import traceback
|
||||
|
||||
from uuid import uuid4
|
||||
import time,json
|
||||
import sys,os
|
||||
from flask import render_template, Response, request, redirect, url_for, jsonify
|
||||
import concurrent.futures
|
||||
from flask_login import login_required
|
||||
|
||||
from pprint import pprint
|
||||
|
||||
# from flask_socketio import SocketIO, emit, join_room, leave_room, \
|
||||
# close_room, rooms, disconnect, send
|
||||
# socketio = SocketIO(app)
|
||||
|
||||
# from flask_login import login_required
|
||||
# from flask_oidc import OpenIDConnect
|
||||
|
||||
from ..auth.authentication import oidc
|
||||
|
||||
@app.route('/isard-sso-admin/custom_callback')
|
||||
@oidc.custom_callback
|
||||
def callback(data):
|
||||
return 'Hello. You submitted %s' % data
|
||||
|
||||
@app.route('/isard-sso-admin/private')
|
||||
@oidc.require_login
|
||||
def hello_me():
|
||||
info = oidc.user_getinfo(['email', 'openid_id'])
|
||||
return ('Hello, %s (%s)! <a href="/">Return</a>' %
|
||||
(info.get('email'), info.get('openid_id')))
|
||||
|
||||
|
||||
@app.route('/isard-sso-admin/api')
|
||||
@oidc.accept_token(True, ['openid'])
|
||||
def hello_api():
|
||||
return json.dumps({'hello': 'Welcome %s' % g.oidc_token_info['sub']})
|
||||
|
||||
|
||||
@app.route('/isard-sso-admin/logout')
|
||||
def logoutoidc():
|
||||
oidc.logout()
|
||||
return 'Hi, you have been logged out! <a href="/">Return</a>'
|
||||
|
||||
|
||||
@app.route('/isard-sso-admin/resync')
|
||||
@login_required
|
||||
def resync():
|
||||
return json.dumps(app.admin.resync_data()), 200, {'Content-Type': 'application/json'}
|
||||
|
||||
@app.route('/isard-sso-admin/users', methods=['GET'])
|
||||
@app.route('/isard-sso-admin/users/<provider>', methods=['POST', 'PUT', 'GET', 'DELETE'])
|
||||
@login_required
|
||||
def users(provider=False):
|
||||
if request.method == 'DELETE':
|
||||
if provider == 'keycloak':
|
||||
return json.dumps(app.admin.delete_keycloak_users()), 200, {'Content-Type': 'application/json'}
|
||||
if provider == 'nextcloud':
|
||||
return json.dumps(app.admin.delete_nextcloud_users()), 200, {'Content-Type': 'application/json'}
|
||||
if provider == 'moodle':
|
||||
return json.dumps(app.admin.delete_moodle_users()), 200, {'Content-Type': 'application/json'}
|
||||
if request.method == 'POST':
|
||||
if provider == 'moodle':
|
||||
return json.dumps(app.admin.sync_to_moodle()), 200, {'Content-Type': 'application/json'}
|
||||
if provider == 'nextcloud':
|
||||
return json.dumps(app.admin.sync_to_nextcloud()), 200, {'Content-Type': 'application/json'}
|
||||
return render_template('pages/users.html', title="Users", nav="Users")
|
||||
|
||||
@app.route('/isard-sso-admin/users_list')
|
||||
@login_required
|
||||
def users_list():
|
||||
return json.dumps(app.admin.get_mix_users()), 200, {'Content-Type': 'application/json'}
|
||||
|
||||
|
||||
@app.route('/isard-sso-admin/roles')
|
||||
@login_required
|
||||
def roles():
|
||||
return render_template('pages/roles.html', title="Roles", nav="Roles")
|
||||
|
||||
@app.route('/isard-sso-admin/roles_list')
|
||||
@login_required
|
||||
def roles_list():
|
||||
return json.dumps(app.admin.get_roles()), 200, {'Content-Type': 'application/json'}
|
||||
|
||||
|
||||
@app.route('/isard-sso-admin/groups')
|
||||
@app.route('/isard-sso-admin/groups/<provider>', methods=['POST', 'PUT', 'GET', 'DELETE'])
|
||||
@login_required
|
||||
def groups(provider=False):
|
||||
if request.method == 'DELETE':
|
||||
if provider == 'keycloak':
|
||||
return json.dumps(app.admin.delete_keycloak_groups()), 200, {'Content-Type': 'application/json'}
|
||||
return render_template('pages/groups.html', title="Groups", nav="Groups")
|
||||
|
||||
@app.route('/isard-sso-admin/groups_list')
|
||||
@login_required
|
||||
def groups_list():
|
||||
return json.dumps(app.admin.get_mix_groups()), 200, {'Content-Type': 'application/json'}
|
||||
|
||||
|
||||
@app.route('/isard-sso-admin/external', methods=['POST', 'PUT', 'GET'])
|
||||
@login_required
|
||||
def external():
|
||||
if request.method == 'POST':
|
||||
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':
|
||||
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")
|
||||
|
||||
@app.route('/isard-sso-admin/external_users_list')
|
||||
@login_required
|
||||
def external_users_list():
|
||||
return json.dumps(app.admin.get_external_users()), 200, {'Content-Type': 'application/json'}
|
||||
|
||||
@app.route('/isard-sso-admin/external_groups_list')
|
||||
@login_required
|
||||
def external_groups_list():
|
||||
return json.dumps(app.admin.get_external_groups()), 200, {'Content-Type': 'application/json'}
|
||||
|
||||
@app.route('/isard-sso-admin/external/roles', methods=['PUT'])
|
||||
@login_required
|
||||
def external_roles():
|
||||
if request.method == 'PUT':
|
||||
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
|
|
@ -6,14 +6,14 @@
|
|||
# # socketio = SocketIO(app)
|
||||
# # from ...start import socketio
|
||||
|
||||
# @socketio.on('connect', namespace='/isard-sso-admin/sio')
|
||||
# @socketio.on('connect', namespace='//sio')
|
||||
# def socketio_connect():
|
||||
# join_room('admin')
|
||||
# socketio.emit('update',
|
||||
# json.dumps('Joined'),
|
||||
# namespace='/isard-sso-admin/sio',
|
||||
# namespace='//sio',
|
||||
# room='admin')
|
||||
|
||||
# @socketio.on('disconnect', namespace='/isard-sso-admin/sio')
|
||||
# @socketio.on('disconnect', namespace='//sio')
|
||||
# def socketio_domains_disconnect():
|
||||
# None
|
|
@ -0,0 +1,80 @@
|
|||
#!flask/bin/python
|
||||
# coding=utf-8
|
||||
from admin import app
|
||||
import logging as log
|
||||
import traceback
|
||||
|
||||
from uuid import uuid4
|
||||
import time,json
|
||||
import sys,os
|
||||
from flask import render_template, Response, request, redirect, url_for, jsonify, send_file
|
||||
import concurrent.futures
|
||||
from flask_login import login_required
|
||||
|
||||
from pprint import pprint
|
||||
from ..lib.avatars import Avatars
|
||||
|
||||
avatars=Avatars()
|
||||
|
||||
''' OIDC TESTS '''
|
||||
# from ..auth.authentication import oidc
|
||||
|
||||
# @app.route('/custom_callback')
|
||||
# @oidc.custom_callback
|
||||
# def callback(data):
|
||||
# return 'Hello. You submitted %s' % data
|
||||
|
||||
# @app.route('/private')
|
||||
# @oidc.require_login
|
||||
# def hello_me():
|
||||
# info = oidc.user_getinfo(['email', 'openid_id'])
|
||||
# return ('Hello, %s (%s)! <a href="/">Return</a>' %
|
||||
# (info.get('email'), info.get('openid_id')))
|
||||
|
||||
|
||||
# @app.route('/api')
|
||||
# @oidc.accept_token(True, ['openid'])
|
||||
# def hello_api():
|
||||
# return json.dumps({'hello': 'Welcome %s' % g.oidc_token_info['sub']})
|
||||
|
||||
|
||||
# @app.route('/logout')
|
||||
# def logoutoidc():
|
||||
# oidc.logout()
|
||||
# return 'Hi, you have been logged out! <a href="/">Return</a>'
|
||||
''' OIDC TESTS '''
|
||||
|
||||
@app.route('/users')
|
||||
@login_required
|
||||
def web_users():
|
||||
return render_template('pages/users.html', title="Users", nav="Users")
|
||||
|
||||
@app.route('/roles')
|
||||
@login_required
|
||||
def web_roles():
|
||||
return render_template('pages/roles.html', title="Roles", nav="Roles")
|
||||
|
||||
@app.route('/groups')
|
||||
@login_required
|
||||
def web_groups(provider=False):
|
||||
return render_template('pages/groups.html', title="Groups", nav="Groups")
|
||||
|
||||
@app.route('/avatar/<userid>', methods=['GET'])
|
||||
@login_required
|
||||
def avatar(userid):
|
||||
if userid != 'false':
|
||||
return send_file('../avatars/master-avatars/'+userid, mimetype='image/jpeg')
|
||||
return send_file('static/img/missing.jpg', mimetype='image/jpeg')
|
||||
|
||||
### SYS ADMIN
|
||||
|
||||
@app.route('/sysadmin/users')
|
||||
@login_required
|
||||
def web_sysadmin_users():
|
||||
return render_template('pages/sysadmin/users.html', title="SysAdmin Users", nav="SysAdminUsers")
|
||||
|
||||
@app.route('/sysadmin/external')
|
||||
@login_required
|
||||
## SysAdmin role
|
||||
def web_sysadmin_external():
|
||||
return render_template('pages/sysadmin/external.html', title="External", nav="External")
|
|
@ -1,13 +1,13 @@
|
|||
{
|
||||
"web": {
|
||||
"auth_uri": "https://sso.santantoni.duckdns.org/auth/realms/master/protocol/openid-connect/auth",
|
||||
"auth_uri": "https://sso.[[DOMAIN]]/auth/realms/master/protocol/openid-connect/auth",
|
||||
"client_id": "adminapp",
|
||||
"client_secret": "8a9e5a2e-3be9-43e3-9c47-1796f0d5ab72",
|
||||
"redirect_uris": [
|
||||
"https://sso.santantoni.duckdns.org/isard-sso-admin/custom_callback"
|
||||
"https://sso.[[DOMAIN]]/oidc_callback"
|
||||
],
|
||||
"userinfo_uri": "https://sso.santantoni.duckdns.org/auth/realms/master/protocol/openid-connect/userinfo",
|
||||
"token_uri": "https://sso.santantoni.duckdns.org/auth/realms/master/protocol/openid-connect/token",
|
||||
"token_introspection_uri": "https://sso.santantoni.duckdns.org/auth/realms/master/protocol/openid-connect/token/introspect"
|
||||
"userinfo_uri": "https://sso.[[DOMAIN]]/auth/realms/master/protocol/openid-connect/userinfo",
|
||||
"token_uri": "https://sso.[[DOMAIN]]/auth/realms/master/protocol/openid-connect/token",
|
||||
"token_introspection_uri": "https://sso.[[DOMAIN]]/auth/realms/master/protocol/openid-connect/token/introspect"
|
||||
}
|
||||
}
|
|
@ -8,34 +8,21 @@ from flask_socketio import SocketIO, emit, join_room, leave_room, \
|
|||
import json
|
||||
from admin import app
|
||||
|
||||
|
||||
# socketio.init_app(app, cors_allowed_origins="*")
|
||||
|
||||
# from admin.views.Socketio import *
|
||||
|
||||
|
||||
|
||||
app.socketio = SocketIO(app)
|
||||
|
||||
# app.socketio.init_app(app, cors_allowed_origins="*")
|
||||
@app.socketio.on('connect', namespace='/isard-sso-admin/sio')
|
||||
@app.socketio.on('connect', namespace='/sio')
|
||||
def socketio_connect():
|
||||
join_room('admin')
|
||||
app.socketio.emit('update',
|
||||
json.dumps('Joined'),
|
||||
namespace='/isard-sso-admin/sio',
|
||||
namespace='/sio',
|
||||
room='admin')
|
||||
|
||||
# socketio.emit('update',
|
||||
# json.dumps('DATA SENT'),
|
||||
# namespace='/isard-sso-admin/sio',
|
||||
# room='admin')
|
||||
|
||||
@app.socketio.on('disconnect', namespace='/isard-sso-admin/sio')
|
||||
def socketio_domains_disconnect():
|
||||
@app.socketio.on('disconnect', namespace='/sio')
|
||||
def socketio_disconnect():
|
||||
None
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.socketio.run(app,host='0.0.0.0', port=9000, debug=False, cors_allowed_origins="*", ssl_context='adhoc', async_mode="threading") #, logger=logger, engineio_logger=engineio_logger)
|
||||
|
||||
app.socketio.run(app,host='0.0.0.0', port=9000, debug=False, ssl_context='adhoc', async_mode="threading") #, logger=logger, engineio_logger=engineio_logger)
|
||||
# , cors_allowed_origins="*"
|
||||
# /usr/lib/python3.8/site-packages/certifi
|
|
@ -47,6 +47,7 @@ frontend website
|
|||
acl is_sso hdr_beg(host) sso.
|
||||
acl is_ipa hdr_beg(host) ipa.
|
||||
acl is_api hdr_beg(host) api.
|
||||
acl is_admin hdr_beg(host) admin.
|
||||
|
||||
use_backend be_nextcloud if is_nextcloud
|
||||
use_backend be_moodle if is_moodle
|
||||
|
@ -56,7 +57,7 @@ frontend website
|
|||
use_backend be_etherpad if is_pad
|
||||
use_backend be_admin if is_sso { path_beg /socket.io }
|
||||
use_backend be_adminer if is_sso { path_beg /isard-sso-adminer }
|
||||
use_backend be_admin if is_sso { path_beg /isard-sso-admin }
|
||||
use_backend be_admin if is_admin
|
||||
use_backend be_sso if is_sso
|
||||
use_backend be_ipa if is_ipa
|
||||
use_backend be_api if is_api
|
||||
|
|
Loading…
Reference in New Issue