diff --git a/cms/engine/plugins/login.py b/cms/engine/plugins/login.py
new file mode 100644
index 0000000..b65f26e
--- /dev/null
+++ b/cms/engine/plugins/login.py
@@ -0,0 +1,25 @@
+import json
+import pandas as pd
+import importlib
+import importlib.util
+import os
+
+#
+# Defining the decorator to be used in plugins, this will enable simple loading and assigning mimetype to the output (if any)
+#
+import cms
+# @cms.Plugin(mimetype="application/json")
+# def authenticate(**_args) :
+# _config = _args['config']
+# _request= _args['request']
+# #
+# # let's load the configuration for
+# _manager = cms.secure.Manager(config=_config)
+# #
+# #
+# _cookies,_args = _manager.authenticate(request=_request)
+
+
+#
+# The html page weill be provided by the front-end
+#
\ No newline at end of file
diff --git a/cms/secure.py b/cms/secure.py
index 3b64726..e5b4c66 100644
--- a/cms/secure.py
+++ b/cms/secure.py
@@ -52,8 +52,10 @@ class Manager :
#
# we need to load the permissions here ...
#
+
_kwargs = _appConfig['system']['source']['secure']
- self._loginURI = [_appConfig['system']['context']]
+
+ self._loginURI = [_appConfig['system'].get('context','')]
if 'uri' in _kwargs :
self._loginURI.appendd(_kwargs['uri'])
else:
@@ -62,14 +64,14 @@ class Manager :
#
# we will assume that all authenticated users have access to every part of the site
#
- if 'authorization' in _kwargs:
+ if 'authorization' in _kwargs and _kwargs['authorization']:
# #
# # loading permissions table from a designated location
reader = transport.get.reader(**_kwargs['authorization'])
self._permissions = reader.read()
-
+
#
# @TODO: add the login page provided int the configuration with full permissions
# or
diff --git a/cms/sites/__init__.py b/cms/sites/__init__.py
index 7450f16..11d6ce5 100644
--- a/cms/sites/__init__.py
+++ b/cms/sites/__init__.py
@@ -18,6 +18,7 @@ import pandas as pd
class RequestController :
def __init__(self,_route):
+ # self._plugins = _plugins
self._routes = _route
def isfile(self,request):
#
@@ -99,6 +100,11 @@ class Initialization (IOConfig):
# self._config = self.read_config(**_args)
self._args = _args
#
+ # in case the path provided does NOT have the manifest
+ if 'path' in self._args and not os.path.isfile(self._args['path']) :
+ #
+ self._args['path'] = f"{self._args['path']}{os.sep}qcms-manifest.json"
+ #
# Invoke initialization
self.reload()
#
@@ -225,9 +231,11 @@ class Initialization (IOConfig):
self.set('system.icon',_icon)
self.set('system.logo',_icon)
+
#
# from the path provided we can determine the location of the project
_homefolder = os.sep.join(_args['path'].split(os.sep)[:-1])
+
if _homefolder and os.path.exists(os.sep.join([_homefolder,_root])) :
self.set('layout.location',_homefolder)
@@ -310,6 +318,20 @@ class Initialization (IOConfig):
# self._config['layout']['menu'] = _menu
else:
pass
+ def _api(self):
+ """
+ This function will update public facing api provided
+ """
+ _context = self.get('system.context')
+ _plugins = self.get('plugins')
+ for _key in ['debug','log'] :
+ _pointer = getattr(self,_key)
+ _uri = f'{_context}/api/system/{_key}'
+ if _uri[0] == '/' :
+ _uri = _uri[1:]
+ _plugins[_uri] = _pointer
+ self.set('plugins',_plugins)
+
def plugins (self,**_args):
"""
This function will load the plugins from disk (only)
@@ -319,15 +341,18 @@ class Initialization (IOConfig):
_parentContext = self.get('system.parentContext')
_map = {}
_plugins = {}
+
# if self.get('system.source.id') == 'cloud' :
# _plugins = cloud.plugins(_context)
# else:
# _plugins = disk.plugins(context=_context)
- _uri = f'{_context}/api/system/debug'
- if _uri.startswith('/') :
- _uri = _uri[1:]
- # _uri = _uri if not _context else f'{_context}/{_uri}'
- _plugins[_uri] = self.debug
+ # _uri = f'{_context}/api/system/debug'
+ # if _uri.startswith('/') :
+ # _uri = _uri[1:]
+ # # _uri = _uri if not _context else f'{_context}/{_uri}'
+ # _plugins[_uri] = self.debug
+
+ self._api() #-- adding default api calls
if os.path.exists(_folder) and self.get('plugins'):
_items = self.get('plugins')
@@ -360,11 +385,14 @@ class Initialization (IOConfig):
#
# Updating plugins from disk/cloud
_plugins = _map if not _plugins else dict(_plugins,**_map)
+
#
# if we have login enabled we should add them as a plugins
#
self.set('plugins',_plugins)
+ self._api() #-- updating with system level api
+
self.log(action='init.plugins',module='plugins',input=list(_plugins.keys()))
class Site(Initialization) :
@@ -431,11 +459,12 @@ class Site(Initialization) :
# _content = f'
{_content}
'
if _uri.split('.')[-1].strip().lower() == 'md':
_content = mistune.html(_content).replace(""",'"').replace("<","<").replace(">",">") if _uri[-2:] in ['md','MD','Md','mD'] else _content
- _content = f"{_content}
" #if 'dom' not in _request.headers else f''
+ # _content = f"{_content}
" #if 'dom' not in _request.headers else f''
else:
- _env = Environment(loader=BaseLoader()).from_string(_content)
+ _env = Environment(loader=BaseLoader()).from_string(f"{_content}
")
_content = str(_env.render(**self.get(None)))
pass
+
return _content,_mimeType
def uri(self,request):
if 'uri' in request.headers or 'uri' in request.args :
@@ -447,6 +476,7 @@ class Site(Initialization) :
#
file = request.path.replace(f'{_route}','')
#
+
if file.startswith('//') or file.startswith('/') :
# NOTE: false positive if file.startswith('/') is used
file = file[2:] if file.startswith('//') else file[1:]
@@ -502,6 +532,7 @@ class Site(Initialization) :
# _content = io.BytesIO(f.read())
# f.close()
+
_content = self.open(uri=self.path(_uri),mode='rb')
_content = io.BytesIO( _content )
_kwargs = {'allow':1,'mimeType':_mimeType,'extension':_extension,
@@ -510,7 +541,7 @@ class Site(Initialization) :
self.log(action='file.read',module='site.read',input=_kwargs)
if _content :
return _content, _mimeType
- return None, 'plain/html'
+ return None, 'text/html'
# if 'html' in _mimetype :
# _args = {'layout':self.get('layout'),'system':self.get('system')}
@@ -554,6 +585,7 @@ class Site(Initialization) :
return None
def apply_tags (self,_html):
_kwargs = {'layout':self.get('layout'),'system':self.get('system')}
+
_env = Environment(loader=BaseLoader()).from_string(f'{_html}
')
return _env.render(**_kwargs)
def run(self,_request) :
@@ -562,8 +594,6 @@ class Site(Initialization) :
_mimeType = 'text/html'
_code = 404
_key = _request.path[1:] #if self.get('system.context') != '' else _request.path[1:]
- # print ([_key,_key in list(_plugins.keys())])
- # print (list (_plugins.keys()))
if _plugins and _key in _plugins:
_mimeType = 'application/octet-stream'
_pointer = _plugins.get(_key)
@@ -606,6 +636,7 @@ class QCMS:
for _name in _routes :
self._routes.append(_name)
_path = _routes[_name]['path']
+
self._sites[_name] = Site(context=_name,path=_path,caller=_app)
# self._sites[f'{_name}/'] = self._sites[_name]
@@ -623,6 +654,7 @@ class QCMS:
isfile = self.inspect.isfile(request)
isapi = self.inspect.isapi(request)
isroute= self.inspect.isroute(request)
+
if not isapi and not isfile:
return self._render(request)
#
diff --git a/cms/static/js/qcms/login/oauth2.0.js b/cms/static/js/qcms/login/oauth2.0.js
new file mode 100644
index 0000000..ec6b414
--- /dev/null
+++ b/cms/static/js/qcms/login/oauth2.0.js
@@ -0,0 +1,22 @@
+if(!qcms){
+ var qcms = {}
+}
+
+if(!qcms.login){
+ qcms.login = {}
+}
+
+qcms.login.oauth = function (_config){
+ //
+ // configuration for the oauth
+ if (_config){
+ var url = [_config.authorization_url+'?']
+ _attr = ['client_id','client_secret','scope','redirect_uri']
+ _attr.forEach((_key)=>{
+ url.push( _config[_key].trim() )
+ })
+ //
+ // We should have the URL that will implement the Oauth 2.0 flow
+ this.url = url
+ }
+}
\ No newline at end of file
diff --git a/cms/static/js/qcms/login/pam.js b/cms/static/js/qcms/login/pam.js
new file mode 100644
index 0000000..2e5c6bd
--- /dev/null
+++ b/cms/static/js/qcms/login/pam.js
@@ -0,0 +1,12 @@
+if(!qcms){
+ var qcms = {}
+}
+
+if(!qcms.login){
+ qcms.login = {}
+}
+
+qcms.login.pam = function (_args){
+ this.url = (_args.uri)?_args.uri : 'login/pam-login.html'
+ this.url = ([qcms.context,this.url]).join('/')
+}
\ No newline at end of file
diff --git a/cms/static/js/qcms/page-loader.js b/cms/static/js/qcms/page-loader.js
index 76d047b..36dbdc0 100644
--- a/cms/static/js/qcms/page-loader.js
+++ b/cms/static/js/qcms/page-loader.js
@@ -36,7 +36,7 @@ qcms.page.Observer = function (_parentId,_domId,_uri){
http.post(_uri,function(x){
var _dom = $(x.responseText)
-
+ _dom = $('').append(_dom)
var _found = qcms.html.hasNode( $(_id), $(_dom))
if (_found == 0){
@@ -83,7 +83,7 @@ qcms.page.loader = function(_parentId,_layout){
}
}
qcms.page.load = function (_uri,_id){
- console.log([_uri,' *** ',_id])
+
var http = HttpClient.instance()
http.get(_uri,(_x)=>{
// var _id = _id[0] == '#' || _id[0] == '.'?_id : (jx.dom.exists(_id)?`#${_id}`:`.${_id}`)
diff --git a/cms/static/js/qcms/utils.js b/cms/static/js/qcms/utils.js
index 4502f39..dd77162 100644
--- a/cms/static/js/qcms/utils.js
+++ b/cms/static/js/qcms/utils.js
@@ -48,6 +48,7 @@ qcms.code.documentation= function(_uri,_id) {
this._id = _id[0] == '#'?_id :( _id[0] == '.' ?_id: '#'+_id)
this.events = {_open:{},_find:{}}
this.events._open = function(_uri){
+
qcms.page.load(_uri,`${_id} .content`)
}
@@ -97,7 +98,8 @@ qcms.code.documentation= function(_uri,_id) {
// var events = this.events
// var _openEvent =this._openEvent
// var _find = this.events._find ;
-
+ $(this._id).empty()
qcms.utils.csv(this) //(this._uri,this.render)
+ $(this._id).find('*.child').show() //css({display:'block'})
}
}
diff --git a/cms/templates/index.html b/cms/templates/index.html
index 784a579..22bcb98 100644
--- a/cms/templates/index.html
+++ b/cms/templates/index.html
@@ -52,7 +52,7 @@ Vanderbilt University Medical Center
-
+
diff --git a/cms/templates/libs.html b/cms/templates/libs.html
index f156c04..4338a59 100644
--- a/cms/templates/libs.html
+++ b/cms/templates/libs.html
@@ -19,7 +19,7 @@
-
+