138 lines
4.6 KiB
Python
138 lines
4.6 KiB
Python
import cherrypy
|
||
import hashlib
|
||
import urllib.parse
|
||
import lybmods.lybtools as lybtools
|
||
import lybmods.lybpqconn as lybpqconn
|
||
from lybmods.lybclasses import Grp
|
||
|
||
def check_credentials(username, password):
|
||
"""Проверяет имя пользователи и пароль.
|
||
Возвращает None при успехе иначе строку с описанием ошибки"""
|
||
cur = lybpqconn.conn.cursor()
|
||
newhash = hashlib.sha1()
|
||
newhash.update(username.encode("utf-8"))
|
||
newhash.update(password.encode("utf-8"))
|
||
cur.execute(lybtools.qChkUserAndPwd, (username, newhash.hexdigest()))
|
||
res = cur.fetchone()[0]
|
||
if res > 0:
|
||
return None
|
||
else:
|
||
return "Incorrect username or password."
|
||
|
||
def check_auth(*args, **kwargs):
|
||
"""A tool that looks in config for 'auth.require'. If found and it
|
||
is not None, a login is required and the entry is evaluated as alist of
|
||
conditions that the user must fulfill"""
|
||
conditions = cherrypy.request.config.get('auth.require', None)
|
||
# format GET params
|
||
get_parmas = urllib.parse.quote(cherrypy.request.request_line.split()[1])
|
||
if conditions is not None:
|
||
username = cherrypy.session.get(lybtools.SESSION_KEY)
|
||
if username:
|
||
cherrypy.request.login = username
|
||
for condition in conditions:
|
||
# A condition is just a callable that returns true orfalse
|
||
if not condition():
|
||
# Send old page as from_page parameter
|
||
raise cherrypy.HTTPRedirect("/denied")
|
||
else:
|
||
# Send old page as from_page parameter
|
||
raise cherrypy.HTTPRedirect("/loginpage?from_page=%s" % get_parmas)
|
||
|
||
#cherrypy.lybtools.auth = cherrypy.Tool('before_handler', check_auth)
|
||
|
||
def require(*conditions):
|
||
"""A decorator that appends conditions to the auth.require config
|
||
variable."""
|
||
def decorate(f):
|
||
if not hasattr(f, '_cp_config'):
|
||
f._cp_config = dict()
|
||
if 'auth.require' not in f._cp_config:
|
||
f._cp_config['auth.require'] = []
|
||
f._cp_config['auth.require'].extend(conditions)
|
||
return f
|
||
return decorate
|
||
|
||
|
||
# Conditions are callables that return True
|
||
# if the user fulfills the conditions they define, False otherwise
|
||
#
|
||
# They can access the current username as cherrypy.request.login
|
||
#
|
||
# Define those at will however suits the application.
|
||
|
||
def member_of(groupname):
|
||
def check():
|
||
username = cherrypy.session.get(lybtools.SESSION_KEY, None)
|
||
try:
|
||
if username and username in [x.name for x in Grp(groupname).members]:
|
||
return True
|
||
else:
|
||
return False
|
||
except KeyError:
|
||
return False
|
||
return check
|
||
|
||
def name_is(reqd_username):
|
||
return lambda: reqd_username == cherrypy.session.get(lybtools.SESSION_KEY, None)
|
||
|
||
# These might be handy
|
||
|
||
def any_of(*conditions):
|
||
"""Returns True if any of the conditions match"""
|
||
def check():
|
||
for c in conditions:
|
||
if c():
|
||
return True
|
||
return False
|
||
return check
|
||
|
||
# By default all conditions are required, but this might still be
|
||
# needed if you want to use it inside of an any_of(...) condition
|
||
def all_of(*conditions):
|
||
"""Returns True if all of the conditions match"""
|
||
def check():
|
||
for c in conditions:
|
||
if not c():
|
||
return False
|
||
return True
|
||
return check
|
||
|
||
|
||
# Controller to provide login and logout actions
|
||
|
||
class AuthController(object):
|
||
|
||
def on_login(self, username):
|
||
"""Called on successful login"""
|
||
|
||
def on_logout(self, username):
|
||
"""Called on logout"""
|
||
|
||
@cherrypy.expose
|
||
def login(self, username=None, password=None, from_page="/"):
|
||
if username is None or password is None:
|
||
raise cherrypy.HTTPRedirect("/")
|
||
|
||
error_msg = check_credentials(username, password)
|
||
if error_msg:
|
||
raise cherrypy.HTTPRedirect("/loginpage?from_page=" + from_page)
|
||
else:
|
||
cherrypy.session.regenerate()
|
||
cherrypy.session[lybtools.SESSION_KEY] = cherrypy.request.login = username
|
||
self.on_login(username)
|
||
raise cherrypy.HTTPRedirect(from_page or "/")
|
||
|
||
@cherrypy.expose
|
||
def logout(self, from_page="/"):
|
||
sess = cherrypy.session
|
||
username = sess.get(lybtools.SESSION_KEY, None)
|
||
# for key in sess.keys():
|
||
# del sess[key]
|
||
# sess[lybtools.SESSION_KEY] = None
|
||
sess.regenerate()
|
||
sess.delete()
|
||
if username:
|
||
cherrypy.request.login = None
|
||
self.on_logout(username)
|
||
raise cherrypy.HTTPRedirect("/") |