Sunil Mohan Adapa 58d13e3ed8 Use Django dispatcher instead of CherryPy dispatcher
This commit is big because anything small breaks the code.

- Django dispatcher is based on regular expressions and does not need a tree structure
- Reduces a lot of unnecessary dependencies among modules
- Use Django sessions middlewear instead of CherryPy sessions
- Introduce dependency based modules instead of numeric load order
- Remove PagePlugin and simply use Django views
- Eliminate page rendering wrappers in favor of Django context processors
- Use custom auth for now until replaced by Django auth middlewear
- Use Django templated 404 and 500 error pages
2014-06-12 23:33:25 +05:30

101 lines
2.8 KiB
Python

from django.http.response import HttpResponseRedirect
import functools
from passlib.hash import bcrypt
from passlib.exc import PasswordSizeError
import cfg
from model import User
cfg.session_key = '_username'
def add_user(username, passphrase, name='', email='', expert=False):
"""Add a new user with specified username and passphrase.
"""
error = None
if not username: error = "Must specify a username!"
if not passphrase: error = "Must specify a passphrase!"
if error is None:
if username in map(lambda x: x[0], cfg.users.get_all()):
error = "User already exists!"
else:
try:
pass_hash = bcrypt.encrypt(passphrase)
except PasswordSizeError:
error = "Password is too long."
if error is None:
di = {
'username':username,
'name':name,
'email':email,
'expert':'on' if expert else 'off',
'groups':['expert'] if expert else [],
'passphrase':pass_hash,
'salt':pass_hash[7:29], # for bcrypt
}
new_user = User(di)
cfg.users.set(username,new_user)
if error:
cfg.log(error)
return error
def check_credentials(username, passphrase):
"""Verifies credentials for username and passphrase.
Returns None on success or a string describing the error on failure.
Handles passwords up to 4096 bytes:
>>> len("A" * 4096)
4096
>>> len(u"u|2603" * 682)
4092
"""
if not username or not passphrase:
error = "No username or password."
cfg.log(error)
return error
bad_authentication = "Bad username or password."
hashed_password = None
if username not in cfg.users or 'passphrase' not in cfg.users[username]:
cfg.log(bad_authentication)
return bad_authentication
hashed_password = cfg.users[username]['passphrase']
try:
# time-dependent comparison when non-ASCII characters are used.
if not bcrypt.verify(passphrase, hashed_password):
error = bad_authentication
else:
error = None
except PasswordSizeError:
error = bad_authentication
if error:
cfg.log(error)
return error
# XXX: Only required until we start using Django authentication system properly
def login_required(func):
"""A decorator to ensure that user is logged in before accessing a view"""
@functools.wraps(func)
def wrapper(request, *args, **kwargs):
"""Check that user is logged in"""
if not request.session.get(cfg.session_key, None):
return HttpResponseRedirect(
cfg.server_dir + "/auth/login?from_page=%s" % request.path)
return func(request, *args, **kwargs)
return wrapper