[devtools] accept str objects in CubicWebTC.new_access and .create_user
# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr## This file is part of CubicWeb.## CubicWeb is free software: you can redistribute it and/or modify it under the# terms of the GNU Lesser General Public License as published by the Free# Software Foundation, either version 2.1 of the License, or (at your option)# any later version.## CubicWeb is distributed in the hope that it will be useful, but WITHOUT# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more# details.## You should have received a copy of the GNU Lesser General Public License along# with CubicWeb. If not, see <http://www.gnu.org/licenses/>."""web ui configuration for cubicweb instances"""__docformat__="restructuredtext en"_=unicodeimportosimporthmacfromuuidimportuuid4fromos.pathimportjoin,exists,split,isdirfromwarningsimportwarnfromlogilab.common.decoratorsimportcached,cachedpropertyfromlogilab.common.deprecationimportdeprecatedfromlogilab.common.configurationimportmerge_optionsfromcubicwebimportConfigurationErrorfromcubicweb.toolsutilsimportread_configfromcubicweb.cwconfigimportCubicWebConfiguration,register_persistent_optionsregister_persistent_options((# site-wide only web ui configuration('site-title',{'type':'string','default':'unset title','help':_('site title'),'sitewide':True,'group':'ui',}),('main-template',{'type':'string','default':'main-template','help':_('id of main template used to render pages'),'sitewide':True,'group':'ui',}),# user web ui configuration('fckeditor',{'type':'yn','default':True,'help':_('should html fields being edited using fckeditor (a HTML ''WYSIWYG editor). You should also select text/html as default ''text format to actually get fckeditor.'),'group':'ui',}),# navigation configuration('page-size',{'type':'int','default':40,'help':_('maximum number of objects displayed by page of results'),'group':'navigation',}),('related-limit',{'type':'int','default':8,'help':_('maximum number of related entities to display in the primary ''view'),'group':'navigation',}),('combobox-limit',{'type':'int','default':20,'help':_('maximum number of entities to display in related combo box'),'group':'navigation',}),))classWebConfiguration(CubicWebConfiguration):"""the WebConfiguration is a singleton object handling instance's configuration and preferences """cubicweb_appobject_path=CubicWebConfiguration.cubicweb_appobject_path|set([join('web','views')])cube_appobject_path=CubicWebConfiguration.cube_appobject_path|set(['views'])options=merge_options(CubicWebConfiguration.options+(('repository-uri',{'type':'string','default':'inmemory://','help':'see `cubicweb.dbapi.connect` documentation for possible value','group':'web','level':2,}),('anonymous-user',{'type':'string','default':None,'help':'login of the CubicWeb user account to use for anonymous user (if you want to allow anonymous)','group':'web','level':1,}),('anonymous-password',{'type':'string','default':None,'help':'password of the CubicWeb user account to use for anonymous user, ''if anonymous-user is set','group':'web','level':1,}),('query-log-file',{'type':'string','default':None,'help':'web instance query log file','group':'web','level':3,}),# web configuration('https-url',{'type':'string','default':None,'help':'web server root url on https. By specifying this option your '\'site can be available as an http and https site. Authenticated users '\'will in this case be authenticated and once done navigate through the '\'https site. IMPORTANTE NOTE: to do this work, you should have your '\'apache redirection include "https" as base url path so cubicweb can '\'differentiate between http vs https access. For instance: \n'\'RewriteRule ^/demo/(.*) http://127.0.0.1:8080/https/$1 [L,P]\n'\'where the cubicweb web server is listening on port 8080.','group':'main','level':3,}),('https-deny-anonymous',{'type':'yn','default':False,'help':'Prevent anonymous user to browse through https version of ''the site (https-url). Login form will then be displayed ''until logged','group':'web','level':2}),('auth-mode',{'type':'choice','choices':('cookie','http'),'default':'cookie','help':'authentication mode (cookie / http)','group':'web','level':3,}),('realm',{'type':'string','default':'cubicweb','help':'realm to use on HTTP authentication mode','group':'web','level':3,}),('http-session-time',{'type':'time','default':0,'help':"duration of the cookie used to store session identifier. ""If 0, the cookie will expire when the user exist its browser. ""Should be 0 or greater than repository\'s session-time.",'group':'web','level':2,}),('cleanup-anonymous-session-time',{'type':'time','default':'5min','help':'Same as cleanup-session-time but specific to anonymous ''sessions. You can have a much smaller timeout here since it will be ''transparent to the user. Default to 5min.','group':'web','level':3,}),('embed-allowed',{'type':'regexp','default':None,'help':'regular expression matching URLs that may be embeded. \leave it blank if you don\'t want the embedding feature, or set it to ".*" \if you want to allow everything','group':'web','level':3,}),('submit-mail',{'type':'string','default':None,'help':('Mail used as recipient to report bug in this instance, ''if you want this feature on'),'group':'web','level':2,}),('language-negociation',{'type':'yn','default':True,'help':'use Accept-Language http header to try to set user '\'interface\'s language according to browser defined preferences','group':'web','level':2,}),('print-traceback',{'type':'yn','default':CubicWebConfiguration.mode!='system','help':'print the traceback on the error page when an error occurred','group':'web','level':2,}),('captcha-font-file',{'type':'string','default':join(CubicWebConfiguration.shared_dir(),'data','porkys.ttf'),'help':'True type font to use for captcha image generation (you \must have the python imaging library installed to use captcha)','group':'web','level':3,}),('captcha-font-size',{'type':'int','default':25,'help':'Font size to use for captcha image generation (you must \have the python imaging library installed to use captcha)','group':'web','level':3,}),('concat-resources',{'type':'yn','default':False,'help':'use modconcat-like URLS to concat and serve JS / CSS files','group':'web','level':2,}),('anonymize-jsonp-queries',{'type':'yn','default':True,'help':'anonymize the connection before executing any jsonp query.','group':'web','level':1}),('generate-staticdir',{'type':'yn','default':True,'help':'Generate the static data resource directory on upgrade.','group':'web','level':2,}),('staticdir-path',{'type':'string','default':None,'help':'The static data resource directory path.','group':'web','level':2,}),('access-control-allow-origin',{'type':'csv','default':(),'help':('comma-separated list of allowed origin domains or "*" for any domain'),'group':'web','level':2,}),('access-control-allow-methods',{'type':'csv','default':(),'help':('comma-separated list of allowed HTTP methods'),'group':'web','level':2,}),('access-control-max-age',{'type':'int','default':None,'help':('maximum age of cross-origin resource sharing (in seconds)'),'group':'web','level':2,}),('access-control-expose-headers',{'type':'csv','default':(),'help':('comma-separated list of HTTP headers the application declare in response to a preflight request'),'group':'web','level':2,}),('access-control-allow-headers',{'type':'csv','default':(),'help':('comma-separated list of HTTP headers the application may set in the response'),'group':'web','level':2,}),))def__init__(self,*args,**kwargs):super(WebConfiguration,self).__init__(*args,**kwargs)self.uiprops=Noneself.https_uiprops=Noneself.datadir_url=Noneself.https_datadir_url=Nonedeffckeditor_installed(self):ifself.uipropsisNone:returnFalsereturnexists(self.uiprops.get('FCKEDITOR_PATH',''))defcwproperty_definitions(self):forkey,pdefinsuper(WebConfiguration,self).cwproperty_definitions():ifkey=='ui.fckeditor'andnotself.fckeditor_installed():continueyieldkey,pdef# don't use @cached: we want to be able to disable it while this must still# be cacheddefrepository(self,vreg=None):"""return the instance's repository object"""try:returnself.__repoexceptAttributeError:fromcubicweb.repoapiimportget_repositoryrepo=get_repository(config=self,vreg=vreg)self.__repo=reporeturnrepodefvc_config(self):returnself.repository().get_versions()defanonymous_user(self):"""return a login and password to use for anonymous users. None may be returned for both if anonymous connection is not allowed or if an empty login is used in configuration """try:user=self['anonymous-user']orNonepasswd=self['anonymous-password']ifuser:user=unicode(user)exceptKeyError:user,passwd=None,NoneexceptUnicodeDecodeError:raiseConfigurationError("anonymous information should only contains ascii")returnuser,passwd@cachedpropertydef_instance_salt(self):"""This random key/salt is used to sign content to be sent back by browsers, eg. in the error report form. """returnstr(uuid4())defsign_text(self,text):"""sign some text for later checking"""# hmac.new expect bytesifisinstance(text,unicode):text=text.encode('utf-8')# replace \r\n so we do not depend on whether a browser "reencode"# original message using \r\n or notreturnhmac.new(self._instance_salt,text.strip().replace('\r\n','\n')).hexdigest()defcheck_text_sign(self,text,signature):"""check the text signature is equal to the given signature"""returnself.sign_text(text)==signaturedeflocate_resource(self,rid):"""return the (directory, filename) where the given resource may be found """returnself._fs_locate(rid,'data')deflocate_doc_file(self,fname):"""return the directory where the given resource may be found"""returnself._fs_locate(fname,'wdoc')[0]@cacheddef_fs_path_locate(self,rid,rdirectory):"""return the directory where the given resource may be found"""path=[self.apphome]+self.cubes_path()+[join(self.shared_dir())]fordirectoryinpath:ifexists(join(directory,rdirectory,rid)):returndirectorydef_fs_locate(self,rid,rdirectory):"""return the (directory, filename) where the given resource may be found """directory=self._fs_path_locate(rid,rdirectory)ifdirectoryisNone:returnNone,Noneifrdirectory=='data'andrid.endswith('.css'):ifrid=='cubicweb.old.css':# @import('cubicweb.css') in csswarn('[3.20] cubicweb.old.css has been renamed back to cubicweb.css',DeprecationWarning)rid='cubicweb.css'returnself.uiprops.process_resource(join(directory,rdirectory),rid),ridreturnjoin(directory,rdirectory),riddeflocate_all_files(self,rid,rdirectory='wdoc'):"""return all files corresponding to the given resource"""path=[self.apphome]+self.cubes_path()+[join(self.shared_dir())]fordirectoryinpath:fpath=join(directory,rdirectory,rid)ifexists(fpath):yieldjoin(fpath)defload_configuration(self):"""load instance's configuration files"""super(WebConfiguration,self).load_configuration()# load external resources definitionself._init_base_url()self._build_ui_properties()def_init_base_url(self):# normalize base url(s)baseurl=self['base-url']orself.default_base_url()ifbaseurlandbaseurl[-1]!='/':baseurl+='/'ifnot(self.repairingorself.creating):self.global_set_option('base-url',baseurl)httpsurl=self['https-url']data_relpath=self.data_relpath()ifhttpsurl:ifhttpsurl[-1]!='/':httpsurl+='/'ifnotself.repairing:self.global_set_option('https-url',httpsurl)self.https_datadir_url=httpsurl+data_relpathself.datadir_url=baseurl+data_relpathdefdata_relpath(self):ifself.mode=='test':return'data/'return'data/%s/'%self.instance_md5_version()def_build_ui_properties(self):# self.datadir_url[:-1] to remove trailing /fromcubicweb.web.propertysheetimportPropertySheetcachedir=join(self.appdatahome,'uicache')self.check_writeable_uid_directory(cachedir)self.uiprops=PropertySheet(cachedir,data=lambdax:self.datadir_url+x,datadir_url=self.datadir_url[:-1])self._init_uiprops(self.uiprops)ifself['https-url']:cachedir=join(self.appdatahome,'uicachehttps')self.check_writeable_uid_directory(cachedir)self.https_uiprops=PropertySheet(cachedir,data=lambdax:self.https_datadir_url+x,datadir_url=self.https_datadir_url[:-1])self._init_uiprops(self.https_uiprops)def_init_uiprops(self,uiprops):libuiprops=join(self.shared_dir(),'data','uiprops.py')uiprops.load(libuiprops)forpathinreversed([self.apphome]+self.cubes_path()):self._load_ui_properties_file(uiprops,path)self._load_ui_properties_file(uiprops,self.apphome)datadir_url=uiprops.context['datadir_url']if(datadir_url+'/cubicweb.old.css')inuiprops['STYLESHEETS']:warn('[3.20] cubicweb.old.css has been renamed back to cubicweb.css',DeprecationWarning)idx=uiprops['STYLESHEETS'].index(datadir_url+'/cubicweb.old.css')uiprops['STYLESHEETS'][idx]=datadir_url+'/cubicweb.css'ifdatadir_url+'/cubicweb.reset.css'inuiprops['STYLESHEETS']:warn('[3.20] cubicweb.reset.css is obsolete',DeprecationWarning)uiprops['STYLESHEETS'].remove(datadir_url+'/cubicweb.reset.css')cubicweb_js_url=datadir_url+'/cubicweb.js'ifcubicweb_js_urlnotinuiprops['JAVASCRIPTS']:uiprops['JAVASCRIPTS'].insert(0,cubicweb_js_url)def_load_ui_properties_file(self,uiprops,path):uipropsfile=join(path,'uiprops.py')ifexists(uipropsfile):self.debug('loading %s',uipropsfile)uiprops.load(uipropsfile)# static files handling ###################################################@propertydefstatic_directory(self):returnjoin(self.appdatahome,'static')defstatic_file_exists(self,rpath):returnexists(join(self.static_directory,rpath))defstatic_file_open(self,rpath,mode='wb'):staticdir=self.static_directoryrdir,filename=split(rpath)ifrdir:staticdir=join(staticdir,rdir)ifnotisdir(staticdir)and'w'inmode:os.makedirs(staticdir)returnfile(join(staticdir,filename),mode)defstatic_file_add(self,rpath,data):stream=self.static_file_open(rpath)stream.write(data)stream.close()defstatic_file_del(self,rpath):ifself.static_file_exists(rpath):os.remove(join(self.static_directory,rpath))@deprecated('[3.9] use _cw.uiprops.get(rid)')defhas_resource(self,rid):"""return true if an external resource is defined"""returnbool(self.uiprops.get(rid))