fixes in admin

root 2021-06-01 22:59:12 +02:00
parent d2f0f66805
commit 49ef0ede48
7 changed files with 191 additions and 71 deletions

View File

@ -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

View File

@ -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):

View File

@ -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)

View File

@ -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']

View File

@ -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:

View File

@ -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>"
}},
]
} );
});

View File

@ -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>