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}
' + # _content = f"
{_content}
" #if 'dom' not in _request.headers else f'
{_content}
' 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 -
{%include "menu.html" %}
+
{%include "menu.html" %}
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 @@ - +