lybrary/lybmods/lybformauth.py

138 lines
4.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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("/")