diff --git a/intranet/plugins/domfilter.py b/intranet/ClassesIntranet/AJAXManager.py similarity index 100% rename from intranet/plugins/domfilter.py rename to intranet/ClassesIntranet/AJAXManager.py diff --git a/intranet/plugins/verifdroitsfilter.py b/intranet/ClassesIntranet/AuthorisationsManager.py similarity index 76% rename from intranet/plugins/verifdroitsfilter.py rename to intranet/ClassesIntranet/AuthorisationsManager.py index b52f2023..26d12162 100644 --- a/intranet/plugins/verifdroitsfilter.py +++ b/intranet/ClassesIntranet/AuthorisationsManager.py @@ -1,5 +1,6 @@ from cherrypy.filters.basefilter import BaseFilter import cherrypy._cputil +import cherrypy ########################## # verification des droits @@ -8,7 +9,7 @@ import cherrypy._cputil def verifDroits(mesDroits, lesDroitsQuilFaut): if not type(mesDroits) == list: raise ValueError, "mesDroits doit etre une liste" - if (lesDroitsQuilFaut == "all"): + if (lesDroitsQuilFaut == "all") or (lesDroitsQuilFaut == []): return True if ("Nounou" in mesDroits): return True @@ -18,7 +19,7 @@ def verifDroits(mesDroits, lesDroitsQuilFaut): return True in [d in mesDroits for d in lesDroitsQuilFaut] return False -class VerifDroitsFilter(BaseFilter): +class AuthorisationsFilter(BaseFilter): def before_main(self): if not cherrypy.config.get('sessionAuthenticateFilter.on', False): @@ -29,3 +30,13 @@ class VerifDroitsFilter(BaseFilter): if not verifDroits(cherrypy.session['droits'], droits): raise cherrypy.HTTPError(403, "Vous n'avez pas les droits nécessaires pour accéder à cette page.") +########################## +# mise en place des droits +########################## +# +def setDroits(chemin, lesDroitsQuilFaut): + settings= { + chemin: + { 'crans.droits': lesDroitsQuilFaut} + } + cherrypy.config.update(settings) diff --git a/intranet/ClassesIntranet/Intranet.py b/intranet/ClassesIntranet/Intranet.py new file mode 100755 index 00000000..9c2e4bf0 --- /dev/null +++ b/intranet/ClassesIntranet/Intranet.py @@ -0,0 +1,224 @@ +#!/usr/bin/env python +# -*- coding: iso-8859-15 -*- +# ############################################################# +# .. +# .... ............ ........ +# . ....... . .... .. +# . ... .. .. .. .. ..... . .. +# .. .. ....@@@. .. . ........ . +# .. . .. ..@.@@..@@. .@@@@@@@ @@@@@@. .... +# .@@@@. .@@@@. .@@@@..@@.@@..@@@..@@@..@@@@.... .... +# @@@@... .@@@.. @@ @@ .@..@@..@@...@@@. .@@@@@. .. +# .@@@.. . @@@. @@.@@..@@.@@..@@@ @@ .@@@@@@.. ..... +# ...@@@.... @@@ .@@.......... ........ ..... .. +# . ..@@@@.. . .@@@@. .. ....... . ............. +# . .. .... .. .. . ... .... +# . . .... ............. .. ... +# .. .. ... ........ ... ... +# ................................ +# +# ############################################################# +# Intranet.py +# +# Classe Intranet, clase de base de l'intranet +# +# Copyright (c) 2006 by www.crans.org +# ############################################################# +import crans.cp as _crans_cp +import cherrypy, os +import crans.utils.exceptions +from ClassesIntranet.AuthorisationsManager import setDroits + +class Intranet: +# ######################################################## # +# GESTION DES MODULES # +# ######################################################## # +# +# + _loaded_modules = {} + + def _make_static_path_for_module(self, module_name ): + return "/" + module_name + "/static" + + def loadModule(self, un_module): + MODULES_DIR = cherrypy.config.get("crans.modules.dir") + if not un_module.startswith("."): + # faire ici l'importation + # importer le fichier main.py + try: + module_path = MODULES_DIR + "/" + un_module + "/main" + mon_module = __import__(module_path) + module_root = mon_module.main() + # on ajoute la classe a l'arborescence de cherrypy : + setattr( self, un_module, module_root) + # on ajoute le module aux modules connus : + try: + cat = module_root.category() + if not self._loaded_modules.has_key(cat): + self._loaded_modules[cat] = {} + self._loaded_modules[cat][un_module] = module_root + except: + if cherrypy.config.get("server.environment") == "development": + _crans_cp.log("Impossible d'obtenir les parametres du module %s" % un_module) + _crans_cp.log(crans.utils.exceptions.formatExc()) + # on ajoute les droits du module : + try: + droits_module = module_root.droits() + setDroits("/%s" % un_module, droits_module) + except: + if cherrypy.config.get("server.environment") == "development": + _crans_cp.log("Impossible d'obtenir les parametres du module %s" % un_module) + _crans_cp.log(crans.utils.exceptions.formatExc()) + except: + _crans_cp.log("Impossible de charger le module %s" % un_module) + if cherrypy.config.get("server.environment") == "development": + _crans_cp.log(crans.utils.exceptions.formatExc()) + # ajouter le dossier static ou il faut + staticPath = cherrypy.config.get("rootDir") + "/" + MODULES_DIR + "/" + un_module + "/static" + if os.path.isdir(staticPath): + settings= { self._make_static_path_for_module(un_module): + { 'sessionAuthenticateFilter.on': False, + 'sessionFilter.on': False, + 'server.output_filters.templatesEngine.on' : False, + 'staticFilter.on': True, + 'staticFilter.dir': staticPath, + } + } + cherrypy.config.update(settings) + if cherrypy.config.get("server.environment") == "development": + _crans_cp.log("New static : %s" % staticPath) + # fin de l'ajout du dossier static + + + def __init__(self): + ## + #### import automatique des modules + ## + MODULES_DIR = cherrypy.config.get("crans.modules.dir", False) + if MODULES_DIR: + if os.path.isdir(MODULES_DIR): + Liste_Modules = os.listdir(MODULES_DIR) + for un_module in Liste_Modules: + self.loadModule(un_module) + else: + _crans_cp.log("Dossier des modules invalide", 'LOADING', 2) + else: + _crans_cp.log("Pas de dossier de modules", 'LOADING', 2) + + +# ######################################################## # +# QUELQUES PAGES # +# ######################################################## # +# +# + def index(self): + items = {} + for a_category in self._loaded_modules: + items[a_category] = {} + for a_module_name in self._loaded_modules[a_category]: + module_object = self._loaded_modules[a_category][a_module_name] + if module_object.accessible(): + items[a_category][a_module_name] = {} + items[a_category][a_module_name]["name"] = module_object.title() + items[a_category][a_module_name]["icon"] = self._make_static_path_for_module(a_module_name) + "/" + module_object.icon() + items[a_category][a_module_name]["url"] = "/" + a_module_name + "/" + # si la categorie est vide, on la vire + if items[a_category] == {}: + del items[a_category] + + return { + 'template':'accueil', + 'values':{"modules":items}, + 'stylesheets':['css/accueil.css'], + } + index.exposed= True + + def info(self): + return { + 'template':'info-diverses', + 'values':{}, + 'stylesheets':['accueil.css'], + } + info.exposed = True + + def send_error_repport(self, **kw): + + # on récupère tout de suite le traceback + tb = crans.utils.exceptions.formatExc() + # entêtes du mail + exp = "intranet" + dest = cherrypy.config.get("mail.bugreport", "nounous@crans.org") + subject = "Rapport de Bug" + text = """ +Bonsoir, + +Ceci est un rapport de bug envoye par l'intranet. + +%s + """ % "\n".join( [ "%s: %s" % (str(a), str(kw[a])) for a in kw] ) + + #On ajoute des variables de cherrypy + text += "\n= Cherrypy vars =\n" + try: + text += "url: %s\n" % cherrypy.request.browser_url + except: + pass + try: + text += "headers: \n %s\n" % "\n".join( [" %s: %s" % (str(a), str(cherrypy.request.headers[a])) for a in cherrypy.request.headers] ) + except: + pass + try: + text += "query_string: %s\n" % cherrypy.request.query_string + except: + pass + try: + text += "path: %s\n" % cherrypy.request.path + except: + pass + + + # on ajoute le traceback + text += "\n= Traceback =\n" + text += tb + + #on signe, quand même ! + text += "\n-- \nRoot.py pour l'intranet\n" + + quickSend(exp, dest, subject, text) + return self.index() + + send_error_repport.exposed = True + + def testErreur(self): + raise Exception, "sdlfkjqmsdklj" + + testErreur.exposed = True + + def test(self): + return cherrypy.request.remote_addr + test.exposed = True + + def _cp_on_http_error(self, status, message): + if (cherrypy.config.configMap["global"]["server.environment"] == "development"): + cherrypy._cputil._cp_on_http_error(status, message) + return + if status==403: + cherrypy.response.body = { + 'template':'error403', + 'values':{'status':status, 'message':message }, + 'standalone':False, + } + elif status==404: + cherrypy.response.body = { + 'template':'error', + 'values':{'status':status, 'message':message }, + 'standalone':False, + } + elif status==500: + self.send_error_repport(status = status, message = message ) + # les filtres ne sont pas appliqués, on le fait àla main... + from plugins.templatesfilter import TemplatesFilter + TemplatesFilter().goWithThisDict({'template':'error', 'values':{'status':status, 'message':message }}) + else: + self.send_error_repport(status = status, message = message) + cherrypy._cputil._cp_on_http_error(status, message) diff --git a/intranet/ClassesIntranet/ModuleBase.py b/intranet/ClassesIntranet/ModuleBase.py new file mode 100644 index 00000000..24e1278f --- /dev/null +++ b/intranet/ClassesIntranet/ModuleBase.py @@ -0,0 +1,18 @@ +import cherrypy +from AuthorisationsManager import verifDroits + +class ModuleBase: + def category(self): + return "Personnel" + def title(self): + return "Titre" + def icon(self): + return "icon.png" + + _droits = [] + def droits(self): + return self._droits + + def accessible(self): + return verifDroits(cherrypy.session['droits'], self.droits()) + diff --git a/intranet/plugins/templatesfilter.py b/intranet/ClassesIntranet/TemplatesManager.py similarity index 66% rename from intranet/plugins/templatesfilter.py rename to intranet/ClassesIntranet/TemplatesManager.py index 0470dcc4..4d7934c0 100644 --- a/intranet/plugins/templatesfilter.py +++ b/intranet/ClassesIntranet/TemplatesManager.py @@ -1,17 +1,25 @@ from cherrypy.filters.basefilter import BaseFilter import cherrypy, os from Cheetah.Template import Template +import crans.cp as _crans_cp +from ClassesIntranet import current_module # ######################################################## # # Configuration de Cheetah # # ######################################################## # def serverSidePath(self, path): - if (cherrypy.config.configMap["global"]["server.environment"] == "development"): - if os.path.isfile(cherrypy.config.configMap["global"]["rootDir"]+'/templates/'+path+".dev"): - return cherrypy.config.configMap["global"]["rootDir"]+'/templates/'+path+".dev" - # les template se trouve dans le dossier template - return cherrypy.config.configMap["global"]["rootDir"]+'/templates/'+path + root_dir = cherrypy.config.configMap["global"]["rootDir"] + if os.path.isfile(path): + return path + try: + module_name = current_module() + hyp_path = root_dir + '/modules/' + module_name + '/templates/' + path + if os.path.isfile(hyp_path): + return hyp_path + except: + pass + return root_dir + '/templates/' + path # on surcharge cette fonction dans la classe Template Template.serverSidePath = serverSidePath @@ -25,6 +33,19 @@ Template.serverSidePath = serverSidePath # avec plein de test chians # class TemplatesFilter(BaseFilter): + def _getCorrectStaticMethod(self): + try: + module_name = current_module() + if module_name != None: + def static(truc): + return "/" + module_name + "/static/" + truc + return static + except: + pass + def static(truc): + return "/static/" + truc + return static + def _getBodyTemplate(self, body): if isinstance(body, dict): @@ -55,10 +76,13 @@ class TemplatesFilter(BaseFilter): return {} def _useMainTemplate(self, body): + values = {'environment':cherrypy.config.configMap["global"]["server.environment"], + 'static':self._getCorrectStaticMethod(), + } try: - t = Template(file='main.tmpl', searchList=[body,{'login':cherrypy.session['uid'], 'environment':cherrypy.config.configMap["global"]["server.environment"]}]) + t = Template(file='main.tmpl', searchList= [body,{'login':cherrypy.session['uid']}, values]) except: - t = Template(file='main.tmpl', searchList=[body,{'login':'', 'environment':cherrypy.config.configMap["global"]["server.environment"]}]) + t = Template(file='main.tmpl', searchList=[body,{'login':''},values]) return str(t) @@ -67,7 +91,8 @@ class TemplatesFilter(BaseFilter): bodyTemplate = self._getBodyTemplate(body) if bodyTemplate: templatevalues = self._getBodyNameSpace(body) - t = Template(file=bodyTemplate, searchList=[templatevalues]) + defaultvalues = {'static':self._getCorrectStaticMethod()} + t = Template(file=bodyTemplate, searchList=[templatevalues, defaultvalues]) body['page'] = str(t) if not self._isStandaloneBody(body): diff --git a/intranet/ClassesIntranet/__init__.py b/intranet/ClassesIntranet/__init__.py new file mode 100644 index 00000000..a75f95cd --- /dev/null +++ b/intranet/ClassesIntranet/__init__.py @@ -0,0 +1,8 @@ +import cherrypy + +def current_module(): + current_path = cherrypy.request.object_path + module_name = current_path.split('/')[1] + if module_name != 'index': + return module_name + return None diff --git a/intranet/Root.py b/intranet/Root.py index 4b7ed28f..189f6399 100755 --- a/intranet/Root.py +++ b/intranet/Root.py @@ -24,13 +24,9 @@ # # Copyright (c) 2006 by www.crans.org # ############################################################# - - import cherrypy, sys, os, datetime import crans.utils.exceptions sys.path.append('/usr/scripts/gestion/') - - # ######################################################## # # COMMAND LINE OPTION # # ######################################################## # @@ -61,7 +57,7 @@ parser.add_option("-p", "--port", if (options.dev): cherrypy.config.update(file=os.getcwd() + "/conf/intranet.cfg") cherrypy.config.update(file=os.getcwd() + "/conf/dev.cfg") - settings={'global': { 'rootDir': os.getcwd() } } + settings= { 'global': { 'rootDir': os.getcwd() } } cherrypy.config.update(settings) else: @@ -75,142 +71,28 @@ if (options.port): # import du CransLdap qu'il va bien (on utilise CransLdap et non crans_ldap car on veut -# forcer l'ouverture d'une nouvelle connexion à chaque login) +# forcer l'ouverture d'une nouvelle connexion à chaque login) if (cherrypy.config.configMap["global"]["server.environment"] == "development"): from ldap_crans_test import CransLdap - cherrypy.log("settings : unsing test ldap : env=" + cherrypy.config.configMap["global"]["server.environment"], "LDAP") else: from ldap_crans import CransLdap - cherrypy.log("settings : unsing prod ldap : env=" + cherrypy.config.configMap["global"]["server.environment"], "LDAP") +sys.path.append(cherrypy.config.get('rootDir')) # ######################################################## # # FILTRES MAISON # # ######################################################## # -from plugins.domfilter import DOMFilter -from plugins.templatesfilter import TemplatesFilter -from plugins.verifdroitsfilter import VerifDroitsFilter +from ClassesIntranet.AJAXManager import DOMFilter +from ClassesIntranet.TemplatesManager import TemplatesFilter +from ClassesIntranet.AuthorisationsManager import AuthorisationsFilter from crans.mail import quickSend +import crans.cp as _crans_cp # ######################################################## # # SERVER # # ######################################################## # -class Intranet: - def __init__(self): - from pages import monCompte, impression, factures, digicode, mesmachines - from pages import gestionFactures - - # liste des modules disponibles - self.monCompte = monCompte.monCompte() - self.sous = factures.root() - self.impression = impression.root() - self.digicode = digicode.root() - self.mesMachines = mesmachines.root() - self.gestionFactures = gestionFactures.root() - - # liste des modules en developpement - #if (cherrypy.config.configMap["global"]["server.environment"] == "development"): - - - _cpFilterList = [TemplatesFilter(), DOMFilter(), VerifDroitsFilter()] - - def index(self): - return { - 'template':'accueil', - 'values':{}, - 'stylesheets':['accueil.css'], - } - index.exposed= True - - def info(self): - return { - 'template':'info-diverses', - 'values':{}, - 'stylesheets':['accueil.css'], - } - info.exposed = True - - def send_error_repport(self, **kw): - - # on récupère tout de suite le traceback - tb = crans.utils.exceptions.formatExc() - # entêtes du mail - exp = "intranet" - dest = cherrypy.config.get("mail.bugreport", "nounous@crans.org") - subject = "Rapport de Bug" - text = """ -Bonsoir, - -Ceci est un rapport de bug envoye par l'intranet. - -%s - """ % "\n".join( [ "%s: %s" % (str(a), str(kw[a])) for a in kw] ) - - #On ajoute des variables de cherrypy - text += "\n= Cherrypy vars =\n" - try: - text += "url: %s\n" % cherrypy.request.browser_url - except: - pass - try: - text += "headers: \n %s\n" % "\n".join( [" %s: %s" % (str(a), str(cherrypy.request.headers[a])) for a in cherrypy.request.headers] ) - except: - pass - try: - text += "query_string: %s\n" % cherrypy.request.query_string - except: - pass - try: - text += "path: %s\n" % cherrypy.request.path - except: - pass - - - # on ajoute le traceback - text += "\n= Traceback =\n" - text += tb - - #on signe, quand même ! - text += "\n-- \nRoot.py pour l'intranet\n" - - quickSend(exp, dest, subject, text) - return self.index() - - send_error_repport.exposed = True - - def testErreur(self): - raise Exception, "sdlfkjqmsdklj" - - testErreur.exposed = True - - def test(self): - return cherrypy.request.remote_addr - test.exposed = True - - def _cp_on_http_error(self, status, message): - if (cherrypy.config.configMap["global"]["server.environment"] == "development"): - cherrypy._cputil._cp_on_http_error(status, message) - return - if status==403: - cherrypy.response.body = { - 'template':'error403', - 'values':{'status':status, 'message':message }, - 'standalone':False, - } - elif status==404: - cherrypy.response.body = { - 'template':'error', - 'values':{'status':status, 'message':message }, - 'standalone':False, - } - elif status==500: - self.send_error_repport(status = status, message = message ) - # les filtres ne sont pas appliqués, on le fait àla main... - from plugins.templatesfilter import TemplatesFilter - TemplatesFilter().goWithThisDict({'template':'error', 'values':{'status':status, 'message':message }}) - else: - self.send_error_repport(status = status, message = message) - cherrypy._cputil._cp_on_http_error(status, message) - +from ClassesIntranet.Intranet import Intranet +# GESTION DES FILTRES +Intranet._cpFilterList = [TemplatesFilter(), DOMFilter(), AuthorisationsFilter()] # ######################################################## # # LOGIN MAISON # @@ -266,5 +148,5 @@ cherrypy.config.update(settings) # ######################################################## # # LANCEMENT DE CHERRYPY # # ######################################################## # -cherrypy.root = Intranet() +cherrypy.tree.mount(Intranet(),'/') cherrypy.server.start() diff --git a/intranet/conf/dev.cfg b/intranet/conf/dev.cfg index 00c15772..ce624b46 100644 --- a/intranet/conf/dev.cfg +++ b/intranet/conf/dev.cfg @@ -20,9 +20,12 @@ logDebugInfoFilter.on = False paypal.businessAdress = "gdetrez-buisness@crans.org" paypal.useSandbox = True +crans.modules.dir = "modules" + # [/test] crans.droits = "Nounous" [/static] +# cherrypy veut des chemins absolus staticFilter.dir = "/home/gdetrez/crans.usr.scripts/intranet/static/" diff --git a/intranet/conf/intranet.cfg b/intranet/conf/intranet.cfg index ee344282..cb6b6df3 100644 --- a/intranet/conf/intranet.cfg +++ b/intranet/conf/intranet.cfg @@ -5,10 +5,7 @@ mail.bugreport = "intranet-bugreport@lists.crans.org" sessionAuthenticateFilter.on=True sessionFilter.on = True sessionFilter.locking = "implicit" - -# ceci est un exemple de definission de droits -#[/nounous] -#crans.droits="Nounou" +crans.modules.dir = "/usr/scripts/intranet/modules/" [/] # Now we can work on our filter as with the standard filters @@ -21,7 +18,7 @@ crans.droits="Imprimeur" [/impression] crans.activate = True -crans.activate.errorMsg = u"Plus d'encre ! Le fournisseur s'est trompé dans la commande." +crans.activate.errorMsg = u"Plus d'encre ! Le fournisseur s'est trompé dans la commande." [/static] sessionAuthenticateFilter.on=False @@ -30,9 +27,9 @@ server.output_filters.templatesEngine.on = False staticFilter.on = True staticFilter.dir = "/usr/scripts/intranet/static/" -[/favicon.ico] -sessionAuthenticateFilter.on=False -sessionFilter.on = False -server.output_filters.templatesEngine.on = False -staticFilter.on = True -staticFilter.file = "/usr/scripts/intranet/static/favicon.ico" +#[/favicon.ico] +#sessionAuthenticateFilter.on=False +#sessionFilter.on = False +#server.output_filters.templatesEngine.on = False +#staticFilter.on = True +#staticFilter.file = "/usr/scripts/intranet/static/favicon.ico" diff --git a/intranet/conf/prod.cfg b/intranet/conf/prod.cfg index 7527c7d7..c81f10f3 100644 --- a/intranet/conf/prod.cfg +++ b/intranet/conf/prod.cfg @@ -1,4 +1,4 @@ -# The configuration file called myconfigfile.conf +# The configuration file called prod.conf [global] server.socketPort=8080 server.socketHost="" diff --git a/intranet/plugins/__init__.py b/intranet/plugins/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/intranet/templates/accueil.tmpl b/intranet/templates/accueil.tmpl index dcdf295e..57af4f4b 100644 --- a/intranet/templates/accueil.tmpl +++ b/intranet/templates/accueil.tmpl @@ -2,46 +2,18 @@ $sys.path.append(cherrypy.config.get('rootDir')) #from plugins.verifdroitsfilter import verifDroits