Archived
1
0
Fork 0

Merge branch '31-admin-user-management' into dev

This commit is contained in:
Henrik Hautakoski 2022-08-09 13:54:08 +02:00
commit 3edb12817a
7 changed files with 294 additions and 37 deletions

View file

@ -11,8 +11,36 @@
display: none; display: none;
} }
// Contextual colors
// ----------------------------------
&-default {
color: white;
background-color: $gray-400;
}
&-primary { &-primary {
color: white; color: white;
background-color: $primary; background-color: $primary;
} }
&-info {
color: white;
background-color: $info;
}
&-success {
color: white;
background-color: $success;
}
&-warning {
color: black;
background-color: $warning;
}
&-danger {
color: white;
background-color: $danger;
}
} }

View file

@ -62,8 +62,20 @@ router:
pattern: '/admin' pattern: '/admin'
path: backend::user::index path: backend::user::index
backend-user-list: backend-user-list:
pattern: '/admin/user/list/{page:([0-9]+)}' pattern: '/admin/user/list{page:/?([0-9]+)?}'
path: backend::user::index path: backend::user::index
backend-user-new:
pattern: '/admin/user/new'
path: backend::user::new
backend-user-edit:
pattern: '/admin/user/{id:([0-9]+)}'
path: backend::user::edit
backend-user-status:
pattern: '/admin/user/{id:([0-9]+)}/{type}'
path:
module: backend
controller: user
action: status
backend-log: backend-log:
pattern: '/admin/log{page:/?([0-9]+)?}' pattern: '/admin/log{page:/?([0-9]+)?}'
path: backend::log::index path: backend::log::index

View file

@ -2,7 +2,8 @@
namespace App\Controller\Backend; namespace App\Controller\Backend;
use App\Model\Data\User; use App\Model\Data\User,
App\Form\UserSettings as UserSettingsForm;
class UserController extends \Phalcon\Mvc\Controller class UserController extends \Phalcon\Mvc\Controller
{ {
@ -21,4 +22,79 @@ class UserController extends \Phalcon\Mvc\Controller
$this->view->pagination_url = '/admin/user/list/'; $this->view->pagination_url = '/admin/user/list/';
$this->view->page = $paginator->paginate(); $this->view->page = $paginator->paginate();
} }
public function newAction()
{
$user = new User;
$form = new UserSettingsForm($user, true);
if ($this->request->isPost()) {
$data = $this->request->getPost();
if ($form->isValid($data)) {
$new_pw = $form->getValue('passwordNew');
if (strlen($new_pw) > 0) {
$hash = $this->security->hash($new_pw, 12);
$user->setPassword($hash);
}
$form->initialize();
$this->flash->message('success', 'User created!');
$this->response->redirect(['for' => 'backend-user-list']);
return;
}
$this->flash->message('error', 'Could not create user');
}
$this->view->user = $user;
$this->view->form = $form;
$this->view->pick('user/form');
}
public function editAction($id)
{
$user = User::findFirstById($id);
$form = new UserSettingsForm($user, true);
if ($this->request->isPost()) {
$data = $this->request->getPost();
if ($form->isValid($data)) {
$new_pw = $form->getValue('passwordNew');
if (strlen($new_pw) > 0) {
$hash = $this->security->hash($new_pw, 12);
$user->setPassword($hash);
}
$user->save();
$form->initialize();
$this->flash->message('success', 'User saved!');
} else {
$this->flash->message('error', 'Could not save user');
}
}
$this->view->user = $user;
$this->view->form = $form;
$this->view->pick('user/form');
}
public function statusAction($id, $type)
{
$user = User::findFirstById($id);
$user->setStatus(ucfirst($type));
$user->save();
$status = $user->getStatus();
// Bit of a hack to convert "active" to verb.
if ($status === User::STATUS_ACTIVE) {
$status = 'Activated';
}
$this->flash->success('The account was: ' . $status);
$this->response->redirect('/admin');
}
} }

View file

@ -35,23 +35,41 @@ use Phalcon\Validation\Validator\Callback as CallbackValidator,
class UserSettings extends FormBase class UserSettings extends FormBase
{ {
/**
* @var bool
*/
protected $_admin;
public function __construct(UserModel $user = null, bool $admin = false)
{
$this->_admin = $admin;
parent::__construct($user);
}
public function initialize() public function initialize()
{ {
$entity = $this->getEntity();
$this->setValidation(new \Phalcon\Validation()); $this->setValidation(new \Phalcon\Validation());
// Id // Id
$id = new Text('id', array( if ($entity && $entity->getId()) {
'class' => 'form-control',
'readonly' => '',
'disabled' => 'disabled',
));
$id->addValidator(new IdenticalValidator([
'accepted' => $this->getEntity()->getId(),
'allowEmpty' => true
]));
$id->setLabel('ID'); $id = new Text('id', array(
$this->add($id); 'class' => 'form-control',
'readonly' => '',
'disabled' => 'disabled',
));
$id->addValidator(new IdenticalValidator([
'accepted' => $entity->getId(),
'allowEmpty' => true
]));
$id->setLabel('ID');
$this->add($id);
}
// Username // Username
$username = new Text('username', array( $username = new Text('username', array(
@ -61,16 +79,20 @@ class UserSettings extends FormBase
$username->setLabel('Username'); $username->setLabel('Username');
$username->addValidator(new AlnumValidator()); $validator_options = array(
$validator = new UniquenessValidator(array(
'model' => new UserModel(), 'model' => new UserModel(),
'message' => 'The username already exists.', 'message' => 'The :field already exists.',
'attribute' => 'username', 'attribute' => 'username',
'except' => [ $this->getEntity()->getUsername() ] );
));
$username->addValidator($validator); if ($entity && strlen($entity->getUsername())) {
$validator_options['except'] = [ $entity->getUsername() ];
}
$username->addValidators([
new AlnumValidator(),
new UniquenessValidator($validator_options)
]);
$this->add($username); $this->add($username);
@ -89,27 +111,48 @@ class UserSettings extends FormBase
$this->add($name); $this->add($name);
// Email // Email
$email = new Text('email', array( if ($this->_admin === false && $entity) {
'class' => 'form-control', $email = new Text('email', array(
'placeholder' => 'Email', 'class' => 'form-control',
'readonly' => '', 'placeholder' => 'Email',
'disabled' => 'disabled', 'readonly' => '',
)); 'disabled' => 'disabled',
));
$email->addValidator(new IdenticalValidator([ $email->addValidator(new IdenticalValidator([
'accepted' => $this->getEntity()->getEmail(), 'accepted' => $entity->getEmail(),
'allowEmpty' => true 'allowEmpty' => true
])); ]));
} else {
$email = new Text('email', array(
'class' => 'form-control',
'placeholder' => 'Email',
));
$validator_options = [
'model' => new UserModel(),
'message' => 'The :field already exists.',
'attribute' => 'email',
];
if ($entity && strlen($entity->getEmail())) {
$validator_options['except'] = [ $entity->getEmail() ];
}
$email->addValidators([
new EmailValidator(),
new UniquenessValidator($validator_options)
]);
}
$email->setLabel('Email'); $email->setLabel('Email');
$this->add($email); $this->add($email);
// Passwords // Passwords
$this->_passwords(); $this->_passwords();
// Submit // Submit
$submit = new Submit('Save', array('class' => 'button button-default')); $submit = new Submit($entity && $entity->getId() ? 'Save' : 'Create', array('class' => 'button button-default'));
$this->add($submit); $this->add($submit);
} }
@ -118,10 +161,10 @@ class UserSettings extends FormBase
*/ */
protected function _passwords() protected function _passwords()
{ {
$current_pw = $this->getEntity()->getPassword(); $entity = $this->getEntity();
// Current // Current
if (strlen($current_pw) > 0) { if ($this->_admin === false && $entity && strlen($entity->getPassword()) > 0) {
$current = new Password('passwordCurrent', array( $current = new Password('passwordCurrent', array(
'class' => 'form-control', 'class' => 'form-control',
)); ));
@ -146,7 +189,7 @@ class UserSettings extends FormBase
// Validation // Validation
$validation = $this->getValidation(); $validation = $this->getValidation();
if (strlen($current_pw) > 0) { if ($this->_admin === false && $entity && strlen($entity->getPassword()) > 0) {
$validation->add('passwordCurrent', new CallbackValidator([ $validation->add('passwordCurrent', new CallbackValidator([
'callback' => function($data) { 'callback' => function($data) {
$new_pw = $data['passwordNew']; $new_pw = $data['passwordNew'];

View file

@ -255,6 +255,16 @@ class User extends Base
return $this; return $this;
} }
/**
* Returns true if this is a active user.
*
* @return bool
*/
public function isActive()
{
return $this->status == self::STATUS_ACTIVE;
}
/** /**
* @return mixed * @return mixed
*/ */

View file

@ -0,0 +1,74 @@
<div class="clearfix">
<h2 class="float-start">
{% if (user.getId()) %} Edit user #{{ user.getId() }} {% else %} Create user {% endif %}
</h2>
{% if (user.getId() and user.isActive() === false) %}
<p class="float-end badge badge-danger">{{ user.getStatus() }}</p>
{% endif %}
</div>
<form class="form-horizontal" method="post" action="">
<div class="row mb-3">
{% if (form.has('id')) %}
{{ form.renderDecorated('username', [ 'length': 7 ]) }}
{{ form.renderDecorated('id', [ 'length': 2, 'label-length' : 1 ]) }}
{% else %}
{{ form.renderDecorated('username') }}
{% endif %}
</div>
<div class="row mb-3">
{{ form.renderDecorated('name') }}
</div>
<div class="row mb-3">
{{ form.renderDecorated('email') }}
</div>
<div class="row mb-3">
<div class="offset-sm-2 col-sm-10">
<h4>Password</h4>
</div>
</div>
<div class="row mb-3">
{{ form.renderDecorated('passwordNew') }}
</div>
<div class="row mb-3">
{{ form.renderDecorated('passwordConfirm') }}
</div>
<div class="row mb-3">
<div class="offset-sm-2 col-sm-10">
<hr />
{% if (form.has('Save')) %}
{{ form.render('Save') }}
{% else %}
{{ form.render('Create') }}
{% endif %}
{% if (user.getId()) %}
{% set actions = [ 'Activate': 'Active', 'Suspend': 'Suspended', 'Delete': 'Deleted' ] %}
<div class="float-end">
{% for label, status in actions %}
{% if (user.status != status) %}
<a class="button button-{{ status == 'Active' ? 'success' : 'danger' }}"
href="{{ url(['for': 'backend-user-status', 'type': status, 'id': user.getId() ]) }}">
{{ label }}
</a>
{% endif %}
{% endfor %}
</div>
{% endif %}
</div>
</div>
</form>

View file

@ -1,10 +1,19 @@
<h1>Users</h1> <div class="clearfix">
<h1 class="float-start">Users</h1>
<div class="float-end">
<a class="button button-large button-primary" href="{{ url(['for': 'backend-user-new' ]) }}">
{{ icon('solid/plus') }} New
</a>
</div>
</div>
<table class="table table-striped table-hover"> <table class="table table-striped table-hover">
<thead> <thead>
<tr> <tr>
<th>&nbsp;</th>
<th>#</th> <th>#</th>
<th>Username</th> <th>Username</th>
<th>Name</th> <th>Name</th>
@ -17,11 +26,16 @@
<tbody> <tbody>
{% for item in page.items %} {% for item in page.items %}
<tr> <tr>
<td>
<a title="Edit" href="{{ url(['for': 'backend-user-edit', 'id': item.id ]) }}">
{{ icon('solid/pen') }}
</a>
</td>
<td>{{ item.id }}</td> <td>{{ item.id }}</td>
<td>{{ item.username }}</td> <td>{{ item.username }}</td>
<td>{{ item.name }}</td> <td>{{ item.name }}</td>
<td>{{ item.email }}</td> <td>{{ item.email }}</td>
<td>{{ item.type }}</td> <td>{{ item.type | capitalize }}</td>
<td>{{ item.status }}</td> <td>{{ item.status }}</td>
</tr> </tr>
{% endfor %} {% endfor %}