1
0
mirror of https://github.com/kakwa/ldapcherry synced 2024-11-25 18:54:29 +01:00

basic skeleton for web application

This commit is contained in:
kakwa 2015-04-15 23:10:01 +02:00
parent 7ec0cb4e74
commit 43299cb52f
2 changed files with 296 additions and 1 deletions

View File

@ -1,7 +1,298 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# vim:set expandtab tabstop=4 shiftwidth=4: # vim:set expandtab tabstop=4 shiftwidth=4:
# #
# The MIT License (MIT) # The MIT License (MIT)
# LdapCherry # ldapCherry
# Copyright (c) 2014 Carpentier Pierre-Francois # Copyright (c) 2014 Carpentier Pierre-Francois
#generic imports
import sys
import re
import traceback
import logging
import logging.handlers
from operator import itemgetter
from socket import error as socket_error
#cherrypy http framework imports
import cherrypy
from cherrypy.lib.httputil import parse_query_string
#mako template engines imports
from mako.template import Template
from mako import lookup
SESSION_KEY = '_cp_username'
class ldapCherry(object):
def _get_param(self, section, key, config, default=None):
""" Get configuration parameter "key" from config
@str section: the section of the config file
@str key: the key to get
@dict config: the configuration (dictionnary)
@str default: the default value if parameter "key" is not present
@rtype: str (value of config['key'] if present default otherwith
"""
if section in config and key in config[section]:
return config[section][key]
if not default is None:
return default
else:
raise MissingParameter(section, key)
def reload(self, config = None):
""" load/reload the configuration
"""
try:
# definition of the template directory
self.template_dir = self._get_param('resources', 'template_dir', config)
# log configuration handling
# get log level
# (if not in configuration file, log level is set to debug)
level = self._get_loglevel(self._get_param('global', 'log.level', config, 'debug'))
# log format for syslog
syslog_formatter = logging.Formatter(
"ldapcherry[%(process)d]: %(message)s")
access_handler = self._get_param('global', 'log.access_handler', config, 'syslog')
# replace access log handler by a syslog handler
if access_handler == 'syslog':
cherrypy.log.access_log.handlers = []
handler = logging.handlers.SysLogHandler(address = '/dev/log',
facility='user')
handler.setFormatter(syslog_formatter)
cherrypy.log.access_log.addHandler(handler)
# if file, we keep the default
elif access_handler == 'file':
pass
# replace access log handler by a null handler
elif access_handler == 'none':
cherrypy.log.access_log.handlers = []
handler = logging.NullHandler()
cherrypy.log.access_log.addHandler(handler)
error_handler = self._get_param('global', 'log.error_handler', config, 'syslog')
# replacing the error handler by a syslog handler
if error_handler == 'syslog':
cherrypy.log.error_log.handlers = []
# redefining log.error method because cherrypy does weird
# things like adding the date inside the message
# or adding space even if context is empty
# (by the way, what's the use of "context"?)
def syslog_error(msg='', context='',
severity=logging.INFO, traceback=False):
if traceback:
msg += cherrypy._cperror.format_exc()
if context == '':
cherrypy.log.error_log.log(severity, msg)
else:
cherrypy.log.error_log.log(severity,
' '.join((context, msg)))
cherrypy.log.error = syslog_error
handler = logging.handlers.SysLogHandler(address = '/dev/log',
facility='user')
handler.setFormatter(syslog_formatter)
cherrypy.log.error_log.addHandler(handler)
# if file, we keep the default
elif error_handler == 'file':
pass
# replacing the error handler by a null handler
elif error_handler == 'none':
cherrypy.log.error_log.handlers = []
handler = logging.NullHandler()
cherrypy.log.error_log.addHandler(handler)
# set log level
cherrypy.log.error_log.setLevel(level)
cherrypy.log.access_log.setLevel(level)
# preload templates
self.temp_lookup = lookup.TemplateLookup(
directories=self.template_dir, input_encoding='utf-8'
)
self.temp_index = self.temp_lookup.get_template('index.tmpl')
self.temp_result = self.temp_lookup.get_template('result.tmpl')
self.temp_error = self.temp_lookup.get_template('error.tmpl')
self.temp_login = self.temp_lookup.get_template('login.tmpl')
# loading the authentification module
auth_module = self._get_param('auth', 'auth.module', config)
auth = __import__(auth_module, globals(), locals(), ['Auth'], -1)
self.auth = auth.Auth(config['auth'], cherrypy.log)
except MissingParameter as e:
cherrypy.log.error(
msg = "ldapcherry failure, "\
"missing parameter '%(param)s' "\
"in section '%(section)s'" % {
'param': e.key,
'section': e.section
},
severity = logging.ERROR
)
exit(1)
def _get_loglevel(self, level):
""" return logging level object
corresponding to a given level passed as
a string
"""
if level == 'debug':
return logging.DEBUG
elif level == 'notice':
return logging.NOTICE
elif level == 'info':
return logging.INFO
elif level == 'warning' or level == 'warn':
return logging.WARNING
elif level == 'error' or level == 'err':
return logging.ERROR
elif level == 'critical' or level == 'crit':
return logging.CRITICAL
elif level == 'alert':
return logging.ALERT
elif level == 'emergency' or level == 'emerg':
return logging.EMERGENCY
else:
return logging.INFO
def _reraise(self, exception):
""" reraise a given exception"""
raise exception
def _error_handler(self, exception, backend=''):
""" exception handling function, takes an exception
and returns the right error page and emits a log
"""
# log the traceback as 'debug'
cherrypy.log.error(
msg = '',
severity = logging.DEBUG,
traceback= True
)
# log and error page handling
def render_error(alert, message):
if alert == 'danger':
severity = logging.ERROR
elif alert == 'warning':
severity = logging.WARNING
else:
severity = logging.CRITICAL
cherrypy.log.error(
msg = message,
severity = severity
)
return self.temp_error.render(
logout_button = self.auth.logout_button,
alert = alert,
message = message,
)
# reraise the exception
try:
self._reraise(exception)
# error handling
except ldapcherry.exception.MissingParameter:
cherrypy.response.status = 500
alert = 'danger'
message = 'Example danger'
return render_error(alert, message)
except KeyError:
cherrypy.response.status = 400
alert = 'warning'
message = 'Example warning'
return render_error(alert, message)
@cherrypy.expose
def signin(self):
"""simple signin page
"""
return self.temp_login.render()
@cherrypy.expose
def login(self, login, password):
"""login page
"""
if self.auth.check_credentials(login, password):
message = "login success for user '%(user)s'" % {
'user': login
}
cherrypy.log.error(
msg = message,
severity = logging.INFO
)
cherrypy.session[SESSION_KEY] = cherrypy.request.login = login
raise cherrypy.HTTPRedirect("/")
else:
message = "login failed for user '%(user)s'" % {
'user': login
}
cherrypy.log.error(
msg = message,
severity = logging.WARNING
)
raise cherrypy.HTTPRedirect("/signin")
@cherrypy.expose
def logout(self):
""" logout page
"""
user = self.auth.end_session()
message = "user '%(user)s' logout" % {
'user': user
}
cherrypy.log.error(
msg = message,
severity = logging.INFO
)
raise cherrypy.HTTPRedirect("/signin")
@cherrypy.expose
def index(self, **params):
"""main page rendering
"""
pass
@cherrypy.expose
def searchuser(self):
""" search user page """
pass
@cherrypy.expose
def adduser(self):
""" add user page """
pass
@cherrypy.expose
def removeuser(self):
""" remove user page """
pass
@cherrypy.expose
def modifyuser(self):
""" modify user page """
pass
@cherrypy.expose
def modifyself(self):
""" self modify user page """
pass

View File

@ -5,3 +5,7 @@
# LdapCherry # LdapCherry
# Copyright (c) 2014 Carpentier Pierre-Francois # Copyright (c) 2014 Carpentier Pierre-Francois
class MissingParameter(Exception):
def __init__(self, section, key):
self.section = section
self.key = key