# HG changeset patch # User Marcin Kuzminski # Date 2010-04-06 22:51:55 # Node ID 71ffa932799da900fa3f2c133d09ff538c139cce # Parent cbc1624cb4990aaefa780cc30ea28255c560d485 Added app basic auth. Changed few deprecations for new pylons. added sqlite logging for user actions. diff --git a/development.ini b/development.ini --- a/development.ini +++ b/development.ini @@ -29,6 +29,7 @@ full_stack = true static_files = true lang=en cache_dir = %(here)s/data +repos_name = etelko ################################################################################ ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ## diff --git a/production.ini b/production.ini --- a/production.ini +++ b/production.ini @@ -29,6 +29,7 @@ full_stack = true static_files = false lang=en cache_dir = %(here)s/data +repos_name = etelko ################################################################################ ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ## diff --git a/pylons_app/config/environment.py b/pylons_app/config/environment.py --- a/pylons_app/config/environment.py +++ b/pylons_app/config/environment.py @@ -28,17 +28,16 @@ def load_environment(global_conf, app_co template_engine='mako', paths=paths) config['routes.map'] = make_map() - config['pylons.g'] = app_globals.Globals() + config['pylons.app_globals'] = app_globals.Globals() config['pylons.h'] = pylons_app.lib.helpers # Create the Mako TemplateLookup, with the default auto-escaping - config['pylons.g'].mako_lookup = TemplateLookup( + config['pylons.app_globals'].mako_lookup = TemplateLookup( directories=paths['templates'], error_handler=handle_mako_error, module_directory=os.path.join(app_conf['cache_dir'], 'templates'), - output_encoding='utf-8', - imports=['from webhelpers.html import escape'], - default_filters=['escape']) + input_encoding='utf-8', default_filters=['escape'], + imports=['from webhelpers.html import escape']) # CONFIGURATION OPTIONS HERE (note: all config options will override # any Pylons config options) diff --git a/pylons_app/config/middleware.py b/pylons_app/config/middleware.py --- a/pylons_app/config/middleware.py +++ b/pylons_app/config/middleware.py @@ -8,9 +8,9 @@ from pylons import config from pylons.middleware import ErrorHandler, StatusCodeRedirect from pylons.wsgiapp import PylonsApp from routes.middleware import RoutesMiddleware - +from paste.auth.basic import AuthBasicHandler from pylons_app.config.environment import load_environment - +from pylons_app.lib.auth import authfunc def make_app(global_conf, full_stack=True, **app_conf): """Create a Pylons WSGI application and return it @@ -43,7 +43,8 @@ def make_app(global_conf, full_stack=Tru app = RoutesMiddleware(app, config['routes.map']) app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) - + app = AuthBasicHandler(app, config['repos_name'] + ' mercurial repository', authfunc) + if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) @@ -55,7 +56,7 @@ def make_app(global_conf, full_stack=Tru app = StatusCodeRedirect(app, [400, 401, 403, 500]) else: app = StatusCodeRedirect(app, [400, 401, 403, 500]) - + # Establish the Registry for this application app = RegistryManager(app) diff --git a/pylons_app/controllers/hg.py b/pylons_app/controllers/hg.py --- a/pylons_app/controllers/hg.py +++ b/pylons_app/controllers/hg.py @@ -1,23 +1,22 @@ #!/usr/bin/python # -*- coding: utf-8 -*- import logging +import os from pylons_app.lib.base import BaseController, render -from pylons import c, g, session, request +from pylons import tmpl_context as c, app_globals as g, session, request, config from pylons_app.lib import helpers as h from mako.template import Template -from pprint import pprint -import os from mercurial import ui, hg from mercurial.error import RepoError from ConfigParser import ConfigParser -import encodings from pylons.controllers.util import abort + log = logging.getLogger(__name__) class HgController(BaseController): def __before__(self): - c.repos_prefix = 'etelko' + c.repos_prefix = config['repos_name'] def view(self, *args, **kwargs): response = g.hgapp(request.environ, self.start_response) @@ -33,14 +32,14 @@ class HgController(BaseController): try: tmpl = u''.join(response) template = Template(tmpl, lookup=request.environ['pylons.pylons']\ - .config['pylons.g'].mako_lookup) + .config['pylons.app_globals'].mako_lookup) except (RuntimeError, UnicodeDecodeError): log.info('disabling unicode due to encoding error') response = g.hgapp(request.environ, self.start_response) tmpl = ''.join(response) template = Template(tmpl, lookup=request.environ['pylons.pylons']\ - .config['pylons.g'].mako_lookup, disable_unicode=True) + .config['pylons.app_globals'].mako_lookup, disable_unicode=True) return template.render(g=g, c=c, session=session, h=h) diff --git a/pylons_app/lib/auth.py b/pylons_app/lib/auth.py new file mode 100644 --- /dev/null +++ b/pylons_app/lib/auth.py @@ -0,0 +1,105 @@ +import sqlite3 +import os +import logging +from os.path import dirname as dn +from datetime import datetime +import crypt + +log = logging.getLogger(__name__) +ROOT = dn(dn(dn(os.path.realpath(__file__)))) + +def get_sqlite_cur_conn(): + conn = sqlite3.connect(os.path.join(ROOT, 'auth.sqlite')) + cur = conn.cursor() + return conn, cur + +def authfunc(environ, username, password): + conn, cur = get_sqlite_cur_conn() + password_crypt = crypt.crypt(password, '6a') + + cur.execute("SELECT * FROM users WHERE username=?", (username,)) + data = cur.fetchone() + + if data: + if data[3]: + if data[1] == username and data[2] == password_crypt: + log.info('user %s authenticated correctly', username) + + http_accept = environ.get('HTTP_ACCEPT') + + if http_accept.startswith('application/mercurial') or \ + environ['PATH_INFO'].find('raw-file') != -1: + cmd = environ['PATH_INFO'] + for qry in environ['QUERY_STRING'].split('&'): + if qry.startswith('cmd'): + cmd += "|" + qry + + try: + cur.execute('''INSERT INTO + user_logs + VALUES(?,?,?,?)''', + (None, data[0], cmd, datetime.now())) + conn.commit() + except Exception as e: + conn.rollback() + log.error(e) + + + return True + else: + log.error('user %s is disabled', username) + + return False + +def create_user_table(): + ''' + Create a auth database + ''' + conn, cur = get_sqlite_cur_conn() + try: + log.info('creating table %s', 'users') + cur.execute('''DROP TABLE IF EXISTS users ''') + cur.execute('''CREATE TABLE users + (id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT, + password TEXT, + active INTEGER)''') + log.info('creating table %s', 'user_logs') + cur.execute('''DROP TABLE IF EXISTS user_logs ''') + cur.execute('''CREATE TABLE user_logs + (id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER, + last_action TEXT, + last_action_date DATETIME)''') + conn.commit() + except: + conn.rollback() + raise + + cur.close() + +def create_user(username, password): + conn, cur = get_sqlite_cur_conn() + password_crypt = crypt.crypt(password, '6a') + cur_date = datetime.now() + log.info('creating user %s', username) + try: + cur.execute('''INSERT INTO users values (?,?,?,?) ''', + (None, username, password_crypt, 1,)) + conn.commit() + except: + conn.rollback() + raise + +if __name__ == "__main__": + create_user_table() + create_user('marcink', 'qweqwe') + create_user('lukaszd', 'qweqwe') + create_user('adriand', 'qweqwe') + create_user('radek', 'qweqwe') + create_user('skrzeka', 'qweqwe') + create_user('bart', 'qweqwe') + create_user('maho', 'qweqwe') + create_user('michalg', 'qweqwe') + + #authfunc('', 'marcink', 'qweqwe')