1
0
Fork 0

* use sha512 passwords

* more robust SQLAlchemy session handling code
 * implemented password change mechanism
This commit is contained in:
Jan Dittberner 2008-06-05 18:25:08 +00:00
parent ade660419c
commit 949e699e25
7 changed files with 99 additions and 28 deletions

View file

@ -38,7 +38,7 @@ sqlalchemy.url = sqlite:///%(here)s/gvaweb.sqlite
authkit.setup.method = form, cookie authkit.setup.method = form, cookie
authkit.form.authenticate.user.type = gnuviechadminweb.model:GVAUsers authkit.form.authenticate.user.type = gnuviechadminweb.model:GVAUsers
authkit.form.authenticate.user.data = gnuviechadminweb.model.meta authkit.form.authenticate.user.data = gnuviechadminweb.model.meta
authkit.form.authenticate.user.encrypt = authkit.users:md5 authkit.form.authenticate.user.encrypt = gnuviechadminweb.model:sha512
authkit.cookie.secret = really secret data authkit.cookie.secret = really secret data
authkit.cookie.signoutpath = /login/logout authkit.cookie.signoutpath = /login/logout

View file

@ -2,6 +2,8 @@
import logging import logging
from gnuviechadminweb.lib.base import * from gnuviechadminweb.lib.base import *
from authkit.permissions import ValidAuthKitUser
from authkit.authorize.pylons_adaptors import authorize
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -9,3 +11,26 @@ class GvaController(BaseController):
def index(self): def index(self):
# Return a rendered template # Return a rendered template
return render('/main.mako') return render('/main.mako')
@authorize(ValidAuthKitUser())
def password(self):
return render('/chpassword.mako')
@authorize(ValidAuthKitUser())
def updatepassword(self):
users = request.environ['authkit.users']
if users.user_has_password(request.environ['REMOTE_USER'],
request.params['oldpassword']):
if request.params['password'] != request.params['confirm']:
c.messages['errors'].append("New password and confirmation don't match")
elif len(request.params['password']) < 8:
c.messages['errors'].append("Your new password is too short. It must consist of at least 8 characters")
else:
users.user_set_password(request.environ['REMOTE_USER'],
request.params['password'])
c.messages['messages'].append("Your password has been changed.")
else:
c.messages['errors'].append("Your old password is not correct.")
if c.messages['errors']:
return render('/chpassword.mako')
return render('/main.mako')

View file

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from authkit.users import Users from authkit.users import Users
from gnuviechadminweb.model.user import Group, Role, User from gnuviechadminweb.model.user import Group, Role, User
@ -6,33 +7,33 @@ import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def needsConnection(func): def initializedSession(func):
def wrapper(*__args, **__kw): def wrapper(*__args, **__kwargs):
from sqlalchemy.orm import create_session meta = __args[0].meta
engine = __args[0].meta.engine conn = meta.engine.connect()
conn = engine.contextual_connect() meta.Session.configure(bind=conn)
if conn.closed:
conn = engine.connect()
__args[0].session = create_session(bind=conn)
try: try:
return func(*__args, **__kw) return func(*__args, **__kwargs)
finally: finally:
meta.Session.remove()
conn.close() conn.close()
else:
__args[0].session = create_session(bind=conn)
return func(*__args, **__kw)
return wrapper return wrapper
def sha512(password, secret = ''):
import hashlib
m = hashlib.sha512()
m.update(password)
m.update(secret)
return m.hexdigest()
class GVAUsers(Users): class GVAUsers(Users):
def __init__(self, data, encrypt = None): def __init__(self, data, encrypt = None):
Users.__init__(self, data, encrypt) Users.__init__(self, data, encrypt)
log.debug("in __init__") log.debug("in __init__")
self.meta = eval_import(self.data) self.meta = eval_import(self.data)
self.session = self.meta.Session
@needsConnection
def _getSession(self): def _getSession(self):
return self.session return self.meta.Session
def _get_group(self, groupname): def _get_group(self, groupname):
return self._getSession().query(Group).filter_by(name=groupname).one() return self._getSession().query(Group).filter_by(name=groupname).one()
@ -44,6 +45,7 @@ class GVAUsers(Users):
return self._getSession().query(Role).filter_by(name=rolename).one() return self._getSession().query(Role).filter_by(name=rolename).one()
# Create Methods # Create Methods
@initializedSession
def user_create(self, username, password, group=None): def user_create(self, username, password, group=None):
n_user = User() n_user = User()
n_user.name = username n_user.name = username
@ -53,12 +55,14 @@ class GVAUsers(Users):
self._getSession().save(n_user) self._getSession().save(n_user)
self._getSession().commit() self._getSession().commit()
@initializedSession
def role_create(self, role): def role_create(self, role):
n_role = Role() n_role = Role()
n_role.name = role n_role.name = role
self._getSession().save(n_role) self._getSession().save(n_role)
self._getSession().commit() self._getSession().commit()
@initializedSession
def group_create(self, group): def group_create(self, group):
n_group = Group() n_group = Group()
n_group.name = group n_group.name = group
@ -66,19 +70,23 @@ class GVAUsers(Users):
self._getSession().commit() self._getSession().commit()
# Delete Methods # Delete Methods
@initializedSession
def user_delete(self, username): def user_delete(self, username):
self._getSession().delete(self._get_user(username)) self._getSession().delete(self._get_user(username))
self._getSession().commit() self._getSession().commit()
@initializedSession
def role_delete(self, role): def role_delete(self, role):
self._getSession().delete(self._get_role(role)) self._getSession().delete(self._get_role(role))
self._getSession().commit() self._getSession().commit()
@initializedSession
def group_delete(self, group): def group_delete(self, group):
self._getSession().delete(self._get_group()) self._getSession().delete(self._get_group())
self._getSession().commit() self._getSession().commit()
# Delete Cascade Methods # Delete Cascade Methods
@initializedSession
def role_delete_cascade(self, role): def role_delete_cascade(self, role):
n_role = self._get_role(role) n_role = self._get_role(role)
for user in self._getSession().query(User).roles.any(name=role).all(): for user in self._getSession().query(User).roles.any(name=role).all():
@ -86,6 +94,7 @@ class GVAUsers(Users):
self._getSession().delete(n_role) self._getSession().delete(n_role)
self._getSession().commit() self._getSession().commit()
@initializedSession
def group_delete_cascade(self, group): def group_delete_cascade(self, group):
n_group = self._get_group(group) n_group = self._get_group(group)
self._getSession().delete(self._getSession().query(User).filter_by( self._getSession().delete(self._getSession().query(User).filter_by(
@ -94,32 +103,39 @@ class GVAUsers(Users):
self._getSession().commit() self._getSession().commit()
# Existence Methods # Existence Methods
@initializedSession
def user_exists(self, username): def user_exists(self, username):
return self._getSession().query(User).filter_by( return self._getSession().query(User).filter_by(
name=username).count() == 1 name=username).count() == 1
@initializedSession
def role_exists(self, role): def role_exists(self, role):
return self._getSession().query(Role).filter_by( return self._getSession().query(Role).filter_by(
name=role).count() == 1 name=role).count() == 1
@initializedSession
def group_exists(self, group): def group_exists(self, group):
return self._getSession().query(Group).filter_by( return self._getSession().query(Group).filter_by(
name=group).count() == 1 name=group).count() == 1
# List Methods # List Methods
@initializedSession
def list_roles(self): def list_roles(self):
return [role.name.lower() for role in self._getSession().query( return [role.name.lower() for role in self._getSession().query(
Role).all()] Role).all()]
@initializedSession
def list_users(self): def list_users(self):
return [user.name.lower() for user in self._getSession().query( return [user.name.lower() for user in self._getSession().query(
User).all()] User).all()]
@initializedSession
def list_groups(self): def list_groups(self):
return [group.name.lower() for group in self._getSession().query( return [group.name.lower() for group in self._getSession().query(
Group).all()] Group).all()]
# User Methods # User Methods
@initializedSession
def user(self, username): def user(self, username):
user = self._get_user(username) user = self._get_user(username)
roles = [role.name.lower() for role in user.roles] roles = [role.name.lower() for role in user.roles]
@ -131,40 +147,48 @@ class GVAUsers(Users):
'roles' : roles 'roles' : roles
} }
@initializedSession
def user_roles(self, username): def user_roles(self, username):
user = self._get_user(username) user = self._get_user(username)
roles = [role.name.lower() for role in user.roles] roles = [role.name.lower() for role in user.roles]
roles.sort() roles.sort()
return roles return roles
@initializedSession
def user_group(self, username): def user_group(self, username):
user = self._get_user(username) user = self._get_user(username)
return None if user.group is None else user.group.name return None if user.group is None else user.group.name
@initializedSession
def user_password(self, username): def user_password(self, username):
user = self._get_user(username) user = self._get_user(username)
return user.password return user.password
@initializedSession
def user_has_role(self, username, role): def user_has_role(self, username, role):
user = self._get_user(username) user = self._get_user(username)
return role in [role.name for role in user.roles] return role in [role.name for role in user.roles]
@initializedSession
def user_has_group(self, username, group): def user_has_group(self, username, group):
user = self._get_user(username) user = self._get_user(username)
return (group is None and user.group is None) or \ return (group is None and user.group is None) or \
(group is not None and user.group is not None and \ (group is not None and user.group is not None and \
group == user.group.name) group == user.group.name)
@initializedSession
def user_has_password(self, username, password): def user_has_password(self, username, password):
user = self._get_user(username) user = self._get_user(username)
return user.password == self.encrypt(password) return user.password == self.encrypt(password)
@initializedSession
def user_set_username(self, username, new_username): def user_set_username(self, username, new_username):
user = self._get_user(username) user = self._get_user(username)
user.name = new_username user.name = new_username
self._getSession().update(user) self._getSession().update(user)
self._getSession().commit() self._getSession().commit()
@initializedSession
def user_set_group(self, username, group, add_if_necessary=False): def user_set_group(self, username, group, add_if_necessary=False):
if add_if_necessary and self._getSession().query(Group).filter_by( if add_if_necessary and self._getSession().query(Group).filter_by(
name=group).count() == 0: name=group).count() == 0:
@ -175,6 +199,7 @@ class GVAUsers(Users):
self._getSession().update(user) self._getSession().update(user)
self._getSession().commit() self._getSession().commit()
@initializedSession
def user_add_role(self, username, role, add_if_necessary=False): def user_add_role(self, username, role, add_if_necessary=False):
if add_if_necessary and self._getSession().query(Role).filter_by( if add_if_necessary and self._getSession().query(Role).filter_by(
name=role).count() == 0: name=role).count() == 0:
@ -186,6 +211,7 @@ class GVAUsers(Users):
self._getSession().update(user) self._getSession().update(user)
self._getSession().commit() self._getSession().commit()
@initializedSession
def user_remove_role(self, username, role): def user_remove_role(self, username, role):
roleobj = self._get_role(role) roleobj = self._get_role(role)
user = self._get_user(username) user = self._get_user(username)
@ -193,8 +219,16 @@ class GVAUsers(Users):
del user.roles[roleobj.id] del user.roles[roleobj.id]
self._getSession().commit() self._getSession().commit()
@initializedSession
def user_remove_group(self, username): def user_remove_group(self, username):
user = self._get_user(username) user = self._get_user(username)
user.group = None user.group = None
self._getSession().update(user) self._getSession().update(user)
self._getSession().commit() self._getSession().commit()
@initializedSession
def user_set_password(self, username, password):
user = self._get_user(username)
user.password = self.encrypt(password)
self._getSession().update(user)
self._getSession().commit()

View file

@ -12,5 +12,5 @@ def init_model(engine):
meta.Session = orm.scoped_session(sm) meta.Session = orm.scoped_session(sm)
from gnuviechadminweb.model.user import Group, Role, User from gnuviechadminweb.model.user import Group, Role, User
from gnuviechadminweb.model.GVAUsers import GVAUsers from gnuviechadminweb.model.GVAUsers import GVAUsers, sha512
from gnuviechadminweb.model.menu import Menu from gnuviechadminweb.model.menu import Menu

View file

@ -5,7 +5,12 @@ class Menu(object):
('Main page', 'gva', 'index', None), ('Main page', 'gva', 'index', None),
('Login', 'login', 'login', []), ('Login', 'login', 'login', []),
('Logout', 'login', 'logout', ['*']), ('Logout', 'login', 'logout', ['*']),
('Admin', 'gva', 'index', ['admin']) ('Manage clients', 'clients', 'index', ['admin']),
('Update Profile', 'client', 'changes', ['client']),
('System accounts', 'sysuser', 'index', ['admin']),
('System account', 'sysuser', 'account', ['client']),
('Mail accounts', 'mailaccount', 'index', ['admin', 'sysuser']),
('Change password', 'gva', 'password', ['*'])
] ]
@classmethod @classmethod
@ -30,7 +35,3 @@ class Menu(object):
self.title = title self.title = title
self.controller = controller self.controller = controller
self.action = action self.action = action

View file

@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
<%inherit file="site.mako" />
<h1>Change your password</h1>
${h.form(h.url(action='updatepassword'), method='post')}
Old password: ${h.password_field('oldpassword')}
New password: ${h.password_field('password')}
Confirm new password: ${h.password_field('confirm')}
${h.submit('Change password')}
${h.end_form()}
<%def name="headlines()">
<title>Change your password</title>
</%def>

View file

@ -6,8 +6,7 @@ from pylons import config
from gnuviechadminweb.config.environment import load_environment from gnuviechadminweb.config.environment import load_environment
from gnuviechadminweb.model import meta, User, Group, Role from gnuviechadminweb.model import meta, User, Group, Role
from gnuviechadminweb.model.GVAUsers import GVAUsers from gnuviechadminweb.model.GVAUsers import GVAUsers, sha512
from authkit.users import md5
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -20,7 +19,7 @@ def setup_config(command, filename, section, vars):
meta.metadata.create_all(bind=meta.engine) meta.metadata.create_all(bind=meta.engine)
log.info("Creating default admin user, role and group") log.info("Creating default admin user, role and group")
users = GVAUsers('gnuviechadminweb.model:meta', md5) users = GVAUsers('gnuviechadminweb.model:meta', sha512)
users.role_create("admin") users.role_create("admin")
users.group_create("administrators") users.group_create("administrators")