diff --git a/admin/src/admin/lib/admin.py b/admin/src/admin/lib/admin.py
index 9eda8a2..ed80c45 100644
--- a/admin/src/admin/lib/admin.py
+++ b/admin/src/admin/lib/admin.py
@@ -6,12 +6,17 @@ from .nextcloud import Nextcloud
import logging as log
from pprint import pprint
+from .nextcloud_exc import *
+
class Admin():
def __init__(self):
self.keycloak=Keycloak(verify=app.config['VERIFY'])
self.moodle=Moodle(verify=app.config['VERIFY'])
self.nextcloud=Nextcloud(verify=app.config['VERIFY'])
+ # self.internal={'users':self.get_mix_users(),
+ # 'groups':self.get_mix_groups(),
+ # 'roles':[]}
self.external={'users':[],
'groups':[],
'roles':[]}
@@ -21,18 +26,24 @@ class Admin():
# pprint(self.get_nextcloud_users())
def get_moodle_users(self):
- users = self.moodle.get_users_with_groups_and_roles()
- #self.moodle.get_user_by('email','%%')['users']
- return [{"id":u['id'],
- "username":u['username'],
- "first": u['firstname'],
- "last": u['lastname'],
- "email": u['email'],
- "groups": u['groups'],
- "roles": u['roles']}
- for u in users]
+ return self.moodle.get_users_with_groups_and_roles()
+
+ ## TOO SLOW. Not used.
+ # def get_moodle_users(self):
+ # log.warning('Loading moodle users... can take a long time...')
+ # users = self.moodle.get_users_with_groups_and_roles()
+ # #self.moodle.get_user_by('email','%%')['users']
+ # return [{"id":u['id'],
+ # "username":u['username'],
+ # "first": u['firstname'],
+ # "last": u['lastname'],
+ # "email": u['email'],
+ # "groups": u['groups'],
+ # "roles": u['roles']}
+ # for u in users]
def get_keycloak_users(self):
+ log.warning('Loading keycloak users... can take a long time...')
users = self.keycloak.get_users_with_groups_and_roles()
return [{"id":u['id'],
"username":u['username'],
@@ -44,6 +55,7 @@ class Admin():
for u in users]
def get_nextcloud_users(self):
+ log.warning('Loading nextcloud users... can take a long time...')
users = self.nextcloud.get_users_list()
users_list=[]
for user in users:
@@ -57,10 +69,14 @@ class Admin():
"roles": []})
return users_list
+ # def get_ram_users(self):
+ # return self.internal['users']
+
def get_mix_users(self):
kusers=self.get_keycloak_users()
musers=self.get_moodle_users()
- nusers=self.get_nextcloud_users()
+ # nusers=self.get_nextcloud_users()
+ nusers=[]
kusers_usernames=[u['username'] for u in kusers]
musers_usernames=[u['username'] for u in musers]
@@ -107,15 +123,21 @@ class Admin():
return self.keycloak.get_roles()
def get_keycloak_groups(self):
+ log.warning('Loading keycloak groups... can take a long time...')
return self.keycloak.get_groups()
def get_moodle_groups(self):
+ log.warning('Loading moodle groups... can take a long time...')
return self.moodle.get_cohorts()
def get_nextcloud_groups(self):
+ log.warning('Loading nextcloud groups... can take a long time...')
return self.nextcloud.get_groups_list()
- def get_groups(self):
+ # def get_ram_groups(self):
+ # return self.internal['groups']
+
+ def get_mix_groups(self):
kgroups=self.get_keycloak_groups()
mgroups=self.get_moodle_groups()
ngroups=self.get_nextcloud_groups()
@@ -198,8 +220,29 @@ class Admin():
return True
+ def sync_external(self):
+ for u in self.external['users']:
+ log.error('Creating user: '+u['username'])
+ self.keycloak.add_user(u['username'],u['first'],u['last'],u['email'],'1Provaprovaprova',group=u['groups'][0])
- # with open(os.path.join(app.root_path, "../custom/jsons/google_all_imported_espinalt.json"),"r") as crt:
- # pprint(data)
-
+ def sync_to_moodle(self):
+ users=self.get_mix_users()
+ for u in users:
+ if not u['moodle']:
+ log.error('Creating moodle user: '+u['username'])
+ self.moodle.create_user(u['email'],u['username'],'-1Provaprovaprova',u['first'],u['last'])
+ def sync_to_nextcloud(self):
+ users=self.get_mix_users()
+ for u in users:
+ if not u['nextcloud']:
+ log.error('Creating nextcloud user: '+u['username'])
+ group=u['keycloak_groups'][0] if len(u['keycloak_groups']) else False
+ try:
+ self.nextcloud.add_user(u['username'],'-1Provaprovaprova',1000,group,u['email'],u['first']+' '+u['last'])
+ except ProviderItemExists:
+ log.error('User '+u['username']+' already exists. Skipping...')
+ continue
+ except:
+ log.error(traceback.format_exc())
+ #
Las contraseñas deben tener al menos 1 dígito(s).
Las contraseñas deben tener al menos 1 mayúscula(s).
Las contraseñas deben tener al menos 1 caracter(es) no alfanumérico(s) como *,-,
diff --git a/admin/src/admin/lib/keycloak.py b/admin/src/admin/lib/keycloak.py
index b209260..7776d03 100644
--- a/admin/src/admin/lib/keycloak.py
+++ b/admin/src/admin/lib/keycloak.py
@@ -37,6 +37,8 @@ class Keycloak():
realm_name=self.realm,
verify=self.verify)
+# keycloak_admin = KeycloakAdmin(server_url="http://isard-sso-keycloak:8080/auth/",username="admin",password="keycloakkeycloak",realm_name="master",verify=False)
+
######## Example create group and subgroup
# try:
@@ -65,26 +67,74 @@ class Keycloak():
self.connect()
return self.keycloak_admin.get_users({})
+# q = """select u.username,u.email,u.first_name,u.last_name, u.realm_id, 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
+# 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.username,u.email,u.first_name,u.last_name, u.realm_id, ua.value
+# order by u.username"""
+# cur.execute(q)
+# users = cur.fetchall()
+# fields = [a.name for a in cur.description]
+# cur.close()
+# conn.close()
+
+
+# users_with_lists = [list(l[:-4])+([[]] if l[-4] == [None] else [list(set(l[-4]))]) +\
+# ([[]] if l[-3] == [None] else [list(set(l[-3]))]) +\
+# ([[]] if l[-3] == [None] else [list(set(l[-2]))]) +\
+# ([[]] if l[-1] == [None] else [list(set(l[-1]))]) for l in users]
+
+# users_with_lists = [list(l[:-4])+([[]] if l[-4] == [None] else [list(set(l[-4]))]) +\
+# ([[]] if l[-3] == [None] else [list(set(l[-3]))]) +\
+# ([[]] if l[-3] == [None] else [list(set(l[-2]))]) +\
+# ([[]] if l[-1] == [None] else [list(set(l[-1]))]) for l in users_with_lists]
+
+# list_dict_users = [dict(zip(fields, r)) for r in users_with_lists]
+
+ ## Too slow
def get_users_with_groups_and_roles(self):
self.connect()
users=self.keycloak_admin.get_users({})
for user in users:
- log.error(user)
user['groups']=[g['path'] for g in self.keycloak_admin.get_user_groups(user_id=user['id'])]
user['roles']= [r['name'] for r in self.keycloak_admin.get_realm_roles_of_user(user_id=user['id'])]
return users
- def add_user(self,username,first,last,email,password):
+ def add_user(self,username,first,last,email,password,group=False):
# Returns user id
+ log.error('Creating group: '+str(group))
self.connect()
- return self.keycloak_admin.create_user({"email": email,
- "username": username,
- "enabled": True,
- "firstName": first,
- "lastName": last,
- "credentials":[{"type":"password",
- "value":password,
- "temporary":False}]})
+ username=username.lower()
+ try:
+ uid=self.keycloak_admin.create_user({"email": email,
+ "username": username,
+ "enabled": True,
+ "firstName": first,
+ "lastName": last,
+ "credentials":[{"type":"password",
+ "value":password,
+ "temporary":False}]})
+ except:
+ uid=self.keycloak_admin.get_user_id(username)
+ log.error(uid)
+ if group:
+ try:
+ gid=self.keycloak_admin.get_group_by_path(path='/'+group,search_in_subgroups=False)['id']
+ log.error('group created with gid: '+str(gid))
+ except:
+ self.keycloak_admin.create_group({"name":group})
+ gid=self.keycloak_admin.get_group_by_path('/'+group)['id']
+ log.error(gid)
+ self.keycloak_admin.group_user_add(uid,gid)
+
def add_user_role(self,client_id,user_id,role_id,role_name):
self.connect()
diff --git a/admin/src/admin/lib/moodle.py b/admin/src/admin/lib/moodle.py
index f122a4a..413f56f 100644
--- a/admin/src/admin/lib/moodle.py
+++ b/admin/src/admin/lib/moodle.py
@@ -3,6 +3,9 @@ from admin import app
import logging as log
+
+from .postgres import Postgres
+
# Module variables to connect to moodle api
class Moodle():
@@ -20,7 +23,10 @@ class Moodle():
self.url = url
self.endpoint = endpoint
self.verify=verify
-
+
+ self.pg=Postgres('isard-apps-postgresql','moodle',app.config['MOODLE_POSTGRES_USER'],app.config['MOODLE_POSTGRES_PASSWORD'])
+
+
def rest_api_parameters(self, in_args, prefix='', out_dict=None):
"""Transform dictionary/array structure to a flat dictionary, with key names
defining the structure.
@@ -70,14 +76,27 @@ class Moodle():
criteria = [{'key': key, 'value': value}]
user = self.call('core_user_get_users', criteria=criteria)
return user
-
+
def get_users_with_groups_and_roles(self):
- users=self.get_user_by('email','%%')['users']
- for user in users:
- user['groups']=[c['name'] for c in self.get_user_cohorts(user['id'])]
- user['roles']=[]
- log.error(users)
- return users
+ 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 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
+ group by u.id , username, first, last, email"""
+ (headers,users)=self.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]
+ return list_dict_users
+
+ ## NOT USED. Too slow
+ # def get_users_with_groups_and_roles(self):
+ # users=self.get_user_by('email','%%')['users']
+ # for user in users:
+ # user['groups']=[c['name'] for c in self.get_user_cohorts(user['id'])]
+ # user['roles']=[]
+ # return users
def enroll_user_to_course(self, user_id, course_id, role_id=5):
# 5 is student
diff --git a/admin/src/admin/lib/nextcloud.py b/admin/src/admin/lib/nextcloud.py
index bc0cb68..ce45e98 100644
--- a/admin/src/admin/lib/nextcloud.py
+++ b/admin/src/admin/lib/nextcloud.py
@@ -76,6 +76,27 @@ class Nextcloud():
raise
# 100 - successful
+# q = """select u.uid as username, adn.value as displayname, ade.value as email, json_agg(gg.displayname) as admin_groups,json_agg(g.displayname) as groups
+# from oc_users as u
+# left join oc_group_user as gu on gu.uid = u.uid
+# left join oc_groups as g on gu.gid = g.gid
+# left join oc_group_admin as ga on ga.uid = u.uid
+# left join oc_groups as gg on gg.gid = ga.gid
+# left join oc_accounts_data as adn on adn.uid = u.uid and adn.name = 'displayname'
+# left join oc_accounts_data as ade on ade.uid = u.uid and ade.name = 'email'
+# group by u.uid, adn.value, ade.value"""
+# cur.execute(q)
+# users = cur.fetchall()
+# fields = [a.name for a in cur.description]
+# cur.close()
+# conn.close()
+
+
+# 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]
+# 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_with_lists]
+# list_dict_users = [dict(zip(fields, r)) for r in users_with_lists]
+
+ ### Too slow...
def get_users_list(self):
url = self.apiurl + "users?format=json"
try:
@@ -87,8 +108,11 @@ class Nextcloud():
log.error(traceback.format_exc())
raise
- def add_user(self,userid,userpassword,quota,group='',email='',displayname=''):
- data={'userid':userid,'password':userpassword,'quota':quota,'groups[]':group,'email':email,'displayname':displayname}
+ def add_user(self,userid,userpassword,quota,group=False,email='',displayname=''):
+ 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',
@@ -98,7 +122,9 @@ class Nextcloud():
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: raise ProviderGroupNotExists
+ if result['ocs']['meta']['statuscode'] == 104:
+ self.add_group(group)
+ # raise ProviderGroupNotExists
log.error('Get Nextcloud provider user add error: '+str(result))
raise ProviderOpError
except:
diff --git a/admin/src/admin/lib/postgres.py b/admin/src/admin/lib/postgres.py
index b8ae12e..ab2f441 100644
--- a/admin/src/admin/lib/postgres.py
+++ b/admin/src/admin/lib/postgres.py
@@ -34,6 +34,12 @@ class Postgres():
self.conn.commit()
# return self.cur.fetchall()
+ def select_with_headers(self,sql):
+ self.cur.execute(sql)
+ data=self.cur.fetchall()
+ fields = [a.name for a in self.cur.description]
+ return (fields,data)
+
# def update_moodle_saml_plugin(self):
# plugin[('idpmetadata', '
NrtA5ynG0htowP3SXw7dBJRIAMxn-1PwuuXwOwNhlRwMIICmzCCAYMCBgF5jb0RCTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjEwNTIxMDcwMjI4WhcNMzEwNTIxMDcwNDA4WjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCI8xh/C0+frz3kgWiUbziTDls71R2YiXLSVE+bw7gbEgZUGCLhoEI679azMtIxmnzM/snIX+yTb12+XoYkgbiLTMPQfnH+Kiab6g3HL3KPfhqS+yWkFxOoCp6Ibmp7yPlVWuHH+MBfO8OBr/r8Ao7heFbuzjiLd1KG67rcoaxfDgMuBoEomg1bgEjFgHaQIrSC6OZzH0h987/arqufZXeXlfyiqScMPUi+u5IpDWSwz06UKP0k8mxzNSlpZ93CKOUSsV0SMLxqg7FQ3SGiOk577bGW9o9BDTkkmSo3Up6smc0LzwvvUwuNd0B1irGkWZFQN9OXJnJYf1InEebIMtmPAgMBAAEwDQYJKoZIhvcNAQELBQADggEBADM34+qEGeBQ22luphVTuVJtGxcbxLx7DfsT0QfJD/OuxTTbNAa1VRyarb5juIAkqdj4y2quZna9ZXLecVo4RkwpzPoKoAkYA8b+kHnWqEwJi9iPrDvKb+GR0bBkLPN49YxIZ8IdKX/PRa3yuLHe+loiNsCaS/2ZK2KO46COsqU4QX1iVhF9kWphNLybjNAX45B6cJLsa1g0vXLdm3kv3SB4I2fErFVaOoDtFIjttoYlXdpUiThkPXBfr7N67P3dZHaS4tjJh+IZ8I6TINpcsH8dBkUhzYEIPHCePwSiC1w6WDBLNDuKt1mj1CZrLq+1x+Yhrs+QNRheEKGi89HZ8N0=urn:oasis:names:tc:SAML:2.0:nameid-format:persistenturn:oasis:names:tc:SAML:2.0:nameid-format:transienturn:oasis:names:tc:SAML:1.1:nameid-format:unspecifiedurn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress')]
# pg_update = """UPDATE mdl_config_plugins set title = %s where plugin = auth_saml2 and name ="""
diff --git a/admin/src/admin/static/js/external.js b/admin/src/admin/static/js/external.js
index 362b898..c9a0da4 100644
--- a/admin/src/admin/static/js/external.js
+++ b/admin/src/admin/static/js/external.js
@@ -12,6 +12,24 @@ $(document).ready(function() {
$('#modalImportForm')[0].reset();
});
+ $('.btn-sync').on('click', function () {
+ $.ajax({
+ type: "PUT",
+ url:"/isard-sso-admin/external",
+ 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...')
+ }
+ });
+ });
+
$("#modalImport #send").on('click', function(e){
var form = $('#modalImportForm');
form.parsley().validate();
diff --git a/admin/src/admin/static/js/users.js b/admin/src/admin/static/js/users.js
index 17130e1..0d2ff32 100644
--- a/admin/src/admin/static/js/users.js
+++ b/admin/src/admin/static/js/users.js
@@ -14,6 +14,42 @@ $(document).ready(function() {
$('#modalAdd').parsley();
});
+ $('.btn-sync_to_moodle').on('click', function () {
+ $.ajax({
+ type: "POST",
+ url:"/isard-sso-admin/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:"/isard-sso-admin/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": {
diff --git a/admin/src/admin/static/templates/pages/external.html b/admin/src/admin/static/templates/pages/external.html
index f6a2e8d..7977142 100644
--- a/admin/src/admin/static/templates/pages/external.html
+++ b/admin/src/admin/static/templates/pages/external.html
@@ -15,6 +15,7 @@
External