diff --git a/admin/docker/Dockerfile b/admin/docker/Dockerfile
index d534cd7..aba1d63 100644
--- a/admin/docker/Dockerfile
+++ b/admin/docker/Dockerfile
@@ -12,7 +12,7 @@ COPY admin/docker/requirements.pip3 /requirements.pip3
RUN pip3 install --no-cache-dir -r requirements.pip3
RUN apk del .build_deps
-RUN apk add curl
+RUN apk add curl py3-yaml
# SSH configuration
ARG SSH_ROOT_PWD
diff --git a/admin/src/api/__init__.py b/admin/src/admin/__init__.py
similarity index 93%
rename from admin/src/api/__init__.py
rename to admin/src/admin/__init__.py
index 1abe5ec..672bb99 100644
--- a/admin/src/api/__init__.py
+++ b/admin/src/admin/__init__.py
@@ -20,13 +20,14 @@ app.secret_key = "Change this key!//\xf7\x83\xbe\x17\xfa\xa3zT\n\\]m\xa6\x8bF\xd
print('Starting isard-sso api...')
-from api.lib.load_config import loadConfig
+from admin.lib.load_config import loadConfig
try:
loadConfig(app)
except:
print('Could not get environment variables...')
-
+from admin.lib.admin import Admin
+app.admin=Admin()
'''
Debug should be removed on production!
diff --git a/admin/src/admin/__pycache__/__init__.cpython-38.pyc b/admin/src/admin/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000..8ffb775
Binary files /dev/null and b/admin/src/admin/__pycache__/__init__.cpython-38.pyc differ
diff --git a/admin/src/admin/lib/__pycache__/admin.cpython-38.pyc b/admin/src/admin/lib/__pycache__/admin.cpython-38.pyc
new file mode 100644
index 0000000..71cb8d5
Binary files /dev/null and b/admin/src/admin/lib/__pycache__/admin.cpython-38.pyc differ
diff --git a/admin/src/admin/lib/__pycache__/keycloak.cpython-38.pyc b/admin/src/admin/lib/__pycache__/keycloak.cpython-38.pyc
new file mode 100644
index 0000000..3d889a6
Binary files /dev/null and b/admin/src/admin/lib/__pycache__/keycloak.cpython-38.pyc differ
diff --git a/admin/src/api/lib/__pycache__/load_config.cpython-38.pyc b/admin/src/admin/lib/__pycache__/load_config.cpython-38.pyc
similarity index 62%
rename from admin/src/api/lib/__pycache__/load_config.cpython-38.pyc
rename to admin/src/admin/lib/__pycache__/load_config.cpython-38.pyc
index 3383d33..f16472e 100644
Binary files a/admin/src/api/lib/__pycache__/load_config.cpython-38.pyc and b/admin/src/admin/lib/__pycache__/load_config.cpython-38.pyc differ
diff --git a/admin/src/api/lib/__pycache__/menu.cpython-38.pyc b/admin/src/admin/lib/__pycache__/menu.cpython-38.pyc
similarity index 100%
rename from admin/src/api/lib/__pycache__/menu.cpython-38.pyc
rename to admin/src/admin/lib/__pycache__/menu.cpython-38.pyc
diff --git a/admin/src/admin/lib/__pycache__/moodle.cpython-38.pyc b/admin/src/admin/lib/__pycache__/moodle.cpython-38.pyc
new file mode 100644
index 0000000..df413a4
Binary files /dev/null and b/admin/src/admin/lib/__pycache__/moodle.cpython-38.pyc differ
diff --git a/admin/src/admin/lib/__pycache__/nextcloud.cpython-38.pyc b/admin/src/admin/lib/__pycache__/nextcloud.cpython-38.pyc
new file mode 100644
index 0000000..86c6e38
Binary files /dev/null and b/admin/src/admin/lib/__pycache__/nextcloud.cpython-38.pyc differ
diff --git a/admin/src/admin/lib/__pycache__/nextcloud_exc.cpython-38.pyc b/admin/src/admin/lib/__pycache__/nextcloud_exc.cpython-38.pyc
new file mode 100644
index 0000000..52dac4f
Binary files /dev/null and b/admin/src/admin/lib/__pycache__/nextcloud_exc.cpython-38.pyc differ
diff --git a/admin/src/admin/lib/admin.py b/admin/src/admin/lib/admin.py
new file mode 100644
index 0000000..4d902cf
--- /dev/null
+++ b/admin/src/admin/lib/admin.py
@@ -0,0 +1,58 @@
+from .keycloak import Keycloak
+from .moodle import Moodle
+from .nextcloud import Nextcloud
+
+from pprint import pprint
+class Admin():
+ def __init__(self):
+ URL="http://isard-sso-keycloak:8080/auth/"
+ USERNAME='admin'
+ PASSWORD='keycloakkeycloak'
+ REALM="master"
+ VERIFY_CERT=True
+ self.keycloak=Keycloak(URL,USERNAME,PASSWORD,REALM,VERIFY_CERT)
+
+ KEY = "a1d8b3248e1a3e3b839645503df0e3a5"
+ URL = "https://moodle.santantoni.duckdns.org"
+ ENDPOINT="/webservice/rest/server.php"
+ self.moodle=Moodle(KEY,URL,ENDPOINT)
+
+ URL="https://nextcloud.santantoni.duckdns.org"
+ USERNAME='admin'
+ PASSWORD='N3xtcl0ud'
+ VERIFY_CERT=False
+ self.nextcloud=Nextcloud(URL,USERNAME,PASSWORD,VERIFY_CERT)
+
+ pprint(self.get_moodle_users())
+ pprint(self.get_keycloak_users())
+ pprint(self.get_nextcloud_users())
+
+ def get_moodle_users(self):
+ users = self.moodle.get_user_by('email','%%')['users']
+ return [{"id":u['id'],
+ "username":u['username'],
+ "first": u['firstname'],
+ "last": u['lastname'],
+ "email": u['email']}
+ for u in users]
+
+ def get_keycloak_users(self):
+ users = self.keycloak.get_users()
+ return [{"id":u['id'],
+ "username":u['username'],
+ "first": u.get('firstName',None),
+ "last": u.get('lastName',None),
+ "email": u.get('email','')}
+ for u in users]
+
+ def get_nextcloud_users(self):
+ users = self.nextcloud.get_users_list()
+ users_list=[]
+ for user in users:
+ u=self.nextcloud.get_user(user)
+ users_list.append({"id":u['id'],
+ "username":u['id'],
+ "first": u['displayname'],
+ "last": None,
+ "email": u['email']})
+ return users_list
\ No newline at end of file
diff --git a/admin/src/admin/lib/keycloak.py b/admin/src/admin/lib/keycloak.py
new file mode 100644
index 0000000..70e9a6e
--- /dev/null
+++ b/admin/src/admin/lib/keycloak.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+# coding=utf-8
+import time
+from admin import app as application
+from datetime import datetime, timedelta
+import pprint
+
+import logging
+import traceback
+import yaml, json
+
+from jinja2 import Environment, FileSystemLoader
+
+from keycloak import KeycloakAdmin
+
+class Keycloak():
+ """https://www.keycloak.org/docs-api/13.0/rest-api/index.html
+ https://github.com/marcospereirampj/python-keycloak
+ """
+ def __init__(self,url,username,password,realm,verify=True):
+ self.keycloak_admin = KeycloakAdmin(server_url=url,
+ username=username,
+ password=password,
+ realm_name=realm,
+ verify=verify)
+
+ ## USERS
+
+ def get_user_id(self,username):
+ return self.keycloak_admin.get_user_id(username)
+
+ def get_users(self):
+ return self.keycloak_admin.get_users({})
+
+ def add_user(self,username,first,last,email,password):
+ # Returns user id
+ return self.keycloak_admin.create_user({"email": email,
+ "username": username,
+ "enabled": True,
+ "firstName": first,
+ "lastName": last,
+ "credentials":[{"type":"password",
+ "value":password,
+ "temporary":False}]})
+
+ def add_user_role(self,client_id,user_id,role_id,role_name):
+ return self.keycloak_admin.assign_client_role(client_id="client_id", user_id="user_id", role_id="role_id", role_name="test")
+
+ def delete_user(self,userid):
+ return self.keycloak_admin.delete_user(user_id=userid)
+
+ ## SYSTEM
+ def get_server_info(self):
+ return self.keycloak_admin.get_server_info()
+
+ def get_server_clients(self):
+ return self.keycloak_admin.get_clients()
+
+ ## CLIENTS
+
+ def get_client_roles(self,client_id):
+ return self.keycloak_admin.get_client_roles(client_id=client_id)
+
+ # def add_client_role(self,client_id,roleName):
+ # return self.keycloak_admin.create_client_role(client_id=client_id, {'name': roleName, 'clientRole': True})
diff --git a/admin/src/api/lib/load_config.py b/admin/src/admin/lib/load_config.py
similarity index 93%
rename from admin/src/api/lib/load_config.py
rename to admin/src/admin/lib/load_config.py
index a3f2640..a4de719 100644
--- a/admin/src/api/lib/load_config.py
+++ b/admin/src/admin/lib/load_config.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# coding=utf-8
-from api import app
+from admin import app
import os, sys
import logging as log
diff --git a/admin/src/admin/lib/moodle.py b/admin/src/admin/lib/moodle.py
new file mode 100644
index 0000000..9b473ec
--- /dev/null
+++ b/admin/src/admin/lib/moodle.py
@@ -0,0 +1,73 @@
+from requests import get, post
+# Module variables to connect to moodle api
+
+class Moodle():
+ """https://github.com/mrcinv/moodle_api.py
+ https://docs.moodle.org/dev/Web_service_API_functions
+ https://docs.moodle.org/311/en/Using_web_services
+ """
+
+ def __init__(self, key, url, endpoint):
+ self.key = key
+ self.url = url
+ self.endpoint = endpoint
+
+ 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.
+ Example usage:
+ >>> rest_api_parameters({'courses':[{'id':1,'name': 'course1'}]})
+ {'courses[0][id]':1,
+ 'courses[0][name]':'course1'}
+ """
+ if out_dict==None:
+ out_dict = {}
+ if not type(in_args) in (list,dict):
+ out_dict[prefix] = in_args
+ return out_dict
+ if prefix == '':
+ prefix = prefix + '{0}'
+ else:
+ prefix = prefix + '[{0}]'
+ if type(in_args)==list:
+ for idx, item in enumerate(in_args):
+ self.rest_api_parameters(item, prefix.format(idx), out_dict)
+ elif type(in_args)==dict:
+ for key, item in in_args.items():
+ self.rest_api_parameters(item, prefix.format(key), out_dict)
+ return out_dict
+
+ def call(self, fname, **kwargs):
+ """Calls moodle API function with function name fname and keyword arguments.
+ Example:
+ >>> call_mdl_function('core_course_update_courses',
+ courses = [{'id': 1, 'fullname': 'My favorite course'}])
+ """
+ parameters = self.rest_api_parameters(kwargs)
+ parameters.update({"wstoken": self.key, 'moodlewsrestformat': 'json', "wsfunction": fname})
+ response = post(self.url+self.endpoint, parameters, verify=False)
+ response = response.json()
+ if type(response) == dict and response.get('exception'):
+ raise SystemError("Error calling Moodle API\n", response)
+ return response
+
+ def create_user(self, email, username, password, first_name='-', last_name='-'):
+ data = [{'username': username, 'email':email,
+ 'password': password, 'firstname':first_name, 'lastname':last_name}]
+ user = self.call('core_user_create_users', users=data)
+ return user
+
+ def get_user_by(self, key, value):
+ criteria = [{'key': key, 'value': value}]
+ user = self.call('core_user_get_users', criteria=criteria)
+ return user
+
+ def enroll_user_to_course(self, user_id, course_id, role_id=5):
+ # 5 is student
+ data = [{'roleid': role_id, 'userid': user_id, 'courseid': course_id}]
+ enrolment = self.call('enrol_manual_enrol_users', enrolments=data)
+ return enrolment
+
+ def get_quiz_attempt(self, quiz_id, user_id):
+ attempts = self.call('mod_quiz_get_user_attempts', quizid=quiz_id, userid=user_id)
+ return attempts
\ No newline at end of file
diff --git a/admin/src/admin/lib/nextcloud.py b/admin/src/admin/lib/nextcloud.py
new file mode 100644
index 0000000..d731f24
--- /dev/null
+++ b/admin/src/admin/lib/nextcloud.py
@@ -0,0 +1,253 @@
+#!/usr/bin/env python
+# coding=utf-8
+
+#from ..lib.log import *
+import time,requests,json,pprint
+import traceback
+import logging as log
+from .nextcloud_exc import *
+
+class Nextcloud():
+ def __init__(self,url,username,password,verify):
+ self.verify_cert=verify
+ self.apiurl=url+'/ocs/v1.php/cloud/'
+ self.shareurl=url+'/ocs/v2.php/apps/files_sharing/api/v1/'
+ self.davurl=url+'/remote.php/dav/files/'
+ self.auth=(username,password)
+ self.user=username
+
+ def _request(self,method,url,data={},headers={'OCS-APIRequest':'true'},auth=False):
+ if auth == False: auth=self.auth
+ try:
+ return requests.request(method, url, data=data, auth=auth, verify=self.verify_cert, headers=headers).text
+
+ ## At least the ProviderSslError is not being catched or not raised correctly
+ except requests.exceptions.HTTPError as errh:
+ raise ProviderConnError
+ except requests.exceptions.Timeout as errt:
+ raise ProviderConnTimeout
+ except requests.exceptions.SSLError as err:
+ raise ProviderSslError
+ except requests.exceptions.ConnectionError as errc:
+ raise ProviderConnError
+ # except requests.exceptions.RequestException as err:
+ # raise ProviderError
+ except Exception as e:
+ if str(e) == 'an integer is required (got type bytes)':
+ raise ProviderConnError
+ raise ProviderError
+
+ def check_connection(self):
+ url = self.apiurl + "users/"+self.user+"?format=json"
+ try:
+ result = self._request('GET',url)
+ if json.loads(result)['ocs']['meta']['statuscode'] == 100: return True
+ raise ProviderError
+ except requests.exceptions.HTTPError as errh:
+ raise ProviderConnError
+ except requests.exceptions.ConnectionError as errc:
+ raise ProviderConnError
+ except requests.exceptions.Timeout as errt:
+ raise ProviderConnTimeout
+ except requests.exceptions.SSLError as err:
+ raise ProviderSslError
+ except requests.exceptions.RequestException as err:
+ raise ProviderError
+ except Exception as e:
+ if str(e) == 'an integer is required (got type bytes)':
+ raise ProviderConnError
+ raise ProviderError
+
+ def get_user(self,userid):
+ url = self.apiurl + "users/"+userid+"?format=json"
+ try:
+ result = json.loads(self._request('GET',url))
+ if result['ocs']['meta']['statuscode'] == 100: return result['ocs']['data']
+ raise ProviderItemNotExists
+ except:
+ log.error(traceback.format_exc())
+ raise
+ # 100 - successful
+
+ def get_users_list(self):
+ url = self.apiurl + "users?format=json"
+ try:
+ result = json.loads(self._request('GET',url))
+ if result['ocs']['meta']['statuscode'] == 100: return result['ocs']['data']['users']
+ log.error('Get Nextcloud provider users list error: '+str(result))
+ raise ProviderOpError
+ except:
+ 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}
+ 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: 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:
+ result = json.loads(self._request('DELETE',url))
+ if result['ocs']['meta']['statuscode'] == 100: return True
+ if result['ocs']['meta']['statuscode'] == 101: raise ProviderUserNotExists
+ log.error(traceback.format_exc())
+ raise ProviderOpError
+ except:
+ log.error(traceback.format_exc())
+ raise
+ # 100 - successful
+ # 101 - failure
+
+ def enable_user(self,userid):
+ None
+
+ def disable_user(self,userid):
+ None
+
+ def exists_user_folder(self,userid,userpassword,folder='IsardVDI'):
+ auth=(userid,userpassword)
+ url = self.davurl + userid +"/" + folder+"?format=json"
+ headers = {
+ 'Depth': '0',
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'OCS-APIRequest': 'true',
+ }
+ try:
+ result = self._request('PROPFIND',url,auth=auth,headers=headers)
+ if 'HTTP/1.1 200 OK' in result: return True
+ return False
+ except:
+ log.error(traceback.format_exc())
+ raise
+
+ def add_user_folder(self,userid,userpassword,folder='IsardVDI'):
+ auth=(userid,userpassword)
+ url = self.davurl + userid +"/" + folder+"?format=json"
+ headers = {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'OCS-APIRequest': 'true',
+ }
+ try:
+ result = self._request('MKCOL',url,auth=auth,headers=headers)
+ if result=='': return True
+ if 'The resource you tried to create already exists' in result: raise ProviderItemExists
+ log.error(result.split('message>')[1].split('<')[0])
+ raise ProviderOpError
+ except:
+ log.error(traceback.format_exc())
+ raise
+
+ def exists_user_share_folder(self,userid,userpassword,folder='IsardVDI'):
+ auth=(userid,userpassword)
+ url = self.shareurl + "shares?format=json"
+ headers = {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'OCS-APIRequest': 'true',
+ }
+ try:
+ result = json.loads(self._request('GET', url, auth=auth, headers=headers))
+ if result['ocs']['meta']['statuscode']==200:
+ share=[s for s in result['ocs']['data'] if s['path'] == '/'+folder]
+ if len(share) >= 1:
+ # Should we delete all but the first (0) one?
+ return {'token': share[0]['token'],
+ 'url': share[0]['url']}
+ raise ProviderItemNotExists
+ raise ProviderOpError
+ except:
+ log.error(traceback.format_exc())
+ raise
+
+ def add_user_share_folder(self,userid,userpassword,folder='IsardVDI'):
+ auth=(userid,userpassword)
+ data={'path':'/'+folder,'shareType':3}
+ url = self.shareurl + "shares?format=json"
+ headers = {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'OCS-APIRequest': 'true',
+ }
+ try:
+ result = json.loads(self._request('POST',url, data=data, auth=auth, headers=headers))
+ if result['ocs']['meta']['statuscode'] == 100 or result['ocs']['meta']['statuscode'] == 200:
+ return {'token': result['ocs']['data']['token'],
+ 'url': result['ocs']['data']['url']}
+ log.error('Add user share folder error: '+result['ocs']['meta']['message'])
+ raise ProviderFolderNotExists
+ except:
+ log.error(traceback.format_exc())
+ raise
+
+ def get_group(self,userid):
+ None
+
+ def get_groups_list(self):
+ url = self.apiurl + "groups?format=json"
+ try:
+ result = json.loads(self._request('GET',url))
+ if result['ocs']['meta']['statuscode'] == 100: return [g for g in result['ocs']['data']['groups'] if '-' in g]
+ raise ProviderOpError
+ except:
+ log.error(traceback.format_exc())
+ raise
+
+ def add_group(self,groupid):
+ data={'groupid':groupid}
+ url = self.apiurl + "groups?format=json"
+ headers = {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'OCS-APIRequest': 'true',
+ }
+ try:
+ result = json.loads(self._request('POST',url, data=data, auth=self.auth, headers=headers))
+ if result['ocs']['meta']['statuscode'] == 100: return True
+ if result['ocs']['meta']['statuscode'] == 102: raise ProviderItemExists
+ raise ProviderOpError
+ except:
+ log.error(traceback.format_exc())
+ raise
+ # 100 - successful
+ # 101 - invalid input data
+ # 102 - group already exists
+ # 103 - failed to add the group
+
+ def delete_group(self,groupid):
+ url = self.apiurl + "groups/"+groupid+"?format=json"
+ headers = {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'OCS-APIRequest': 'true',
+ }
+ try:
+ result = json.loads(self._request('DELETE',url, auth=self.auth, headers=headers))
+ if result['ocs']['meta']['statuscode'] == 100: return True
+ log.error(traceback.format_exc())
+ raise ProviderOpError
+ except:
+ log.error(traceback.format_exc())
+ raise
+ # 100 - successful
+ # 101 - invalid input data
+ # 102 - group already exists
+ # 103 - failed to add the group
+
diff --git a/admin/src/admin/lib/nextcloud_exc.py b/admin/src/admin/lib/nextcloud_exc.py
new file mode 100644
index 0000000..32baf33
--- /dev/null
+++ b/admin/src/admin/lib/nextcloud_exc.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+# coding=utf-8
+class ProviderConnError(Exception):
+ pass
+
+class ProviderSslError(Exception):
+ pass
+
+class ProviderConnTimeout(Exception):
+ pass
+
+class ProviderError(Exception):
+ pass
+
+class ProviderItemExists(Exception):
+ pass
+
+class ProviderItemNotExists(Exception):
+ pass
+
+class ProviderGroupNotExists(Exception):
+ pass
+
+class ProviderFolderNotExists(Exception):
+ pass
+
+
+class ProviderOpError(Exception):
+ pass
diff --git a/admin/src/api/static/_templates/apps.html b/admin/src/admin/static/_templates/apps.html
similarity index 100%
rename from admin/src/api/static/_templates/apps.html
rename to admin/src/admin/static/_templates/apps.html
diff --git a/admin/src/api/static/_templates/navbar_nextcloud.html b/admin/src/admin/static/_templates/navbar_nextcloud.html
similarity index 100%
rename from admin/src/api/static/_templates/navbar_nextcloud.html
rename to admin/src/admin/static/_templates/navbar_nextcloud.html
diff --git a/admin/src/api/static/_templates/nextcloud.html b/admin/src/admin/static/_templates/nextcloud.html
similarity index 100%
rename from admin/src/api/static/_templates/nextcloud.html
rename to admin/src/admin/static/_templates/nextcloud.html
diff --git a/admin/src/api/static/css/bootstrap.min.css b/admin/src/admin/static/css/bootstrap.min.css
similarity index 100%
rename from admin/src/api/static/css/bootstrap.min.css
rename to admin/src/admin/static/css/bootstrap.min.css
diff --git a/admin/src/api/static/css/dd.css b/admin/src/admin/static/css/dd.css
similarity index 100%
rename from admin/src/api/static/css/dd.css
rename to admin/src/admin/static/css/dd.css
diff --git a/admin/src/api/static/img/background.png b/admin/src/admin/static/img/background.png
similarity index 100%
rename from admin/src/api/static/img/background.png
rename to admin/src/admin/static/img/background.png
diff --git a/admin/src/api/static/img/logo.png b/admin/src/admin/static/img/logo.png
similarity index 100%
rename from admin/src/api/static/img/logo.png
rename to admin/src/admin/static/img/logo.png
diff --git a/admin/src/api/static/js/navbar.js b/admin/src/admin/static/js/navbar.js
similarity index 100%
rename from admin/src/api/static/js/navbar.js
rename to admin/src/admin/static/js/navbar.js
diff --git a/admin/src/api/static/templates/.gitkeep b/admin/src/admin/static/templates/.gitkeep
similarity index 100%
rename from admin/src/api/static/templates/.gitkeep
rename to admin/src/admin/static/templates/.gitkeep
diff --git a/admin/src/api/static/templates/header.html b/admin/src/admin/static/templates/header.html
similarity index 100%
rename from admin/src/api/static/templates/header.html
rename to admin/src/admin/static/templates/header.html
diff --git a/admin/src/api/static/templates/header.json b/admin/src/admin/static/templates/header.json
similarity index 100%
rename from admin/src/api/static/templates/header.json
rename to admin/src/admin/static/templates/header.json
diff --git a/admin/src/api/static/templates/header_nextcloud.html b/admin/src/admin/static/templates/header_nextcloud.html
similarity index 100%
rename from admin/src/api/static/templates/header_nextcloud.html
rename to admin/src/admin/static/templates/header_nextcloud.html
diff --git a/admin/src/admin/views/MenuViews.py b/admin/src/admin/views/MenuViews.py
new file mode 100644
index 0000000..b858891
--- /dev/null
+++ b/admin/src/admin/views/MenuViews.py
@@ -0,0 +1,28 @@
+#!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
+
+# from ..lib.admin import Admin
+# menu = Menu()
+
+# @app.route('/header/', methods=['GET'])
+# @app.route('/header//', methods=['GET'])
+# def api_v2_header(format,application=False):
+# if application == False:
+# if format == 'json':
+# if application == False:
+# return json.dumps(menu.get_header()), 200, {'Content-Type': 'application/json'}
+# if format == 'html':
+# if application == False:
+# return render_template('header.html')
+# if application == 'nextcloud':
+# return render_template('header_nextcloud.html')
+# if application == 'wordpress':
+# return render_template('header_wordpress.html')
\ No newline at end of file
diff --git a/admin/src/api/views/__init__.py b/admin/src/admin/views/__init__.py
similarity index 100%
rename from admin/src/api/views/__init__.py
rename to admin/src/admin/views/__init__.py
diff --git a/admin/src/admin/views/__pycache__/MenuViews.cpython-38.pyc b/admin/src/admin/views/__pycache__/MenuViews.cpython-38.pyc
new file mode 100644
index 0000000..c2a7a3e
Binary files /dev/null and b/admin/src/admin/views/__pycache__/MenuViews.cpython-38.pyc differ
diff --git a/admin/src/api/views/__pycache__/__init__.cpython-38.pyc b/admin/src/admin/views/__pycache__/__init__.cpython-38.pyc
similarity index 100%
rename from admin/src/api/views/__pycache__/__init__.cpython-38.pyc
rename to admin/src/admin/views/__pycache__/__init__.cpython-38.pyc
diff --git a/admin/src/api/__pycache__/__init__.cpython-38.pyc b/admin/src/api/__pycache__/__init__.cpython-38.pyc
deleted file mode 100644
index 82ea2c5..0000000
Binary files a/admin/src/api/__pycache__/__init__.cpython-38.pyc and /dev/null differ
diff --git a/admin/src/api/lib/menu.py b/admin/src/api/lib/menu.py
deleted file mode 100644
index b55c2f3..0000000
--- a/admin/src/api/lib/menu.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/env python
-# coding=utf-8
-# Copyright 2017 the Isard-vdi project authors:
-# Josep Maria Viñolas Auquer
-# Alberto Larraz Dalmases
-# License: AGPLv3
-import time
-from api import app as application
-from datetime import datetime, timedelta
-import pprint
-
-import logging
-import traceback
-import yaml, json
-
-from jinja2 import Environment, FileSystemLoader
-
-class Menu():
- def __init__(self):
- self.menudict=self.gen_header()
- pprint.pprint(self.menudict)
- self.write_headers()
- None
-
- def gen_header(self):
- with open(r'system.yaml') as yml:
- system=yaml.load(yml, Loader=yaml.FullLoader)
- apps_internal = []
- for app in system['apps_internal']:
- app['href']='https://'+app['subdomain']+'.'+application.config['DOMAIN']+app['href']
- del app['subdomain']
- apps_internal.append(app)
-
- with open(r'custom.yaml') as yml:
- custom=yaml.load(yml, Loader=yaml.FullLoader)
- custom['background_login']='https://api.'+application.config['DOMAIN']+custom['background_login']
- custom['logo']='https://api.'+application.config['DOMAIN']+custom['logo']
-
- menudict={**custom,**{'apps_internal':apps_internal}}
- menudict['user']={}
- menudict['user']['account']='https://sso.'+application.config['DOMAIN']+system['user']['account']
- menudict['user']['avatar']='https://sso.'+application.config['DOMAIN']+system['user']['avatar']
- menudict['user']['password']='https://sso.'+application.config['DOMAIN']+system['user']['password']
- return menudict
-
- def write_headers(self):
- env = Environment(loader=FileSystemLoader('api/static/_templates'))
- template = env.get_template('apps.html')
- output_from_parsed_template = template.render(data=self.menudict)
- print(output_from_parsed_template)
- with open("api/static/templates/header.html", "w") as fh:
- fh.write(output_from_parsed_template)
-
- with open("api/static/templates/header_nextcloud.html", "w") as fh:
- fh.write(output_from_parsed_template)
- with open("api/static/templates/header_nextcloud.html", "a") as fh:
- with open("api/static/_templates/nextcloud.html", "r") as nextcloud:
- fh.write(nextcloud.read())
- with open("api/static/templates/header.json", "w") as fh:
- fh.write(json.dumps(self.menudict))
-
- def get_header(self):
- return self.menudict
- # with open('menu.yaml', 'w') as yml:
- # print(yaml.dump(header, yml, allow_unicode=True))
\ No newline at end of file
diff --git a/admin/src/api/views/MenuViews.py b/admin/src/api/views/MenuViews.py
deleted file mode 100644
index 40efc3c..0000000
--- a/admin/src/api/views/MenuViews.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!flask/bin/python
-# coding=utf-8
-from api 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
-
-from ..lib.menu import Menu
-menu = Menu()
-
-@app.route('/header/', methods=['GET'])
-@app.route('/header//', methods=['GET'])
-def api_v2_header(format,application=False):
- if application == False:
- if format == 'json':
- if application == False:
- return json.dumps(menu.get_header()), 200, {'Content-Type': 'application/json'}
- if format == 'html':
- if application == False:
- return render_template('header.html')
- if application == 'nextcloud':
- return render_template('header_nextcloud.html')
- if application == 'wordpress':
- return render_template('header_wordpress.html')
\ No newline at end of file
diff --git a/admin/src/api/views/__pycache__/MenuViews.cpython-38.pyc b/admin/src/api/views/__pycache__/MenuViews.cpython-38.pyc
deleted file mode 100644
index 5e86e46..0000000
Binary files a/admin/src/api/views/__pycache__/MenuViews.cpython-38.pyc and /dev/null differ
diff --git a/admin/src/start.py b/admin/src/start.py
index 2a09cf8..c754f13 100644
--- a/admin/src/start.py
+++ b/admin/src/start.py
@@ -3,11 +3,8 @@
from gevent import monkey
monkey.patch_all()
-import yaml
-from api import app
+from admin import app
-# import pprint
-# pprint.pprint(app.yaml)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=9000, debug=False) #, logger=logger, engineio_logger=engineio_logger)
diff --git a/admin/src/system.yaml.example b/admin/src/system.yaml.example
deleted file mode 100644
index 226fd04..0000000
--- a/admin/src/system.yaml.example
+++ /dev/null
@@ -1,55 +0,0 @@
-apps_internal:
-- subdomain: nextcloud
- href: /
- icon: fa fa-cloud
- name: Núvol + crear arxius
- shortname: cloud
-- subdomain: nextcloud
- href: /apps/mail/setup
- icon: fa fa-envelope-o
- name: Correu
- shortname: email
-- subdomain: pad
- href: /
- icon: fa fa-file-text-o
- name: Pads
- shortname: pads
-- subdomain: nextcloud
- href: /apps/forms
- icon: fa fa-check-square-o
- name: Formularis
- shortname: forms
-- subdomain: nextcloud
- href: /apps/polls
- icon: fa fa-bar-chart
- name: Enquestes
- shortname: feedback
-- subdomain: nextcloud
- href: /apps/spreed
- icon: fa fa-commenting-o
- name: Xat
- shortname: chat
-- subdomain: nextcloud
- href: /apps/calendar
- icon: fa fa-calendar
- name: Calendari
- shortname: schedule
-- subdomain: wp
- href: /wp-login.php?saml_sso
- icon: fa fa-rss
- name: Webs
- shortname: webs
-- subdomain: nextcloud
- href: /apps/bbb
- icon: fa fa-video-camera
- name: Reunions BBB
- shortname: meets_bbb
-- subdomain: nextcloud
- href: /apps/photos
- icon: fa fa-file-image-o
- name: Fotos
- shortname: photos
-user:
- account: /auth/realms/master/account
- avatar: /auth/realms/master/avatar-provider
- password: /auth/realms/master/password
diff --git a/admin/src/tests/test_lib.py b/admin/src/tests/test_lib.py
index cf52403..57cef0d 100644
--- a/admin/src/tests/test_lib.py
+++ b/admin/src/tests/test_lib.py
@@ -28,4 +28,7 @@ new_user = keycloak_admin.create_user({"email": "example@example.com",
"enabled": True,
"firstName": "Example",
"lastName": "Example"})
-print(new_user)
\ No newline at end of file
+print(new_user)
+
+user_id_keycloak = keycloak_admin.get_user_id("admin")
+print(user_id_keycloak)
\ No newline at end of file
diff --git a/docker-compose-parts/admin.yml b/docker-compose-parts/admin.yml
index 4b16cfe..6ff59d8 100644
--- a/docker-compose-parts/admin.yml
+++ b/docker-compose-parts/admin.yml
@@ -19,6 +19,7 @@ services:
- /etc/localtime:/etc/localtime:ro
- ${BUILD_ROOT_PATH}/admin/src:/admin # Revome in production
- ${BUILD_ROOT_PATH}/custom:/admin/custom #:ro in production
+ - ${DATA_FOLDER}/avatars:/admin/avatars:ro
env_file:
- .env
command: sleep infinity
diff --git a/isard-sso b/isard-sso
index 790afd2..7a0176a 160000
--- a/isard-sso
+++ b/isard-sso
@@ -1 +1 @@
-Subproject commit 790afd2a9c70618e422b0e69ffa702f80a4ee1a6
+Subproject commit 7a0176a6e31ced64dc32fdcc175a21601747c0f7