#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
"""server.serverconfig definition:organization: Logilab:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses"""__docformat__="restructuredtext en"fromos.pathimportjoin,existsfromlogilab.common.configurationimportREQUIRED,Method,Configuration, \ini_format_sectionfromlogilab.common.decoratorsimportwproperty,cached,clear_cachefromcubicweb.toolsutilsimportread_config,restrict_perms_to_userfromcubicweb.cwconfigimportCubicWebConfiguration,merge_optionsfromcubicweb.serverimportSOURCE_TYPESUSER_OPTIONS=(('login',{'type':'string','default':'admin','help':"cubicweb manager account's login "'(this user will be created)','inputlevel':0,}),('password',{'type':'password','default':REQUIRED,'help':"cubicweb manager account's password",'inputlevel':0,}),)classSourceConfiguration(Configuration):def__init__(self,appid,options):self.appid=appid# has to be done before super callsuper(SourceConfiguration,self).__init__(options=options)# make Method('default_instance_id') usable in db option defs (in native.py)defdefault_instance_id(self):returnself.appiddefgenerate_sources_file(appid,sourcesfile,sourcescfg,keys=None):"""serialize repository'sources configuration into a INI like file the `keys` parameter may be used to sort sections """ifkeysisNone:keys=sourcescfg.keys()else:forkeyinsourcescfg:ifnotkeyinkeys:keys.append(key)stream=open(sourcesfile,'w')foruriinkeys:sconfig=sourcescfg[uri]ifisinstance(sconfig,dict):# get a Configuration objectifuri=='admin':options=USER_OPTIONSelse:options=SOURCE_TYPES[sconfig['adapter']].options_sconfig=SourceConfiguration(appid,options=options)forattr,valinsconfig.items():ifattr=='uri':continueifattr=='adapter':_sconfig.adapter=valelse:_sconfig.set_option(attr,val)sconfig=_sconfigoptsbysect=list(sconfig.options_by_section())assertlen(optsbysect)==1,'all options for a source should be in the same group'ini_format_section(stream,uri,optsbysect[0][1])ifhasattr(sconfig,'adapter'):print>>streamprint>>stream,'# adapter for this source (YOU SHOULD NOT CHANGE THIS)'print>>stream,'adapter=%s'%sconfig.adapterprint>>streamclassServerConfiguration(CubicWebConfiguration):"""standalone RQL server"""name='repository'cubicweb_appobject_path=CubicWebConfiguration.cubicweb_appobject_path|set(['sobjects','hooks'])cube_appobject_path=CubicWebConfiguration.cube_appobject_path|set(['sobjects','hooks'])options=merge_options((# ctl configuration('host',{'type':'string','default':None,'help':'host name if not correctly detectable through gethostname','group':'main','inputlevel':1,}),('pid-file',{'type':'string','default':Method('default_pid_file'),'help':'repository\'s pid file','group':'main','inputlevel':2,}),('uid',{'type':'string','default':None,'help':'if this option is set, use the specified user to start \the repository rather than the user running the command','group':'main','inputlevel':(CubicWebConfiguration.mode=='installed')and0or1,}),('session-time',{'type':'int','default':30*60,'help':'session expiration time, default to 30 minutes','group':'main','inputlevel':1,}),('connections-pool-size',{'type':'int','default':4,'help':'size of the connections pools. Each source supporting multiple \connections will have this number of opened connections.','group':'main','inputlevel':1,}),('rql-cache-size',{'type':'int','default':300,'help':'size of the parsed rql cache size.','group':'main','inputlevel':1,}),('undo-support',{'type':'string','default':'','help':'string defining actions that will have undo support: \[C]reate [U]pdate [D]elete entities / [A]dd [R]emove relation. Leave it empty \for no undo support, set it to CUDAR for full undo support, or to DR for \support undoing of deletion only.','group':'main','inputlevel':1,}),('keep-transaction-lifetime',{'type':'int','default':7,'help':'number of days during which transaction records should be \kept (hence undoable).','group':'main','inputlevel':1,}),('multi-sources-etypes',{'type':'csv','default':(),'help':'defines which entity types from this repository are used \by some other instances. You should set this properly so those instances to \detect updates / deletions.','group':'main','inputlevel':1,}),('delay-full-text-indexation',{'type':'yn','default':False,'help':'When full text indexation of entity has a too important cost'' to be done when entity are added/modified by users, activate this ''option and setup a job using cubicweb-ctl db-rebuild-fti on your ''system (using cron for instance).','group':'main','inputlevel':1,}),# email configuration('default-recipients-mode',{'type':'choice','choices':('default-dest-addrs','users','none'),'default':'default-dest-addrs','help':'when a notification should be sent with no specific rules \to find recipients, recipients will be found according to this mode. Available \modes are "default-dest-addrs" (emails specified in the configuration \variable with the same name), "users" (every users which has activated \account with an email set), "none" (no notification).','group':'email','inputlevel':1,}),('default-dest-addrs',{'type':'csv','default':(),'help':'comma separated list of email addresses that will be used \as default recipient when an email is sent and the notification has no \specific recipient rules.','group':'email','inputlevel':1,}),('supervising-addrs',{'type':'csv','default':(),'help':'comma separated list of email addresses that will be \notified of every changes.','group':'email','inputlevel':2,}),# pyro server.serverconfig('pyro-host',{'type':'string','default':None,'help':'Pyro server host, if not detectable correctly through \gethostname(). It may contains port information using <host>:<port> notation, \and if not set, it will be choosen randomly','group':'pyro','inputlevel':2,}),)+CubicWebConfiguration.options)# should we open connections pools (eg connect to sources). This is usually# necessary...open_connections_pools=True# read the schema from the databaseread_instance_schema=True# set to true while creating an instancecreating=False# set this to true to get a minimal repository, for instance to get cubes# information on commands such as i18ninstance, db-restore, etc...quick_start=False# check user's state at login timeconsider_user_state=True# should some hooks be deactivated during [pre|post]create script executionfree_wheel=False# list of enables sources when sources restriction is necessary# (eg repository initialization at least)_enabled_sources=None@wpropertydefenabled_sources(self,sourceuris=None):self._enabled_sources=sourceurisclear_cache(self,'sources')defbootstrap_cubes(self):fromlogilab.common.textutilsimportsplitstripforlineinfile(join(self.apphome,'bootstrap_cubes')):line=line.strip()ifnotlineorline.startswith('#'):continueself.init_cubes(self.expand_cubes(splitstrip(line)))breakelse:# no cubesself.init_cubes(())defwrite_bootstrap_cubes_file(self,cubes):stream=file(join(self.apphome,'bootstrap_cubes'),'w')stream.write('# this is a generated file only used for bootstraping\n')stream.write('# you should not have to edit this\n')stream.write('%s\n'%','.join(cubes))stream.close()defsources_file(self):returnjoin(self.apphome,'sources')# this method has to be cached since when the server is running using a# restricted user, this user usually don't have access to the sources# configuration file (#16102)@cacheddefread_sources_file(self):returnread_config(self.sources_file())defsources(self):"""return a dictionnaries containing sources definitions indexed by sources'uri """allsources=self.read_sources_file()ifself._enabled_sourcesisNone:returnallsourcesreturndict((uri,config)foruri,configinallsources.items()ifuriinself._enabled_sourcesoruri=='admin')defwrite_sources_file(self,sourcescfg):sourcesfile=self.sources_file()ifexists(sourcesfile):importshutilshutil.copy(sourcesfile,sourcesfile+'.bak')generate_sources_file(self.appid,sourcesfile,sourcescfg,['admin','system'])restrict_perms_to_user(sourcesfile)defpyro_enabled(self):"""pyro is always enabled in standalone repository configuration"""returnTruedefload_schema(self,expand_cubes=False,**kwargs):fromcubicweb.schemaimportCubicWebSchemaLoaderifexpand_cubes:# in case some new dependencies have been introduced, we have to# reinitialize cubes so the full filesystem schema is readorigcubes=self.cubes()self._cubes=Noneself.init_cubes(self.expand_cubes(origcubes))schema=CubicWebSchemaLoader().load(self,**kwargs)ifexpand_cubes:# restaure original valueself._cubes=origcubesreturnschemadefload_bootstrap_schema(self):fromcubicweb.schemaimportBootstrapSchemaLoaderschema=BootstrapSchemaLoader().load(self)schema.name='bootstrap'returnschemadefset_sources_mode(self,sources):if'migration'insources:fromcubicweb.server.sourcesimportsource_adapterassertlen(sources)==1enabled_sources=[]foruri,configinself.sources().iteritems():ifuri=='admin':continueifsource_adapter(config).connect_for_migration:enabled_sources.append(uri)else:print'not connecting to source',uri,'during migration'elif'all'insources:assertlen(sources)==1enabled_sources=Noneelse:known_sources=self.sources()foruriinsources:asserturiinknown_sources,urienabled_sources=sourcesself._enabled_sources=enabled_sourcesclear_cache(self,'sources')defmigration_handler(self,schema=None,interactive=True,cnx=None,repo=None,connect=True,verbosity=None):"""return a migration handler instance"""fromcubicweb.server.migractionsimportServerMigrationHelperifverbosityisNone:verbosity=getattr(self,'verbosity',0)returnServerMigrationHelper(self,schema,interactive=interactive,cnx=cnx,repo=repo,connect=connect,verbosity=verbosity)