Merge pull request 'version 3.0' (#52) from v3.0 into master

Reviewed-on: cloud/cms#52
master
Steve L. Nyemba 4 days ago
commit ead753cda0

@ -19,6 +19,7 @@ import base64
import io
import cms
from cms import index
import cms.cli
from cms.engine.config.structure import Layout, System
from cms.engine import project, themes
@ -142,8 +143,7 @@ def set_cloud(manifest:Annotated[str,typer.Argument(help="path of the auth-file
else:
_msg = INVALID_FOLDER
print (_msg)
@cli.command(name='secure')
# def set_key(path):
@cli.command(name='set-key')
def secure(
manifest:Annotated[str,typer.Argument(help="path of the manifest file")],
keyfile:Annotated[str,typer.Argument(help="path of the key file to generate")]):
@ -202,77 +202,77 @@ def load(**_args):
return getattr(module,_name) if hasattr(module,_name) else None
@cli.command(name='plugins')
def plugin_manager (manifest:Annotated[str,typer.Argument(help="path to manifest file")],
show:bool=typer.Option(default=False,help="list plugins loaded"),
add: Annotated[Optional[bool],typer.Option("--register/--unregister",help="add/remove a plugin to manifest use with --pointer option")] = None,
pointer:str=typer.Option(default=None,help="pointer is structured as 'filename.function'")
) :
"""
Manage plugins list loaded plugins,
"""
manifest = get_manifest(manifest)
_config = cms.engine.config.get(manifest)
if _config :
_root = os.sep.join(manifest.split(os.sep)[:-1] + [_config['layout']['root'],'_plugins'])
else :
_root = None
if _root and os.path.exists(_root) :
# files = os.listdir(_root)
_msg = f"""{FAILED} no operation was specified, please use --help option"""
# if 'plugins' in _config :
_plugins = _config['plugins'] if 'plugins' in _config else {}
# @cli.command(name='plugins')
# def plugin_manager (manifest:Annotated[str,typer.Argument(help="path to manifest file")],
# show:bool=typer.Option(default=False,help="list plugins loaded"),
# add: Annotated[Optional[bool],typer.Option("--register/--unregister",help="add/remove a plugin to manifest use with --pointer option")] = None,
# pointer:str=typer.Option(default=None,help="pointer is structured as 'filename.function'")
# ) :
# """
# Manage plugins list loaded plugins,
# """
# manifest = get_manifest(manifest)
# _config = cms.engine.config.get(manifest)
# if _config :
# _root = os.sep.join(manifest.split(os.sep)[:-1] + [_config['layout']['root'],'_plugins'])
# else :
# _root = None
# if _root and os.path.exists(_root) :
# # files = os.listdir(_root)
# _msg = f"""{FAILED} no operation was specified, please use --help option"""
# # if 'plugins' in _config :
# _plugins = _config['plugins'] if 'plugins' in _config else {}
if show :
if not _plugins :
_msg = f"""{FAILED} no plugins are loaded\n\t{manifest}"""
else:
_data = []
_plugConf = _config['plugins']
# if show :
# if not _plugins :
# _msg = f"""{FAILED} no plugins are loaded\n\t{manifest}"""
# else:
# _data = []
# _plugConf = _config['plugins']
for _name in _plugConf :
_log = {"files":_name,"loaded":len(_plugConf[_name]),"functions":json.dumps(_plugConf[_name])}
_data.append(_log)
_data= pd.DataFrame(_data)
# for _name in _plugConf :
# _log = {"files":_name,"loaded":len(_plugConf[_name]),"functions":json.dumps(_plugConf[_name])}
# _data.append(_log)
# _data= pd.DataFrame(_data)
# # # _data = plugins.stats(_plugins)
# # _data = cms.Plugin.stats(_plugins)
print (to_Table(_data))
_msg = f"""{PASSED} [bold]{_config['layout']['header']['title']}[/bold]: found a total of {_data.loaded.sum()} plugins loaded from {_data.shape[0]} file(s)\n\t{_root}"""
# # # # _data = plugins.stats(_plugins)
# # # _data = cms.Plugin.stats(_plugins)
# print (to_Table(_data))
# _msg = f"""{PASSED} [bold]{_config['layout']['header']['title']}[/bold]: found a total of {_data.loaded.sum()} plugins loaded from {_data.shape[0]} file(s)\n\t{_root}"""
if add in [True,False] and pointer :
# if add in [True,False] and pointer :
file,fnName = pointer.split('.')
# _fnpointer = plugins.load(_root,file+'.py',fnName)
# _fnpointer = cms.Plugin.load(_root,file+'.py',fnName)
_ploader = plugin_ix.Loader(file = os.sep.join([_root,file+'.py']))
# file,fnName = pointer.split('.')
# # _fnpointer = plugins.load(_root,file+'.py',fnName)
# # _fnpointer = cms.Plugin.load(_root,file+'.py',fnName)
# _ploader = plugin_ix.Loader(file = os.sep.join([_root,file+'.py']))
if add and _ploader.has(fnName):
if file not in _plugins :
_plugins[file] = []
# if add and _ploader.has(fnName):
# if file not in _plugins :
# _plugins[file] = []
if fnName not in _plugins[file] :
_plugins[file].append(fnName)
_msg = f"""{PASSED} [bold]{_config['layout']['header']['title']}[/bold]: registered {pointer}, use the --show option to list loaded plugins"""
else:
_msg = f"""{FAILED} [bold]{_config['layout']['header']['title']}[/bold]: could not register {pointer}, it already exists"""
elif add is False and file in _plugins:
_plugins[file] = [_name.strip() for _name in _plugins[file] if _name.strip() != fnName.strip() ]
_msg = f"""{PASSED} [bold]{_config['layout']['header']['title']}[/bold]: unregistered {pointer}, use the --show option to list loaded plugins """
# if fnName not in _plugins[file] :
# _plugins[file].append(fnName)
# _msg = f"""{PASSED} [bold]{_config['layout']['header']['title']}[/bold]: registered {pointer}, use the --show option to list loaded plugins"""
# else:
# _msg = f"""{FAILED} [bold]{_config['layout']['header']['title']}[/bold]: could not register {pointer}, it already exists"""
# elif add is False and file in _plugins:
# _plugins[file] = [_name.strip() for _name in _plugins[file] if _name.strip() != fnName.strip() ]
# _msg = f"""{PASSED} [bold]{_config['layout']['header']['title']}[/bold]: unregistered {pointer}, use the --show option to list loaded plugins """
# #
# # We need to write this down !!
if add in [True,False] :
# # #
# # # We need to write this down !!
# if add in [True,False] :
_config['plugins'] = _plugins
cms.engine.config.write(_config,manifest)
# else:
# _msg = f"""{FAILED} [bold]{_config['layout']['header']['title']}[/bold]: no plugins are loaded """
print()
print(_msg)
else:
_msg = f"""{FAILED} No plugin folder could be found in {manifest}"""
print (_msg)
# _config['plugins'] = _plugins
# cms.engine.config.write(_config,manifest)
# # else:
# # _msg = f"""{FAILED} [bold]{_config['layout']['header']['title']}[/bold]: no plugins are loaded """
# print()
# print(_msg)
# else:
# _msg = f"""{FAILED} No plugin folder could be found in {manifest}"""
# print (_msg)
@cli.command (name='create')
@ -501,4 +501,6 @@ def handle_theme (
global SYS_ARGS
if __name__ == '__main__':
cli.add_typer(cli_theme,name="themes",help="manage themes associated with a site")
cli.add_typer(cms.cli.auth.cli,name="login",help="manage login (authentication/authorization) to a sites")
cli.add_typer(cms.cli.plugins.cli,name="plugins",help="manage plugins associated with a site")
cli()

@ -10,6 +10,14 @@ from . import sites
from . import apexchart
from . import meta
from . import secure
# def get_manifest (manifest):
# if not manifest.endswith('json') and os.path.isdir(manifest):
# manifest = manifest if not manifest.endswith(os.sep) else os.sep.join(manifest.split(os.sep)[:-1])
# return os.sep.join([manifest,'qcms-manifest.json'])
# else:
# return manifest
class Plugin :
#
# decorator for plugin functions, this is a preliminary to enable future developement
@ -87,8 +95,7 @@ class Plugin :
#
# default plugins to load into the configuration file
@Plugin(mimetype="application/json")
def authorizationURL (**_args):
# _config = _args['config']
@ -144,4 +151,4 @@ def oauthFinalize (**_args):
<div style="font-size:13px">Please wait ...</div>
</div>
"""
return _html
return _html

@ -0,0 +1 @@
from . import plugins, secure, auth

@ -0,0 +1,85 @@
import typer
from typing_extensions import Annotated
from typing import Optional
from typing import Tuple
import os
import json
import plugin_ix as px
from enum import Enum
import pandas as pd
from rich.table import Table
from rich import print
import uuid
import cms
import requests
FAILED = '[ [red] \u2717 [/red] ]'
PASSED = '[ [green] \u2713 [/green] ]'
cli = typer.Typer()
@cli.command(name="set")
def set_auth (
id:Annotated[str,typer.Argument(help="identifier used in setting cookies")],
manifest:Annotated[str,typer.Argument(help="path manifest or site folder")],
registry:Annotated[str,typer.Argument(help="path to the registry created by plugin-ix")],
authpath:Annotated[str,typer.Argument(help="Authentication file location, that contains the authentication model")]
):
"""
This function will set login configuration to a manifest
"""
try:
_args = {"id":id,"registry":registry,"path":authpath,"authorization":{}}
path = cms.engine.config.get_manifest(manifest=manifest)
_config = cms.engine.config.get(path)
_config['system']['source'] = {'secure':_args}
_secEngine = cms.secure.Manager(config=_config)
cms.engine.config.write(config=_config,path=path)
except Exception as e:
print (f"""{FAILED} [bold][red]{id}, failed [/red][/bold], error found {str(e)}""")
#
# we should try to test this configuration to see if it works
#
pass
def permissions():
pass
def inspect ():
pass
@cli.command("drop")
def remove (manifest:Annotated[str,typer.Argument(help="path manifest or site folder")]):
"""
This function removes login configuration from a manifest
"""
path = cms.engine.config.get_manifest(manifest=manifest)
_config = cms.engine.config.get(path)
_msg = f'{FAILED}'
try:
if 'secure' in _config['system']['source'] :
del _config['system']['source']['secure']
cms.engine.config.write(config=_config,path=path)
_msg = f'{PASSED} [green]Successfully[/green] removed secure attribute'
except Exception as e:
_msg = f'{_msg}, error found {str(e)}'
print (_msg)
pass
@cli.command(name="template")
def gen_auth (
_model:Annotated[str,typer.Argument(help="generate an authentication parameter file")],
):
"""
This function generates a template login file content for a model (pam, oauth2, nextcloud)
"""
_conf = {"method":_model}
_map = {"pam":{"age":3600},"nextcloud":{"url":"https://your-nextcloud-site"}}
#
# parameters client_id, client-secret,
_map["oauth2"] = {"client_id":"client_id","client_secret":"client_secret","scope":"profile","response_type":"code","authorization_url":"authorization_url","redirect_uri":"redirect_uri"}
if _model in _map :
_conf = dict(_conf, **_map.get(_model))
print (_conf)
print ()
print(f'{PASSED} [bold] Edit[/bold] and [bold]save[/bold] the content into an [bold]"authentication file"[/bold]')
else:
print (f"""{FAILED} [bold]{_model}[/bold] is not a supported authentication model""")

@ -0,0 +1,207 @@
import typer
from typing_extensions import Annotated
from typing import Optional
from typing import Tuple
import os
import json
import plugin_ix as px
from enum import Enum
import pandas as pd
from rich.table import Table
from rich import print
import cms
FAILED = '[ [red] \u2717 [/red] ]'
PASSED = '[ [green] \u2713 [/green] ]'
"""
Handling cli interface for plugins, performing add list and remove
"""
cli = typer.Typer()
def to_Table(df: pd.DataFrame):
"""Displays a Pandas DataFrame as a rich table."""
table = Table(show_header=True, header_style="bold magenta")
for col in df.columns:
table.add_column(col)
for _, row in df.iterrows():
table.add_row(*row.astype(str).tolist())
# console.print(table)
return table
# def cms.get_manifest (manifest):
# if not manifest.endswith('json') and os.path.isdir(manifest):
# manifest = manifest if not manifest.endswith(os.sep) else os.sep.join(manifest.split(os.sep)[:-1])
# path = os.sep.join([manifest,'qcms-manifest.json'])
# else:
# path = manifest
# return path
# def get_config(path,key=None):
# f = open(path)
# _config = json.loads(f.read())
# f.close()
# return _config[key] if key and key in _config else _config
def format(file,_content):
return [{'file':file.replace('.py',''),'uri':f'api/{file.replace(".py","")}/{_name}','endpoint':_name} for _name in _content]
def get (manifest:Annotated[str,typer.Argument(help="project folder or manifest file")],):
"""
List the plugins in the from a project folder (from the manifest)
"""
path = cms.engine.config.get_manifest(manifest=manifest) #
_config = cms.engine.config.get(path) #get_config(path)
_root = _config['layout']['root']
#
# remove the manifest file to pull the plugins folder
folder = os.sep.join([path.replace('qcms-manifest.json','')[:-1],f'{_root}/_plugins'])
loader = px.Loader ()
_api = []
for _name in os.listdir(folder):
_file = os.sep.join([folder,_name])
try:
loader.load(file=_file)
_api+= format(_name,loader.names())
# _ondisk[_name] = loader.names()
except Exception as e:
#
# If the file has an error, it will be skipped
print (e)
break
#
# at this point we know what we have on disk, we should be able to make a report/dashboard of sorts
pass
# On disk
# files = os.listdir(folder)
#
_online = []
_plugins = _config['plugins']
for _name in _plugins :
_online += format(_name, _plugins[_name])
return _api,_online
class StatusFilter(str,Enum):
online="online"
offline="offline"
@cli.command(name="status")
def status(manifest:Annotated[str,typer.Argument(help="project folder or manifest file")],
filter : StatusFilter = None
):
"""
This function will provide the status of all available plugins
"""
_avail,_depl = get(manifest)
_avail = pd.DataFrame(_avail)# available on disk (not deployed)
_depl = pd.DataFrame(_depl) # deployed
files = _avail.file.unique().tolist()+ _depl.file.unique().tolist()
_df = pd.DataFrame()
for _name in files :
_xe = _avail[_avail.file == _name].endpoint.tolist()
_ye = _depl[_depl.file == _name].endpoint.tolist()
_online = list(set(_xe) & set(_ye))
_offline = list(set(_xe) - set(_ye))
_data = pd.DataFrame()
_data['api'] = _offline + _online
_data['file'] = _name
_data['status'] = (['[red]offline[/red]']* len(_offline)) + (['[green]online[/green]']* len(_online))
# _data['deployed'] = _online
_data = _data[['file','api','status']]
_df = pd.concat([_df, _data])
# _df.append({'file':_name,'deployed':_online,'offline':_offline})
_df['uri'] = _df.apply(lambda row: f'api/{row.file}/{row.api}',axis=1)
_df = _df[['file','uri','api','status']]
if filter :
print (f"status in ('{filter.value}')")
_df = _df[_df.status.str.contains(filter.value, case=False, regex=True)]
# _df = _df.query(f" '{filter.value}' in status")
print (to_Table(_df))
pass
@cli.command(name="register")
def add (manifest:Annotated[str,typer.Argument(help="project folder or manifest file")],
pointer:Annotated[str,typer.Argument(help="file/function or file.function with no file extension. e.g: demo/info")]
):
"""
This function will add a plugin function to the site's configuration file making it available as an API
"""
#
# Let's make sure we are adding to the configuration something that actually exists
#
_file,_name = pointer.split('/')
path = cms.engine.config.get_manifest(manifest=manifest) #
_config = cms.engine.config.get(path) #get_config(path)
_root = _config['layout']['root']
_folder = os.sep.join([path.replace('qcms-manifest.json','')[:-1],f'{_root}/_plugins'])
if f'{_file}.py' in os.listdir(_folder) :
loader = px.Loader ()
loader.load(file=f'{_folder}{os.sep}{_file}.py')
if loader.has(_name) :
#
# adding to plugins
_plugins = _config['plugins']
if _file not in _plugins :
_plugins[_file] = []
if _name not in _plugins[_file] :
_plugins[_file].append (_name)
_config['plugins'] = _plugins
cms.engine.config.write(config=_config,path=path)
_msg = f"{PASSED} [bold]{pointer}[/bold] successfully added to {manifest}\nAPI endpoint [bold]api/{_file}/{_name}[/bold]"
else:
_msg = f"{FAILED} [bold]{pointer}[/bold] [red]already exists[/red] in configuration"
else:
#
# failure at this point, asking for a function in a file that doesn't exist
_msg = f"[bold]{pointer}[/bold] [red]{_name} missing[/red] in {_folder}{os.sep}{_file}.py"
pass
else:
#
# throw/raise an exception
_msg = f"{FAILED} [bold]{pointer}[/bold] [red]NOT found[/red] in {_folder}"
print (_msg)
pass
@cli.command(name="unregister")
def remove(manifest:Annotated[str,typer.Argument(help="project folder or manifest file")],
pointer:Annotated[str,typer.Argument(help="file/function or file.function with no file extension. e.g: demo/info")]
):
"""
This function will remove an api from the configuration of a project and won't be available via http/https
"""
_file,_name = pointer.split('/')
path = cms.engine.config.get_manifest(manifest=manifest) #
_config = cms.engine.config.get(path) #get_config(path)
_root = _config['layout']['root']
_plugins = _config.get('plugins',{})
if _file in _plugins :
_plugins[_file] = [_fname for _fname in _plugins[_file] if _fname != _name]
_config['plugins'] = _plugins
_msg = f"{PASSED} [bold]{pointer}[/bold] was [green]successfully[/green] removed from {path}"
else:
_msg = f"{FAILED} [bold]{pointer}[/bold] was [red]NOT found[/red] in {path}"
print (_msg)
cms.engine.config.write(_config,path)
#
#
# def post(config,path):
# f = open(path,'w')
# f.write(json.dumps(config,indent=4))
# f.close()

@ -0,0 +1,88 @@
"""
This file will handle security aspects associated with QCMS
"""
import typer
from typing_extensions import Annotated
from typing import Optional
from typing import Tuple
import os
import json
import plugin_ix as px
from enum import Enum
import pandas as pd
from rich.table import Table
from rich import print
import uuid
import cms
import requests
FAILED = '[ [red] \u2717 [/red] ]'
PASSED = '[ [green] \u2713 [/green] ]'
cli = typer.Typer()
@cli.command(name="set-key")
def set_key (manifest:Annotated[str,typer.Argument(help="path to manifest or manifest folder")],
keyfile:Annotated[str,typer.Argument(help="path of the key file to generate")]
):
"""
force-reload of an application
"""
keyfile = cms.engine.config.get_manifest(keyfile)
if not os.path.exists(keyfile):
f = open(keyfile,'w')
f.write(str(uuid.uuid4()))
f.close()
#
manifest = cms.engine.config.get_manifest(manifest)
_config = cms.engine.config.get(manifest)
if 'source' not in _config['system']:
_config['system']['source'] = {'id':'disk'}
_config['system']['source']['key'] = os.path.abspath(keyfile)
cms.engine.config.write(_config,manifest)
_msg = f"""{PASSED} [bold]{_config['layout']['header']['title']}[/bold] : A key was generated and written to {keyfile}
use this key in header to enable reload of the site ...
"""
else:
_msg = f"""{FAILED} [bold]{_config['system']['layout']['header']['title']}[/bold] : could [bold]NOT[/bold] generate a key, because it would seem you already have one
Please manually delete {keyfile}
"""
print (_msg)
@cli.command (name='reload')
def reload (
path:Annotated[str,typer.Argument(help="")],
port:int=typer.Option(default=None,help="port of the host to call")
) :
"""
Reload a site/portal given the manifest ...
"""
path = cms.engine.config.get_manifest(path)
_config = cms.engine.config.get( path)
if 'source' in _config['system'] and 'key' in _config['system']['source'] :
_spath = _config['system']['source']['key']
# f = open(_config['system']['source']['key'])
if not os.path.exists(_spath) :
mpath = path.split(os.sep)[:-1] + _spath.split(os.sep)
_spath = os.sep.join(mpath)
pass
f = open(_spath)
key = f.read()
f.close()
_port = port if port else _config['system']['app']['port']
url = f"http://localhost:{_port}/reload"
resp = requests.post(url, headers={"key":key})
if resp.status_code == 200 :
_msg = f"""{PASSED} [bold]{_config['layout']['header']['title']}[/bold] : successfully reloaded {url}"""
else:
_msg = f"""{FAILED} failed to reload, status code {resp.status_code}\n{url}
"""
else:
_msg = f"""{FAILED} no secure key found in manifest to request reload"""
print (_msg)

@ -5,6 +5,8 @@ import os
import json
def get (path) :
#
# Opens the manifest file and returns the configuration
if os.path.exists(path) :
f = open(path)
_conf = json.loads(f.read())
@ -12,6 +14,15 @@ def get (path) :
else:
_conf = {}
return _conf
def get_manifest(manifest):
#
# returns the manifest file (absolute path) for a site
if not manifest.endswith('json') and os.path.isdir(manifest):
manifest = manifest if not manifest.endswith(os.sep) else os.sep.join(manifest.split(os.sep)[:-1])
return os.sep.join([manifest,'qcms-manifest.json'])
else:
return manifest
def _isvalid(_allowed,**_args):
if not list(set(_allowed) - set(_args.keys())) :
@ -21,8 +32,8 @@ def _isvalid(_allowed,**_args):
return _pargs
return False
def write(_config, path):
def write(config, path):
f = open(path,'w')
f.write( json.dumps(_config,indent=2)) ;
f.write( json.dumps(config,indent=4)) ;
f.close()

@ -60,12 +60,11 @@ import cms
# register this in config.plugins: {"demo":["info"]}
@cms.plugins(mimetype='application/json') :
@cms.Plugin(mimetype='application/json',methods=['POST','GET'])
def info (**_args):
_request= _args['request']
_config = _args['config']
return {"version":_config['system']['version'],'title':_config['layout']['header']['title']}
pass
"""
loc = os.sep.join([_path,_root,'_plugins','demo.py'])
f = open(loc,'w')
@ -137,6 +136,9 @@ def _index (_path,root):
</div>
</div>
<p>
<div>
Add custom python functions and provide access as <b>api</b>
</div>
<div align="center">Learn more about <b>QCMS</b> and at {themes.URL}</div>
</p>
"""

@ -63,9 +63,10 @@ class Manager :
# we will assume that all authenticated users have access to every part of the site
#
if 'authorization' in _kwargs:
#
# loading permissions table from a designated location
# #
# # loading permissions table from a designated location
reader = transport.get.reader(**_kwargs['authorization'])
self._permissions = reader.read()
@ -77,7 +78,6 @@ class Manager :
if not path or not os.path.exists(path) :
raise Exception (f'Missing {what} {path}')
def authenticate(self,**_args):
print (" ********* ", self._authKey)
_kwargs = copy.copy(_args)
_kwargs['config'] = self._config
# _user = self.login(**_kwargs)
@ -147,7 +147,7 @@ class Manager :
return None
def method (self):
return self._config['method']
return self._config['method'] if self._config else None
# def _uri (self) :
# return self._config.get('uri',None)
def loginURI (self):

@ -110,7 +110,7 @@ class Initialization (IOConfig):
#
# Log initializaton ...
#
self.log(action='init.security',module='site.init',input= self.secure._permissions.to_dict(orient='records'))
self.log(action='init.security',module='site.init',input= {'method':self.secure.method(),'permissioins':self.secure._permissions.to_dict(orient='records')})
def reload (self):
_args = self._args
self._config = self.read_config(**_args)
@ -428,10 +428,10 @@ class Site(Initialization) :
def html (self,_request):
_uri = self.uri(_request)
_mimeType = self.mimeType(_uri)
f = open(self.path(_uri),'r')
_content = f.read() #_handler.html(_uri, self.get(None))
f.close()
# f = open(self.path(_uri),'r')
# _content = f.read() #_handler.html(_uri, self.get(None))
# f.close()
_content = self.open(uri=self.path(_uri),mode='r')
if 'md' in _mimeType or 'html' in _mimeType :
# _content = f'<div>{_content}</div>'
@ -468,7 +468,22 @@ class Site(Initialization) :
# _isfile = '.' in request.path
# return file if _isfile and not _isroute else self.get('layout.index')
def open(self,**_args) :
"""
:uri path of the file to open
:mode r,rb {text,binary}
"""
_mode = 'r' if 'mode' not in _args else _args['mode']
_uri = _args['uri']
if _uri.endswith('.py') and '_plugins' in _uri and self.get('layout.root') not in _uri:
#
# We can NOT serve python files over the web (possible security issue)
return None
f = open(_uri,_mode)
_content = f.read()
f.close()
return _content
def read(self,request) :
_kwargs = {'allow':0}
# if self.secure.allow(request=request):
@ -484,11 +499,12 @@ class Site(Initialization) :
#
# Opening a binary file
f = open(self.path(_uri),'rb')
_content = io.BytesIO(f.read())
# f = open(self.path(_uri),'rb')
# _content = io.BytesIO(f.read())
f.close()
# _content,_ = _handler.read(uri=_uri, config=self.get(None))
# f.close()
_content = self.open(uri=self.path(_uri),mode='rb')
_content = io.BytesIO( _content )
_kwargs = {'allow':1,'mimeType':_mimeType,'extension':_extension,
'path':self.path(_uri),
'uri':_uri,'request':request.path}

@ -45,43 +45,4 @@ qcms.login.cancel = function (){
})
$('.qcms-login-error').slideUp()
}
/**
* PAM authentication
*/
// qcms.authenticate = {}
// qcms.authenticate.nextcloud = function (){
// var _uri = ([qcms.context,'/login']).join('')
// _args = qcms.login.get()
// var http = HttpClient.instance()
// http.setHeader('Content-Type','application/json')
// // http.setHeader('method','pam')
// http.setData( JSON.stringify(_args))
// http.post(_uri,(x)=>{
// if(x.readyState == 4 && x.status == 200){
// }
// })
// }
// qcms.authenticate.pam = function (){
// var _uri = ([qcms.context,'/login']).join('')
// var _args = {
// username:$('.qcms-login-input .username').val(),
// password:$('.qcms-login-input .password').val()
// }
// var http = HttpClient.instance()
// http.setHeader('Content-Type','application/json')
// http.setHeader('method','pam')
// http.setData( JSON.stringify(_args))
// http.post(_uri,(x)=>{
// if(x.readyState == 4 && x.status == 200){
// window.open(x.responseURL,'_self')
// ;
// }
// })
// }
Loading…
Cancel
Save