auth.py
98 lines
| 3.5 KiB
| text/x-python
|
PythonLexer
Marcin Kuzminski
|
r41 | from datetime import datetime | ||
r190 | from decorator import decorator | |||
from functools import wraps | ||||
r52 | from pylons import session, url | |||
from pylons.controllers.util import abort, redirect | ||||
Marcin Kuzminski
|
r64 | from pylons_app.model import meta | ||
from pylons_app.model.db import Users, UserLogs | ||||
r190 | from sqlalchemy.exc import OperationalError | |||
Marcin Kuzminski
|
r64 | from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound | ||
r190 | import crypt | |||
import logging | ||||
log = logging.getLogger(__name__) | ||||
Marcin Kuzminski
|
r41 | |||
Marcin Kuzminski
|
r64 | def get_crypt_password(password): | ||
r190 | """ | |||
Cryptographic function used for password hashing | ||||
@param password: password to hash | ||||
""" | ||||
Marcin Kuzminski
|
r64 | return crypt.crypt(password, '6a') | ||
Marcin Kuzminski
|
r46 | |||
Marcin Kuzminski
|
r41 | def authfunc(environ, username, password): | ||
Marcin Kuzminski
|
r64 | sa = meta.Session | ||
password_crypt = get_crypt_password(password) | ||||
r42 | try: | |||
Marcin Kuzminski
|
r64 | user = sa.query(Users).filter(Users.username == username).one() | ||
except (NoResultFound, MultipleResultsFound, OperationalError) as e: | ||||
r42 | log.error(e) | |||
Marcin Kuzminski
|
r64 | user = None | ||
if user: | ||||
if user.active: | ||||
if user.username == username and user.password == password_crypt: | ||||
Marcin Kuzminski
|
r41 | log.info('user %s authenticated correctly', username) | ||
r45 | if environ: | |||
http_accept = environ.get('HTTP_ACCEPT') | ||||
if http_accept.startswith('application/mercurial') or \ | ||||
environ['PATH_INFO'].find('raw-file') != -1: | ||||
Marcin Kuzminski
|
r64 | repo = environ['PATH_INFO'] | ||
r45 | for qry in environ['QUERY_STRING'].split('&'): | |||
if qry.startswith('cmd'): | ||||
Marcin Kuzminski
|
r41 | |||
r45 | try: | |||
Marcin Kuzminski
|
r64 | user_log = UserLogs() | ||
user_log.user_id = user.user_id | ||||
user_log.action = qry | ||||
user_log.repository = repo | ||||
user_log.action_date = datetime.now() | ||||
sa.add(user_log) | ||||
sa.commit() | ||||
log.info('Adding user %s, action %s', username, qry) | ||||
r45 | except Exception as e: | |||
Marcin Kuzminski
|
r64 | sa.rollback() | ||
r45 | log.error(e) | |||
Marcin Kuzminski
|
r41 | return True | ||
else: | ||||
log.error('user %s is disabled', username) | ||||
return False | ||||
r190 | class AuthUser(object): | |||
""" | ||||
A simple object that handles a mercurial username for authentication | ||||
""" | ||||
username = 'Empty' | ||||
is_authenticated = False | ||||
is_admin = False | ||||
permissions = set() | ||||
group = set() | ||||
def __init__(self): | ||||
pass | ||||
#=============================================================================== | ||||
# DECORATORS | ||||
#=============================================================================== | ||||
class LoginRequired(object): | ||||
""" | ||||
Must be logged in to execute this function else redirect to login page | ||||
""" | ||||
def __init__(self): | ||||
pass | ||||
def __call__(self, func): | ||||
log.info('Checking login required') | ||||
@wraps(func) | ||||
def _wrapper(*fargs, **fkwargs): | ||||
user = session.get('hg_app_user', AuthUser()) | ||||
if user.is_authenticated: | ||||
log.info('user %s is authenticated', user.username) | ||||
func(*fargs) | ||||
else: | ||||
logging.info('user %s not authenticated', user.username) | ||||
return redirect(url('login_home')) | ||||
r52 | ||||
r190 | return _wrapper | |||