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. 71
      ordr2/views/admin.py

2
.gitignore vendored

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

6
ordr2/events.py

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

7
ordr2/models/user.py

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

11
ordr2/schemas/account.py

@ -81,9 +81,14 @@ class UserSchema(CSRFSchema): @@ -81,9 +81,14 @@ class UserSchema(CSRFSchema):
def as_form(cls, request, **override):
settings = {
'buttons': (
deform.Button('Save changes'),
deform.Button('Reset password', css_class='btn-danger'),
deform.Button('Cancel')
deform.Button(name='save', title='Save changes'),
deform.Button(
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',
}

71
ordr2/views/admin.py

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