Browse Source

editing single user works

php2python
Holger Frey 7 years ago
parent
commit
5e5fe19af3
  1. 2
      .gitignore
  2. 6
      ordr2/events.py
  3. 7
      ordr2/models/user.py
  4. 11
      ordr2/schemas/account.py
  5. 59
      ordr2/views/admin.py

2
.gitignore vendored

@ -1,5 +1,7 @@
# ignore sqlite database # ignore sqlite database
ordr2.sqlite ordr2.sqlite
# ignor pyramid_mailer.debug folder
mail/
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/

6
ordr2/events.py

@ -19,12 +19,12 @@ class UserNotification(object):
class AccountActivation(UserNotification): class AccountActivation(UserNotification):
subject='[ordr] Your account was activated', subject='[ordr] Your account was activated'
template = 'ordr2:templates/emails/activation.jinja2' template = 'ordr2:templates/emails/activation.jinja2'
class PasswordReset(UserNotification): class PasswordReset(UserNotification):
subject='[ordr] Password Reset', subject='[ordr] Password Reset'
template = 'ordr2:templates/emails/password_reset.jinja2' template = 'ordr2:templates/emails/password_reset.jinja2'
@ -50,7 +50,7 @@ def notify_user(event):
event.request event.request
) )
message = Message( message = Message(
subject=event.subject subject=event.subject,
sender=event.request.registry.settings['mail.default_sender'], sender=event.request.registry.settings['mail.default_sender'],
recipients=[event.user.email], recipients=[event.user.email],
html=body html=body

7
ordr2/models/user.py

@ -1,5 +1,6 @@
import bcrypt import bcrypt
import enum import enum
import uuid
from collections import namedtuple from collections import namedtuple
from datetime import datetime from datetime import datetime
@ -40,6 +41,7 @@ class User(Base):
email = Column(Text, nullable=False, unique=True) email = Column(Text, nullable=False, unique=True)
password_hash = Column(Text, nullable=False) password_hash = Column(Text, nullable=False)
role = Column(Enum(Role), nullable=False) role = Column(Enum(Role), nullable=False)
password_reset = Column(Text, nullable=False, default='')
date_created = Column(Date, nullable=False, default=datetime.utcnow) date_created = Column(Date, nullable=False, default=datetime.utcnow)
@property @property
@ -75,6 +77,11 @@ class User(Base):
return bcrypt.checkpw(password.encode('utf8'), expected_hash) return bcrypt.checkpw(password.encode('utf8'), expected_hash)
return False return False
def generate_password_token(self):
token = uuid.uuid4()
self.password_reset = token.hex
return token.hex
def __str__(self): def __str__(self):
''' string representation ''' ''' string representation '''
return '{!s}'.format(self.user_name) return '{!s}'.format(self.user_name)

11
ordr2/schemas/account.py

@ -81,9 +81,14 @@ class UserSchema(CSRFSchema):
def as_form(cls, request, **override): def as_form(cls, request, **override):
settings = { settings = {
'buttons': ( 'buttons': (
deform.Button('Save changes'), deform.Button(name='save', title='Save changes'),
deform.Button('Reset password', css_class='btn-danger'), deform.Button(
deform.Button('Cancel') name='delete',
title='Delete user',
css_class='btn-danger'
),
deform.Button(name='reset', title='Reset password'),
deform.Button(name='cancel', title='Cancel')
), ),
'css_class': 'form-horizontal', 'css_class': 'form-horizontal',
} }

59
ordr2/views/admin.py

@ -5,6 +5,7 @@ from pyramid.renderers import render
from pyramid.security import remember, forget from pyramid.security import remember, forget
from pyramid.view import view_config from pyramid.view import view_config
from ordr2.events import AccountActivation, PasswordReset
from ordr2.models import User, Role from ordr2.models import User, Role
from ordr2.schemas.account import UserSchema from ordr2.schemas.account import UserSchema
@ -66,6 +67,7 @@ def change_column_view(context, request):
renderer='ordr2:templates/admin/user_edit.jinja2' renderer='ordr2:templates/admin/user_edit.jinja2'
) )
def user_account_form(context, request): def user_account_form(context, request):
''' display the user edit form '''
form = UserSchema.as_form(request) form = UserSchema.as_form(request)
form_data = { form_data = {
'user_name': context.model.user_name, 'user_name': context.model.user_name,
@ -79,34 +81,55 @@ def user_account_form(context, request):
@view_config( @view_config(
context='ordr2:resources.Account', context='ordr2:resources.UserAccount',
name='settingsx', permission='edit',
permission='settings',
request_method='POST', request_method='POST',
renderer='ordr2:templates/account/settings.jinja2' renderer='ordr2:templates/admin/user_edit.jinja2'
) )
def settingsx_form_processing(context, request): def user_account_form_processing(context, request):
''' display the user settings form ''' ''' process the user edit form '''
form = SettingsSchema.as_form(request) form = UserSchema.as_form(request)
data = request.POST.items() data = request.POST.items()
if 'delete' in request.POST:
return HTTPFound(request.resource_url(context, 'delete'))
elif 'save' in request.POST:
try: try:
appstruct = form.validate(data) appstruct = form.validate(data)
except deform.ValidationFailure as e: except deform.ValidationFailure as e:
return {'form': form} return {'form': form}
# form validation sucessful, change settings # form validation sucessful, change settings
request.user.first_name = appstruct['general']['first_name'] was_active = context.model.is_active
request.user.last_name = appstruct['general']['last_name'] context.model.first_name = appstruct['first_name']
request.user.email = appstruct['general']['email'] context.model.last_name = appstruct['last_name']
if appstruct['change_password']['new_password']: context.model.email = appstruct['email']
request.user.set_password(appstruct['change_password']['new_password']) context.model.role = Role[appstruct['role']]
if len(appstruct['change_password']['new_password']) < 8:
request.flash( if not was_active and context.model.is_active:
'warning', # user account was activated, notify user
'You should really consider using a longer password.' event = AccountActivation(request, context.model)
request.registry.notify(event)
text = 'An activation email was sent to <em>{}</em>'.format(
appstruct['email']
) )
else:
text = ''
request.flash('success', 'Your account information has been updated.') msg = 'User account <em>{}</em> updated.'.format(
context.model.user_name
)
request.flash('success', msg, text)
return {'form': form} elif 'reset' in request.POST:
token = context.model.generate_password_token()
event = PasswordReset(request, context.model, token)
request.registry.notify(event)
msg = 'Password reset mail sent to {}.'.format(context.model.email)
request.flash('success', msg)
elif 'delete' in request.POST:
return HTTPFound(context, 'delete')
return HTTPFound(context.__parent__.url())