Browse Source

* use sha512 passwords

* more robust SQLAlchemy session handling code
 * implemented password change mechanism
master
Jan Dittberner 12 years ago
parent
commit
949e699e25
7 changed files with 99 additions and 28 deletions
  1. +1
    -1
      development.ini
  2. +25
    -0
      gnuviechadminweb/controllers/gva.py
  3. +52
    -18
      gnuviechadminweb/model/GVAUsers.py
  4. +1
    -1
      gnuviechadminweb/model/__init__.py
  5. +6
    -5
      gnuviechadminweb/model/menu.py
  6. +12
    -0
      gnuviechadminweb/templates/chpassword.mako
  7. +2
    -3
      gnuviechadminweb/websetup.py

+ 1
- 1
development.ini View File

@@ -38,7 +38,7 @@ sqlalchemy.url = sqlite:///%(here)s/gvaweb.sqlite
authkit.setup.method = form, cookie
authkit.form.authenticate.user.type = gnuviechadminweb.model:GVAUsers
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.signoutpath = /login/logout



+ 25
- 0
gnuviechadminweb/controllers/gva.py View File

@@ -2,6 +2,8 @@
import logging

from gnuviechadminweb.lib.base import *
from authkit.permissions import ValidAuthKitUser
from authkit.authorize.pylons_adaptors import authorize

log = logging.getLogger(__name__)

@@ -9,3 +11,26 @@ class GvaController(BaseController):
def index(self):
# Return a rendered template
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')

+ 52
- 18
gnuviechadminweb/model/GVAUsers.py View File

@@ -1,3 +1,4 @@

# -*- coding: utf-8 -*-
from authkit.users import Users
from gnuviechadminweb.model.user import Group, Role, User
@@ -6,33 +7,33 @@ import logging

log = logging.getLogger(__name__)

def needsConnection(func):
def wrapper(*__args, **__kw):
from sqlalchemy.orm import create_session
engine = __args[0].meta.engine
conn = engine.contextual_connect()
if conn.closed:
conn = engine.connect()
__args[0].session = create_session(bind=conn)
try:
return func(*__args, **__kw)
finally:
conn.close()
else:
__args[0].session = create_session(bind=conn)
return func(*__args, **__kw)
def initializedSession(func):
def wrapper(*__args, **__kwargs):
meta = __args[0].meta
conn = meta.engine.connect()
meta.Session.configure(bind=conn)
try:
return func(*__args, **__kwargs)
finally:
meta.Session.remove()
conn.close()
return wrapper

def sha512(password, secret = ''):
import hashlib
m = hashlib.sha512()
m.update(password)
m.update(secret)
return m.hexdigest()

class GVAUsers(Users):
def __init__(self, data, encrypt = None):
Users.__init__(self, data, encrypt)
log.debug("in __init__")
self.meta = eval_import(self.data)
self.session = self.meta.Session

@needsConnection
def _getSession(self):
return self.session
return self.meta.Session

def _get_group(self, groupname):
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()

# Create Methods
@initializedSession
def user_create(self, username, password, group=None):
n_user = User()
n_user.name = username
@@ -53,12 +55,14 @@ class GVAUsers(Users):
self._getSession().save(n_user)
self._getSession().commit()

@initializedSession
def role_create(self, role):
n_role = Role()
n_role.name = role
self._getSession().save(n_role)
self._getSession().commit()
@initializedSession
def group_create(self, group):
n_group = Group()
n_group.name = group
@@ -66,19 +70,23 @@ class GVAUsers(Users):
self._getSession().commit()

# Delete Methods
@initializedSession
def user_delete(self, username):
self._getSession().delete(self._get_user(username))
self._getSession().commit()
@initializedSession
def role_delete(self, role):
self._getSession().delete(self._get_role(role))
self._getSession().commit()
@initializedSession
def group_delete(self, group):
self._getSession().delete(self._get_group())
self._getSession().commit()
# Delete Cascade Methods
@initializedSession
def role_delete_cascade(self, role):
n_role = self._get_role(role)
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().commit()
@initializedSession
def group_delete_cascade(self, group):
n_group = self._get_group(group)
self._getSession().delete(self._getSession().query(User).filter_by(
@@ -94,32 +103,39 @@ class GVAUsers(Users):
self._getSession().commit()

# Existence Methods
@initializedSession
def user_exists(self, username):
return self._getSession().query(User).filter_by(
name=username).count() == 1

@initializedSession
def role_exists(self, role):
return self._getSession().query(Role).filter_by(
name=role).count() == 1

@initializedSession
def group_exists(self, group):
return self._getSession().query(Group).filter_by(
name=group).count() == 1

# List Methods
@initializedSession
def list_roles(self):
return [role.name.lower() for role in self._getSession().query(
Role).all()]
@initializedSession
def list_users(self):
return [user.name.lower() for user in self._getSession().query(
User).all()]

@initializedSession
def list_groups(self):
return [group.name.lower() for group in self._getSession().query(
Group).all()]

# User Methods
@initializedSession
def user(self, username):
user = self._get_user(username)
roles = [role.name.lower() for role in user.roles]
@@ -131,40 +147,48 @@ class GVAUsers(Users):
'roles' : roles
}

@initializedSession
def user_roles(self, username):
user = self._get_user(username)
roles = [role.name.lower() for role in user.roles]
roles.sort()
return roles

@initializedSession
def user_group(self, username):
user = self._get_user(username)
return None if user.group is None else user.group.name

@initializedSession
def user_password(self, username):
user = self._get_user(username)
return user.password

@initializedSession
def user_has_role(self, username, role):
user = self._get_user(username)
return role in [role.name for role in user.roles]

@initializedSession
def user_has_group(self, username, group):
user = self._get_user(username)
return (group is None and user.group is None) or \
(group is not None and user.group is not None and \
group == user.group.name)

@initializedSession
def user_has_password(self, username, password):
user = self._get_user(username)
return user.password == self.encrypt(password)

@initializedSession
def user_set_username(self, username, new_username):
user = self._get_user(username)
user.name = new_username
self._getSession().update(user)
self._getSession().commit()

@initializedSession
def user_set_group(self, username, group, add_if_necessary=False):
if add_if_necessary and self._getSession().query(Group).filter_by(
name=group).count() == 0:
@@ -175,6 +199,7 @@ class GVAUsers(Users):
self._getSession().update(user)
self._getSession().commit()
@initializedSession
def user_add_role(self, username, role, add_if_necessary=False):
if add_if_necessary and self._getSession().query(Role).filter_by(
name=role).count() == 0:
@@ -186,6 +211,7 @@ class GVAUsers(Users):
self._getSession().update(user)
self._getSession().commit()

@initializedSession
def user_remove_role(self, username, role):
roleobj = self._get_role(role)
user = self._get_user(username)
@@ -193,8 +219,16 @@ class GVAUsers(Users):
del user.roles[roleobj.id]
self._getSession().commit()

@initializedSession
def user_remove_group(self, username):
user = self._get_user(username)
user.group = None
self._getSession().update(user)
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()

+ 1
- 1
gnuviechadminweb/model/__init__.py View File

@@ -12,5 +12,5 @@ def init_model(engine):
meta.Session = orm.scoped_session(sm)

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

+ 6
- 5
gnuviechadminweb/model/menu.py View File

@@ -5,7 +5,12 @@ class Menu(object):
('Main page', 'gva', 'index', None),
('Login', 'login', 'login', []),
('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
@@ -30,7 +35,3 @@ class Menu(object):
self.title = title
self.controller = controller
self.action = action


+ 12
- 0
gnuviechadminweb/templates/chpassword.mako 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>

+ 2
- 3
gnuviechadminweb/websetup.py View File

@@ -6,8 +6,7 @@ from pylons import config

from gnuviechadminweb.config.environment import load_environment
from gnuviechadminweb.model import meta, User, Group, Role
from gnuviechadminweb.model.GVAUsers import GVAUsers
from authkit.users import md5
from gnuviechadminweb.model.GVAUsers import GVAUsers, sha512

log = logging.getLogger(__name__)

@@ -20,7 +19,7 @@ def setup_config(command, filename, section, vars):
meta.metadata.create_all(bind=meta.engine)

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.group_create("administrators")



Loading…
Cancel
Save