fixes in admin
parent
d2f0f66805
commit
49ef0ede48
|
@ -5,5 +5,6 @@ cd /admin/admin
|
|||
yarn install
|
||||
## End Only in development
|
||||
cd /admin
|
||||
export PYTHONWARNINGS="ignore:Unverified HTTPS request"
|
||||
python3 start.py &
|
||||
/usr/sbin/sshd -D -e -f /etc/ssh/sshd_config
|
|
@ -39,6 +39,9 @@ class Admin():
|
|||
sleep(2)
|
||||
log.warning('Keycloak connected.')
|
||||
|
||||
# print(self.keycloak.get_user_groups_paths('320b0713-c480-4928-9105-041309d72191'))
|
||||
# exit(1)
|
||||
|
||||
ready=False
|
||||
while not ready:
|
||||
try:
|
||||
|
@ -280,14 +283,12 @@ class Admin():
|
|||
# "roles": []})
|
||||
# return users_list
|
||||
|
||||
# def get_ram_users(self):
|
||||
# return self.internal['users']
|
||||
|
||||
def get_mix_users(self):
|
||||
return self.internal['users']
|
||||
|
||||
def _get_mix_users(self):
|
||||
kusers=self.get_keycloak_users()
|
||||
pprint(kusers)
|
||||
musers=self.get_moodle_users()
|
||||
nusers=self.get_nextcloud_users()
|
||||
|
||||
|
@ -304,7 +305,7 @@ class Admin():
|
|||
if len(keycloak_exists):
|
||||
theuser=keycloak_exists[0]
|
||||
theuser['keycloak']=True
|
||||
theuser['keycloak_groups']=keycloak_exists[0]['groups']
|
||||
theuser['keycloak_groups']=self.keycloak.get_user_groups_paths(keycloak_exists[0]['id']) #keycloak_exists[0]['groups']
|
||||
else:
|
||||
theuser['id']=False
|
||||
theuser['keycloak']=False
|
||||
|
@ -377,6 +378,8 @@ class Admin():
|
|||
if len(keycloak_exists):
|
||||
thegroup=keycloak_exists[0]
|
||||
thegroup['keycloak']=True
|
||||
thegroup['path']=self.keycloak.get_group_path(keycloak_exists[0]['id'])
|
||||
del thegroup['subGroups']
|
||||
else:
|
||||
thegroup['id']=False
|
||||
thegroup['keycloak']=False
|
||||
|
@ -402,7 +405,6 @@ class Admin():
|
|||
thegroup['nextcloud']=False
|
||||
|
||||
groups.append(thegroup)
|
||||
|
||||
return groups
|
||||
|
||||
def get_external_users(self):
|
||||
|
@ -443,7 +445,8 @@ class Admin():
|
|||
'username': u['primaryEmail'].split('@')[0],
|
||||
'groups':[u['orgUnitPath']], ## WARNING: Removing the first
|
||||
'roles':[],
|
||||
'password':diceware.get_passphrase(options=options)})
|
||||
'password':'test'})
|
||||
# 'password':diceware.get_passphrase(options=options)})
|
||||
socketio.emit('update',
|
||||
json.dumps({'status':True,'item':'user','action':'delete','itemdata':''}),
|
||||
namespace='/isard-sso-admin/sio',
|
||||
|
@ -460,7 +463,6 @@ class Admin():
|
|||
return True
|
||||
|
||||
def sync_external(self,ids):
|
||||
pprint(ids)
|
||||
log.warning('Starting sync to keycloak')
|
||||
self.sync_to_keycloak()
|
||||
# log.warning('Starting sync to moodle')
|
||||
|
@ -495,7 +497,7 @@ class Admin():
|
|||
if len(u['roles']) != 0:
|
||||
log.warning(' KEYCLOAK USERS: Assign user '+u['username']+' with initial pwd '+ u['password']+' to role '+u['roles'][0])
|
||||
self.keycloak.assign_realm_roles(uid,u['roles'][0])
|
||||
gid=self.keycloak.get_group(path='/'+u['roles'][0])['id']
|
||||
gid=self.keycloak.get_group_by_path(path='/'+u['roles'][0])['id']
|
||||
self.keycloak.group_user_add(uid,gid)
|
||||
# Add user to groups
|
||||
for g in u['groups']:
|
||||
|
@ -509,7 +511,7 @@ class Admin():
|
|||
|
||||
if sub=='/': continue # User with no path
|
||||
log.warning(' KEYCLOAK USERS: Assign user '+u['username']+' to group '+ str(sub))
|
||||
gid=self.keycloak.get_group(path=sub)['id']
|
||||
gid=self.keycloak.get_group_by_path(path=sub)['id']
|
||||
self.keycloak.group_user_add(uid,gid)
|
||||
self.resync_data()
|
||||
|
||||
|
@ -519,7 +521,6 @@ class Admin():
|
|||
groups=groups+u['keycloak_groups']
|
||||
groups=list(dict.fromkeys(groups))
|
||||
|
||||
pprint(groups)
|
||||
total=len(groups)
|
||||
i=0
|
||||
for g in groups:
|
||||
|
@ -534,23 +535,91 @@ class Admin():
|
|||
log.error('probably exists')
|
||||
i=i+1
|
||||
# print('ADDING FULL PATH: '+str(g))
|
||||
return
|
||||
|
||||
|
||||
cohorts=self.moodle.get_cohorts()
|
||||
|
||||
for u in self.internal['users']:
|
||||
if not u['moodle']:
|
||||
log.info('Creating moodle user: '+u['username'])
|
||||
self.moodle.create_user(u['email'],u['username'],u['password'],u['first'],u['last'])
|
||||
user=self.moodle.create_user(u['email'],u['username'],'1Random 1String',u['first'],u['last'])[0]
|
||||
print(str(user))
|
||||
user_id=user['id']
|
||||
# [{'id': 5, 'username': 'xkrlzwd'}]
|
||||
|
||||
for g in u['keycloak_groups']:
|
||||
log.info('Adding moodle user: '+u['username']+' to cohort '+g)
|
||||
cohort_id=[c['id'] for c in cohorts if c['name']==g][0]
|
||||
|
||||
print(user_id)
|
||||
print(cohort_id)
|
||||
self.moodle.add_user_to_cohort(user_id,cohort_id)
|
||||
|
||||
## Update cohorts on existing
|
||||
self.resync_data()
|
||||
for u in self.internal['users']:
|
||||
if u['moodle']:
|
||||
total=len(groups)
|
||||
index=0
|
||||
for g in groups:
|
||||
print('THE FULL GROUP TO BE ADDED NOW: '+g)
|
||||
parts=g.split('/')
|
||||
subpath=''
|
||||
for i in range(1,len(parts)):
|
||||
try:
|
||||
subpath=subpath+'/'+parts[i]
|
||||
# log.info('Adding moodle user: '+u['username']+' to cohort '+subpath)
|
||||
cohort=[c['id'] for c in cohorts if c['name']==subpath][0]
|
||||
|
||||
log.warning(' MOODLE USER GROUPS GROUPS: Adding user '+u['username']+' to group as cohort '+cohort['name']+' ('+str(index)+'/'+str(total)+'): '+subpath)
|
||||
# print(u['moodle_id'])
|
||||
# print('Adding to cohort id '+str(cohort_id)+' with name '+g)
|
||||
self.moodle.add_user_to_cohort(u['moodle_id'],cohort['id'])
|
||||
except:
|
||||
log.error('probably exists')
|
||||
index=index+1
|
||||
|
||||
### MISING ASSING USER TO ROLE COHORT
|
||||
|
||||
# for g in u['keycloak_groups']:
|
||||
# log.info('Adding moodle user: '+u['username']+' to cohort '+g)
|
||||
# cohort_id=[c['id'] for c in cohorts if c['name']==g][0]
|
||||
|
||||
# print(u['moodle_id'])
|
||||
# print('Adding to cohort id '+str(cohort_id)+' with name '+g)
|
||||
# pprint(self.moodle.add_user_to_cohort(u['moodle_id'],cohort_id))
|
||||
|
||||
|
||||
|
||||
def sync_to_nextcloud(self):
|
||||
groups=[]
|
||||
for u in self.internal['users']:
|
||||
if not u['nextcloud']:
|
||||
log.info('Creating nextcloud user: '+u['username'])
|
||||
group=u['keycloak_groups'][0] if len(u['keycloak_groups']) else False
|
||||
groups=groups+u['keycloak_groups']
|
||||
groups=list(dict.fromkeys(groups))
|
||||
|
||||
total=len(groups)
|
||||
i=0
|
||||
for g in groups:
|
||||
parts=g.split('/')
|
||||
subpath=''
|
||||
for i in range(1,len(parts)):
|
||||
try:
|
||||
self.nextcloud.add_user(u['username'],u['password'],2000000000000,group,u['email'],u['first']+' '+u['last'])
|
||||
log.warning(' NEXTCLOUD GROUPS: Adding group ('+str(i)+'/'+str(total)+'): '+subpath)
|
||||
subpath=subpath+'/'+parts[i]
|
||||
self.nextcloud.add_group(subpath)
|
||||
except:
|
||||
log.error('probably exists')
|
||||
i=i+1
|
||||
|
||||
for u in self.internal['users']:
|
||||
print('User '+u['username'])
|
||||
if not u['nextcloud']:
|
||||
print(' Is not in nextcloud')
|
||||
log.warning(' NEXTCLOUD USERS: Creating nextcloud user: '+u['username']+' in groups '+str(u['keycloak_groups']))
|
||||
# group=u['keycloak_groups'][0] if len(u['keycloak_groups']) else False
|
||||
try:
|
||||
self.nextcloud.add_user_with_groups(u['username'],'1Random 1String',500000000000,u['keycloak_groups'],u['email'],u['first']+' '+u['last'])
|
||||
except ProviderItemExists:
|
||||
log.info('User '+u['username']+' already exists. Skipping...')
|
||||
log.warning('User '+u['username']+' already exists. Skipping...')
|
||||
continue
|
||||
except:
|
||||
log.error(traceback.format_exc())
|
||||
|
@ -597,17 +666,17 @@ class Admin():
|
|||
if u['moodle'] and not u['keycloak']:
|
||||
userids.append(u['moodle_id'])
|
||||
usernames.append(u['username'])
|
||||
|
||||
log.warning('Removing moodle users: '+','.join(usernames))
|
||||
try:
|
||||
self.moodle.delete_users(userids)
|
||||
socketio.emit('update',
|
||||
json.dumps({'status':True,'item':'user','action':'delete','itemdata':u}),
|
||||
namespace='/isard-sso-admin/sio',
|
||||
room='admin')
|
||||
except:
|
||||
log.error(traceback.format_exc())
|
||||
log.warning('Could not remove users: '+','.join(usernames))
|
||||
if len(userids):
|
||||
log.warning('Removing moodle users: '+','.join(usernames))
|
||||
try:
|
||||
self.moodle.delete_users(userids)
|
||||
socketio.emit('update',
|
||||
json.dumps({'status':True,'item':'user','action':'delete','itemdata':u}),
|
||||
namespace='/isard-sso-admin/sio',
|
||||
room='admin')
|
||||
except:
|
||||
log.error(traceback.format_exc())
|
||||
log.warning('Could not remove users: '+','.join(usernames))
|
||||
|
||||
|
||||
def delete_keycloak_groups(self):
|
||||
|
|
|
@ -85,34 +85,6 @@ class KeycloakClient():
|
|||
group by u.id,u.username,u.email,u.first_name,u.last_name, u.realm_id, ua.value
|
||||
order by u.username"""
|
||||
|
||||
# q = """select u.id, u.username, u.email, u.first_name, u.last_name, u.realm_id, ua.value as quota, g.id, g.path, g.name,
|
||||
# --,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
|
||||
# left join user_attribute as ua on ua.user_id=u.id and ua.name = 'quota'
|
||||
# left join user_group_membership as ugm on ugm.user_id = u.id
|
||||
# left join keycloak_group as g on g.id = ugm.group_id
|
||||
# --left join keycloak_group as g_parent on g.parent_group = g_parent.id
|
||||
# --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
|
||||
# order by u.username"""
|
||||
|
||||
# q = """select u.id, u.username, u.email, u.first_name, u.last_name, u.realm_id, ua.value as quota
|
||||
# ,json_agg(g."name") as group_name,json_agg(g."id") as group_id,json_agg(g."path") as group_path
|
||||
# ,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
|
||||
# left join user_attribute as ua on ua.user_id=u.id and ua.name = 'quota'
|
||||
# left join user_group_membership as ugm on ugm.user_id = u.id
|
||||
# left join keycloak_group as g on g.id = ugm.group_id
|
||||
# left join keycloak_group as g_parent on g.parent_group = g_parent.id
|
||||
# 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
|
||||
# order by u.username"""
|
||||
(headers,users)=self.keycloak_pg.select_with_headers(q)
|
||||
|
||||
users_with_lists = [list(l[:-4])+([[]] if l[-4] == [None] else [list(set(l[-4]))]) +\
|
||||
|
@ -128,6 +100,30 @@ class KeycloakClient():
|
|||
list_dict_users = [dict(zip(headers, r)) for r in users_with_lists]
|
||||
return list_dict_users
|
||||
|
||||
|
||||
|
||||
def getparent(self,group_id, data):
|
||||
path = ""
|
||||
for item in data:
|
||||
if group_id == item[0]:
|
||||
path = self.getparent(item[2], data)
|
||||
path = f'{path}/{item[1]}'
|
||||
return path
|
||||
|
||||
def get_group_path(self,group_id):
|
||||
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):
|
||||
q = """SELECT group_id FROM user_group_membership WHERE user_id = '%s'""" % (user_id)
|
||||
user_group_ids=self.keycloak_pg.select(q)
|
||||
|
||||
paths=[]
|
||||
for g in user_group_ids:
|
||||
paths.append(self.get_group_path(g[0]))
|
||||
return paths
|
||||
|
||||
## Too slow
|
||||
# def get_users_with_groups_and_roles(self):
|
||||
# self.connect()
|
||||
|
@ -213,13 +209,18 @@ class KeycloakClient():
|
|||
|
||||
return groups+subgroups+subgroups1
|
||||
|
||||
def get_group(self,path,recursive=True):
|
||||
def get_group_by_id(self,group_id):
|
||||
self.connect()
|
||||
return self.keycloak_admin.get_group(group_id=group_id)
|
||||
|
||||
def get_group_by_path(self,path,recursive=True):
|
||||
self.connect()
|
||||
return self.keycloak_admin.get_group_by_path(path=path,search_in_subgroups=recursive)
|
||||
|
||||
def add_group(self,name,parent=None,skip_exists=False):
|
||||
self.connect()
|
||||
if parent is not None: parent=self.get_group(parent)['id']
|
||||
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)
|
||||
|
||||
def delete_group(self,group_id):
|
||||
|
@ -241,14 +242,14 @@ class KeycloakClient():
|
|||
if parent_path==None:
|
||||
parent_path='/'+parts[i]
|
||||
else:
|
||||
parent_path=self.get_group(parent_path)['path']
|
||||
parent_path=parent_path+parts[i]
|
||||
parent_path=self.get_group_by_path(parent_path)['path']
|
||||
parent_path=parent_path+'/'+parts[i]
|
||||
continue
|
||||
|
||||
if parent_path==None:
|
||||
parent_path='/'+parts[i]
|
||||
else:
|
||||
parent_path=parent_path+parts[i]
|
||||
parent_path=parent_path+'/'+parts[i]
|
||||
|
||||
# try:
|
||||
# if i == 1: parent_id=self.add_group(parts[i])
|
||||
|
@ -287,7 +288,7 @@ class KeycloakClient():
|
|||
if thepath=='/':
|
||||
print('Not adding the user '+username+' to any group as does not have any...')
|
||||
continue
|
||||
gid=self.get_group(path=thepath)['id']
|
||||
gid=self.get_group_by_path(path=thepath)['id']
|
||||
|
||||
print('Adding '+username+' with uuid: '+uid+' to group '+g+' with uuid: '+gid)
|
||||
self.keycloak_admin.group_user_add(uid,gid)
|
||||
|
|
|
@ -135,12 +135,11 @@ class Moodle():
|
|||
# user = self.call('core_cohort_add_cohort_members', criteria=criteria)
|
||||
# return user
|
||||
|
||||
# def add_users_to_cohort(self,userid,cohortid):
|
||||
# members=[{'cohorttype':{'type':'system','value':cohortid},
|
||||
# 'usertype':{'type':'id','value':userid}}]
|
||||
# criteria = [{'key': key, 'value': value}]
|
||||
# user = self.call('core_cohort_add_cohort_members', criteria=criteria)
|
||||
# return user
|
||||
def add_user_to_cohort(self,userid,cohortid):
|
||||
members=[{'cohorttype':{'type':'id','value':cohortid},
|
||||
'usertype':{'type':'id','value':userid}}]
|
||||
user = self.call('core_cohort_add_cohort_members', members=members)
|
||||
return user
|
||||
|
||||
def get_cohort_members(self, cohort_id):
|
||||
members = self.call('core_cohort_get_cohort_members', cohortids=[cohort_id])[0]['userids']
|
||||
|
|
|
@ -160,6 +160,41 @@ class Nextcloud():
|
|||
# 106 - no group specified (required for subadmins)
|
||||
# 107 - all errors that contain a hint - for example “Password is among the 1,000,000 most common ones. Please make it unique.” (this code was added in 12.0.6 & 13.0.1)
|
||||
|
||||
def add_user_with_groups(self,userid,userpassword,quota=False,groups=[],email='',displayname=''):
|
||||
data={'userid':userid,'password':userpassword,'quota':quota,'groups[]':groups,'email':email,'displayname':displayname}
|
||||
# if not group: del data['groups[]']
|
||||
if not quota: del data['quota']
|
||||
# if group:
|
||||
# data={'userid':userid,'password':userpassword,'quota':quota,'groups[]':group,'email':email,'displayname':displayname}
|
||||
# else:
|
||||
# data={'userid':userid,'password':userpassword,'quota':quota,'email':email,'displayname':displayname}
|
||||
url = self.apiurl + "users?format=json"
|
||||
headers = {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'OCS-APIRequest': 'true',
|
||||
}
|
||||
try:
|
||||
result = json.loads(self._request('POST',url,data=data,headers=headers))
|
||||
if result['ocs']['meta']['statuscode'] == 100: return True
|
||||
if result['ocs']['meta']['statuscode'] == 102: raise ProviderItemExists
|
||||
if result['ocs']['meta']['statuscode'] == 104:
|
||||
# self.add_group(group)
|
||||
None
|
||||
# raise ProviderGroupNotExists
|
||||
log.error('Get Nextcloud provider user add error: '+str(result))
|
||||
raise ProviderOpError
|
||||
except:
|
||||
log.error(traceback.format_exc())
|
||||
raise
|
||||
# 100 - successful
|
||||
# 101 - invalid input data
|
||||
# 102 - username already exists
|
||||
# 103 - unknown error occurred whilst adding the user
|
||||
# 104 - group does not exist
|
||||
# 105 - insufficient privileges for group
|
||||
# 106 - no group specified (required for subadmins)
|
||||
# 107 - all errors that contain a hint - for example “Password is among the 1,000,000 most common ones. Please make it unique.” (this code was added in 12.0.6 & 13.0.1)
|
||||
|
||||
def delete_user(self,userid):
|
||||
url = self.apiurl + "users/"+userid+"?format=json"
|
||||
try:
|
||||
|
|
|
@ -232,6 +232,11 @@ $(document).ready(function() {
|
|||
};
|
||||
}},
|
||||
{
|
||||
"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){
|
||||
|
@ -240,6 +245,11 @@ $(document).ready(function() {
|
|||
return '<i class="fa fa-close" style="color:darkred"></i>'
|
||||
};
|
||||
}},
|
||||
{
|
||||
"targets": 10,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
return "<li>" + full.keycloak_groups.join("</li><li>") + "</li>"
|
||||
}},
|
||||
{
|
||||
"targets": 11,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
|
@ -249,6 +259,11 @@ $(document).ready(function() {
|
|||
return '<i class="fa fa-close" style="color:darkred"></i>'
|
||||
};
|
||||
}},
|
||||
{
|
||||
"targets": 12,
|
||||
"render": function ( data, type, full, meta ) {
|
||||
return "<li>" + full.keycloak_groups.join("</li><li>") + "</li>"
|
||||
}},
|
||||
]
|
||||
} );
|
||||
});
|
|
@ -27,7 +27,7 @@
|
|||
<button class="btn btn-primary btn-xs btn-sync_to_moodle">
|
||||
<i class="fa fa-refresh" aria-hidden="true"></i> Sync to Moodle
|
||||
</button>
|
||||
<!-- <button class="btn btn-danger btn-xs btn-delete_keycloak">
|
||||
<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">
|
||||
|
@ -35,7 +35,7 @@
|
|||
</button>
|
||||
<button class="btn btn-danger btn-xs btn-delete_moodle">
|
||||
<i class="fa fa-trash"></i> Delete missing keycloak in moodle
|
||||
</button> -->
|
||||
</button>
|
||||
<table id="users" class="table" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
Loading…
Reference in New Issue