diff --git a/development.ini b/development.ini index 0eb1c99..3da9c3c 100644 --- a/development.ini +++ b/development.ini @@ -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 diff --git a/gnuviechadminweb/controllers/gva.py b/gnuviechadminweb/controllers/gva.py index f31d46f..d1fd8f2 100644 --- a/gnuviechadminweb/controllers/gva.py +++ b/gnuviechadminweb/controllers/gva.py @@ -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') diff --git a/gnuviechadminweb/model/GVAUsers.py b/gnuviechadminweb/model/GVAUsers.py index 1e4f558..2fe3491 100644 --- a/gnuviechadminweb/model/GVAUsers.py +++ b/gnuviechadminweb/model/GVAUsers.py @@ -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() diff --git a/gnuviechadminweb/model/__init__.py b/gnuviechadminweb/model/__init__.py index c05d1a1..040de90 100644 --- a/gnuviechadminweb/model/__init__.py +++ b/gnuviechadminweb/model/__init__.py @@ -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 diff --git a/gnuviechadminweb/model/menu.py b/gnuviechadminweb/model/menu.py index 557df55..7f660c0 100644 --- a/gnuviechadminweb/model/menu.py +++ b/gnuviechadminweb/model/menu.py @@ -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 - - - - diff --git a/gnuviechadminweb/templates/chpassword.mako b/gnuviechadminweb/templates/chpassword.mako new file mode 100644 index 0000000..3d79850 --- /dev/null +++ b/gnuviechadminweb/templates/chpassword.mako @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +<%inherit file="site.mako" /> +

Change your password

+${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()"> + Change your password + \ No newline at end of file diff --git a/gnuviechadminweb/websetup.py b/gnuviechadminweb/websetup.py index 1ee2fe5..0008a36 100644 --- a/gnuviechadminweb/websetup.py +++ b/gnuviechadminweb/websetup.py @@ -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")