Merge branch '31-admin-user-management' into dev
This commit is contained in:
commit
3edb12817a
7 changed files with 294 additions and 37 deletions
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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'];
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
74
app/views/backend/user/form.volt
Normal file
74
app/views/backend/user/form.volt
Normal 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>
|
||||||
|
|
@ -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> </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 %}
|
||||||
|
|
|
||||||
Reference in a new issue