Compare commits
34 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 50464bce0d | |||
| a757e95277 | |||
| bf940f9523 | |||
| 6dc1d0fb87 | |||
| 0634db6d0c | |||
| 24edb5cb59 | |||
| 4ac770f733 | |||
| 69fd7a6e19 | |||
| 6439a83edb | |||
| be4950ff88 | |||
| a7a59b690a | |||
| dd140ccd8a | |||
| d2e7d6b670 | |||
| 8c9455a2d5 | |||
| 151daa8529 | |||
| d3e52269cd | |||
| 8048b3fda8 | |||
| 4ff351d39d | |||
| 1b57749a91 | |||
| c07423f600 | |||
| 7315885877 | |||
| ff15ee697c | |||
| 2e98191d56 | |||
| 0f5f42ca92 | |||
| 14eb4a9137 | |||
| e47aa5188e | |||
| 5b9d64c09e | |||
| ad2952f9fc | |||
| 8d74cb2f06 | |||
| 6aeaf74a2f | |||
| e56c8f37ea | |||
| d7af32a1d7 | |||
| ee5c7719cb | |||
| fa28394a83 |
53 changed files with 398 additions and 193 deletions
|
|
@ -30,7 +30,7 @@ session:
|
||||||
statsKey: _httpcb_sess_idx
|
statsKey: _httpcb_sess_idx
|
||||||
prefix: _httpcb_sess_
|
prefix: _httpcb_sess_
|
||||||
|
|
||||||
#sendgrid
|
#sendgrid:
|
||||||
#key: value
|
#key: value
|
||||||
|
|
||||||
# OAuth
|
# OAuth
|
||||||
|
|
|
||||||
|
|
@ -4,58 +4,61 @@ router:
|
||||||
routes:
|
routes:
|
||||||
home-route:
|
home-route:
|
||||||
pattern: '/'
|
pattern: '/'
|
||||||
path:
|
path: Index::index
|
||||||
controller: index
|
|
||||||
action: index
|
|
||||||
about-route:
|
about-route:
|
||||||
pattern: '/about'
|
pattern: '/about'
|
||||||
path:
|
path: Index::about
|
||||||
controller: index
|
|
||||||
action: about
|
# Callbacks
|
||||||
|
|
||||||
|
cb-list:
|
||||||
|
pattern: '/callback/list'
|
||||||
|
path: Callback::list
|
||||||
|
cb-new:
|
||||||
|
pattern: '/callback/new'
|
||||||
|
path: Callback::new
|
||||||
cb-created:
|
cb-created:
|
||||||
pattern: '/callback/created/{id}'
|
pattern: '/callback/created/{id}'
|
||||||
path:
|
path: Callback::created
|
||||||
controller: callback
|
cb-show:
|
||||||
action: created
|
pattern: '/callback/show/{id}'
|
||||||
|
path: Callback::show
|
||||||
cb-endpoint:
|
cb-endpoint:
|
||||||
pattern: '/cb/{id}/:params'
|
pattern: '/cb/{id}/:params'
|
||||||
path:
|
path: Api::endpoint
|
||||||
controller: api
|
|
||||||
action: endpoint
|
# login
|
||||||
|
|
||||||
login:
|
login:
|
||||||
pattern: '/login'
|
pattern: '/login'
|
||||||
path:
|
path: Auth::index
|
||||||
controller: auth
|
|
||||||
action: index
|
|
||||||
logout:
|
logout:
|
||||||
pattern: '/logout'
|
pattern: '/logout'
|
||||||
path:
|
path: Auth::logout
|
||||||
controller: auth
|
|
||||||
action: logout
|
|
||||||
oauth:
|
oauth:
|
||||||
pattern: '/login/{strategy:([a-z]+)}/:params'
|
pattern: '/login/{strategy:([a-z]+)}/:params'
|
||||||
path:
|
path: Auth::oauth
|
||||||
controller: auth
|
|
||||||
action: oauth
|
|
||||||
oauth-disconnect:
|
oauth-disconnect:
|
||||||
pattern: '/oauth/{provider:([a-z]+)}/disconnect'
|
pattern: '/oauth/{provider:([a-z]+)}/disconnect'
|
||||||
path: 'User::oauthdisconnect'
|
path: 'User::oauthdisconnect'
|
||||||
oauth-disconnect-confirm:
|
oauth-disconnect-confirm:
|
||||||
pattern: '/oauth/{provider:([a-z]+)}/disconnect/{confirm}'
|
pattern: '/oauth/{provider:([a-z]+)}/disconnect/{confirm}'
|
||||||
path: 'User::oauthdisconnect'
|
path: 'User::oauthdisconnect'
|
||||||
|
|
||||||
|
# User
|
||||||
|
|
||||||
user-register:
|
user-register:
|
||||||
pattern: '/register'
|
pattern: '/register'
|
||||||
path: Auth::register
|
path: Auth::register
|
||||||
user-settings:
|
user-settings:
|
||||||
pattern: '/settings'
|
pattern: '/settings'
|
||||||
path:
|
path: User::settings
|
||||||
controller: user
|
user-activity-log:
|
||||||
action: settings
|
pattern: '/user/activity'
|
||||||
|
path: User::activity
|
||||||
activation-link:
|
activation-link:
|
||||||
pattern: '/activate/{link}'
|
pattern: '/activate/{link}'
|
||||||
path:
|
path: Api::activationlink
|
||||||
controller: api
|
|
||||||
action: activationlink
|
|
||||||
|
|
||||||
# Backend
|
# Backend
|
||||||
backend-home:
|
backend-home:
|
||||||
|
|
@ -70,12 +73,15 @@ router:
|
||||||
backend-user-edit:
|
backend-user-edit:
|
||||||
pattern: '/admin/user/{id:([0-9]+)}'
|
pattern: '/admin/user/{id:([0-9]+)}'
|
||||||
path: backend::user::edit
|
path: backend::user::edit
|
||||||
|
backend-user-impersonate:
|
||||||
|
pattern: '/admin/impersonate/{id:([0-9]+)}'
|
||||||
|
path: backend::user::impersonate
|
||||||
|
backend-user-activation-email:
|
||||||
|
pattern: '/admin/user/{id:([0-9]+)}/activation'
|
||||||
|
path: backend::user::activation-email
|
||||||
backend-user-status:
|
backend-user-status:
|
||||||
pattern: '/admin/user/{id:([0-9]+)}/{type}'
|
pattern: '/admin/user/{id:([0-9]+)}/status/{type}'
|
||||||
path:
|
path: backend::user::status
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use App\Controller\ControllerBase,
|
||||||
App\Model\Data\Callback as CallbackModel,
|
App\Model\Data\Callback as CallbackModel,
|
||||||
App\Model\Data\Request as RequestModel,
|
App\Model\Data\Request as RequestModel,
|
||||||
App\Model\Data\RequestMeta as RequestMetaModel,
|
App\Model\Data\RequestMeta as RequestMetaModel,
|
||||||
|
App\Model\Data\User,
|
||||||
App\Model\Data\UserActivation;
|
App\Model\Data\UserActivation;
|
||||||
|
|
||||||
class ApiController extends ControllerBase
|
class ApiController extends ControllerBase
|
||||||
|
|
@ -58,7 +59,7 @@ class ApiController extends ControllerBase
|
||||||
*/
|
*/
|
||||||
public function activationLinkAction($id)
|
public function activationLinkAction($id)
|
||||||
{
|
{
|
||||||
$link = UserActivation::findFirst(['activation_key = ?0', 'bind' => [ $id ]]);
|
$link = UserActivation::findFirst(['activation_key = ?0', 'bind' => [$id]]);
|
||||||
|
|
||||||
if ($link) {
|
if ($link) {
|
||||||
if ($link->isValid()) {
|
if ($link->isValid()) {
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,8 @@ class AuthController extends ControllerBase
|
||||||
} else {
|
} else {
|
||||||
$msg = '<ul>';
|
$msg = '<ul>';
|
||||||
|
|
||||||
foreach($form->getMessages() as $message) {
|
foreach ($form->getMessages() as $message) {
|
||||||
$msg .= '<li><strong>' . $message->getField() . '</strong> '. $message->getMessage() . '</li>';
|
$msg .= '<li><strong>' . $message->getField() . '</strong> ' . $message->getMessage() . '</li>';
|
||||||
}
|
}
|
||||||
|
|
||||||
$msg .= '</ul>';
|
$msg .= '</ul>';
|
||||||
|
|
@ -47,7 +47,7 @@ class AuthController extends ControllerBase
|
||||||
|
|
||||||
public function oauthAction($provider_name)
|
public function oauthAction($provider_name)
|
||||||
{
|
{
|
||||||
$client = $this->getDI()->get('oauth', [ $provider_name ]);
|
$client = $this->getDI()->get('oauth', [$provider_name]);
|
||||||
|
|
||||||
$code = $this->request->get('code');
|
$code = $this->request->get('code');
|
||||||
$state = $this->request->get('state');
|
$state = $this->request->get('state');
|
||||||
|
|
@ -92,7 +92,7 @@ class AuthController extends ControllerBase
|
||||||
// User is logged in.
|
// User is logged in.
|
||||||
$this->response->redirect('/');
|
$this->response->redirect('/');
|
||||||
}
|
}
|
||||||
} catch(\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
throw $e;
|
throw $e;
|
||||||
$this->flash->message('error', 'Failed to authenticate.');
|
$this->flash->message('error', 'Failed to authenticate.');
|
||||||
if ($this->auth->getUser()) {
|
if ($this->auth->getUser()) {
|
||||||
|
|
@ -118,8 +118,11 @@ class AuthController extends ControllerBase
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = new User();
|
$user = new User();
|
||||||
$user->assign($data->toArray(), null,
|
$user->assign(
|
||||||
[ 'email', 'username', 'firstname', 'lastname' ]);
|
$data->toArray(),
|
||||||
|
null,
|
||||||
|
['email', 'username', 'firstname', 'lastname']
|
||||||
|
);
|
||||||
|
|
||||||
$form = new RegistrationForm($user);
|
$form = new RegistrationForm($user);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,24 +55,23 @@ class CallbackController extends ControllerBase
|
||||||
|
|
||||||
return $this->response->redirect(array(
|
return $this->response->redirect(array(
|
||||||
'for' => 'cb-created',
|
'for' => 'cb-created',
|
||||||
'id' => $callback->getPublicId()));
|
'id' => $callback->getPublicId()
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
foreach($callback->getMessages() as $msg) {
|
foreach ($callback->getMessages() as $msg) {
|
||||||
$this->flash->error($msg);
|
$this->flash->error($msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$msg = '<ul>';
|
$msg = '<ul>';
|
||||||
|
|
||||||
foreach($form->getMessages() as $message) {
|
foreach ($form->getMessages() as $message) {
|
||||||
$msg .= '<li><strong>' . $message->getField() . '</strong>: '. $message->getMessage() . '</li>';
|
$msg .= '<li><strong>' . $message->getField() . '</strong>: ' . $message->getMessage() . '</li>';
|
||||||
}
|
}
|
||||||
|
|
||||||
$msg .= '</ul>';
|
$msg .= '</ul>';
|
||||||
$this->flash->message('error', $msg);
|
$this->flash->message('error', $msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->view->form = $form;
|
$this->view->form = $form;
|
||||||
|
|
@ -85,7 +84,6 @@ class CallbackController extends ControllerBase
|
||||||
{
|
{
|
||||||
$row = CallbackModel::get($id);
|
$row = CallbackModel::get($id);
|
||||||
if (!$row) {
|
if (!$row) {
|
||||||
|
|
||||||
}
|
}
|
||||||
$this->view->id = $id;
|
$this->view->id = $id;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ class ControllerBase extends Controller
|
||||||
protected function _forward404()
|
protected function _forward404()
|
||||||
{
|
{
|
||||||
$this->dispatcher->forward(array(
|
$this->dispatcher->forward(array(
|
||||||
|
'namespace' => 'App\\Controller',
|
||||||
'controller' => 'error',
|
'controller' => 'error',
|
||||||
'action' => 'show404'
|
'action' => 'show404'
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -15,4 +15,3 @@ class IndexController extends ControllerBase
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,11 @@ class UserController extends ControllerBase
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Send the email.
|
// Send the email.
|
||||||
$this->di->getMail()->send('Httpcb password activation',
|
$this->di->getMail()->send(
|
||||||
$user->getEmail(), $content);
|
'Httpcb password activation',
|
||||||
|
$user->getEmail(),
|
||||||
|
$content
|
||||||
|
);
|
||||||
|
|
||||||
$msg = "For security reasons. Before a password can be created "
|
$msg = "For security reasons. Before a password can be created "
|
||||||
. "a email has been sent to <strong>{$user->getEmail()}</strong> with "
|
. "a email has been sent to <strong>{$user->getEmail()}</strong> with "
|
||||||
|
|
@ -137,7 +140,7 @@ class UserController extends ControllerBase
|
||||||
|
|
||||||
$msg = '<p>You are about to unlink the last OAuth provider.'
|
$msg = '<p>You are about to unlink the last OAuth provider.'
|
||||||
. ' Your <strong>only</strong> login option will be <strong>password</strong> if you do this.</p>'
|
. ' Your <strong>only</strong> login option will be <strong>password</strong> if you do this.</p>'
|
||||||
. '<p>Are you sure? <a class="alert-link" href="' . $url .'">Yes</a></p>';
|
. '<p>Are you sure? <a class="alert-link" href="' . $url . '">Yes</a></p>';
|
||||||
|
|
||||||
$this->flash->message('warning', $msg);
|
$this->flash->message('warning', $msg);
|
||||||
$this->response->redirect('/settings');
|
$this->response->redirect('/settings');
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class UserController extends \Phalcon\Mvc\Controller
|
||||||
*/
|
*/
|
||||||
public function indexAction($page = 1)
|
public function indexAction($page = 1)
|
||||||
{
|
{
|
||||||
$paginator = User::getPaginationList($page,15);
|
$paginator = User::getPaginationList($page, 15);
|
||||||
|
|
||||||
$this->view->pagination_url = '/admin/user/list/';
|
$this->view->pagination_url = '/admin/user/list/';
|
||||||
$this->view->page = $paginator->paginate();
|
$this->view->page = $paginator->paginate();
|
||||||
|
|
@ -97,4 +97,33 @@ class UserController extends \Phalcon\Mvc\Controller
|
||||||
$this->flash->success('The account was: ' . $status);
|
$this->flash->success('The account was: ' . $status);
|
||||||
$this->response->redirect('/admin');
|
$this->response->redirect('/admin');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function activationEmailAction($id)
|
||||||
|
{
|
||||||
|
$user = User::findFirstById($id);
|
||||||
|
if ($user) {
|
||||||
|
if ($user->isSuspended()) {
|
||||||
|
$this->eventsManager->fire('auth:onSentActivation', $user);
|
||||||
|
$this->flash->success('Activation email sent to: ' . $user->email);
|
||||||
|
} else {
|
||||||
|
$this->flash->error('Only suspended users can be sent activation emails.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->flash->error('Invalid user: ' . $id);
|
||||||
|
}
|
||||||
|
$this->response->redirect('/admin');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function impersonateAction($id)
|
||||||
|
{
|
||||||
|
$user = User::findFirstById($id);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->auth->impersonate($user);
|
||||||
|
$this->response->redirect('/');
|
||||||
|
} catch (\Exception $ex) {
|
||||||
|
$this->flash->error($ex->getMessage());
|
||||||
|
$this->response->redirect('/admin');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,14 @@ use Phalcon\Forms\Form;
|
||||||
/**
|
/**
|
||||||
* Element types
|
* Element types
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Phalcon\Forms\Element\Text;
|
use Phalcon\Forms\Element\Text;
|
||||||
use Phalcon\Forms\Element\Submit;
|
use Phalcon\Forms\Element\Submit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validators
|
* Validators
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Phalcon\Validation\Validator\StringLength;
|
use Phalcon\Validation\Validator\StringLength;
|
||||||
|
|
||||||
class CallbackCreate extends Form
|
class CallbackCreate extends Form
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use Phalcon\Forms\Form;
|
||||||
/**
|
/**
|
||||||
* Element types
|
* Element types
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Phalcon\Forms\Element\Text;
|
use Phalcon\Forms\Element\Text;
|
||||||
use Phalcon\Forms\Element\Password;
|
use Phalcon\Forms\Element\Password;
|
||||||
use Phalcon\Forms\Element\Submit;
|
use Phalcon\Forms\Element\Submit;
|
||||||
|
|
@ -14,6 +15,7 @@ use Phalcon\Forms\Element\Submit;
|
||||||
/**
|
/**
|
||||||
* Validators
|
* Validators
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Phalcon\Validation\Validator\PresenceOf;
|
use Phalcon\Validation\Validator\PresenceOf;
|
||||||
use Phalcon\Validation\Validator\Email as EmailValidator;
|
use Phalcon\Validation\Validator\Email as EmailValidator;
|
||||||
use Phalcon\Validation\Validator\StringLength;
|
use Phalcon\Validation\Validator\StringLength;
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,19 @@ namespace App\Form;
|
||||||
/**
|
/**
|
||||||
* Models
|
* Models
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use App\Model\Data\User;
|
use App\Model\Data\User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Phalcon Form
|
* Phalcon Form
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Httpcb\Form as FormBase;
|
use Httpcb\Form as FormBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Element types
|
* Element types
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Phalcon\Forms\Element\Text,
|
use Phalcon\Forms\Element\Text,
|
||||||
Phalcon\Forms\Element\Password,
|
Phalcon\Forms\Element\Password,
|
||||||
Phalcon\Forms\Element\Submit;
|
Phalcon\Forms\Element\Submit;
|
||||||
|
|
@ -22,6 +25,7 @@ use Phalcon\Forms\Element\Text,
|
||||||
/**
|
/**
|
||||||
* Validators
|
* Validators
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Phalcon\Validation,
|
use Phalcon\Validation,
|
||||||
Phalcon\Validation\Validator\Callback as CallbackValidator,
|
Phalcon\Validation\Validator\Callback as CallbackValidator,
|
||||||
Phalcon\Validation\Validator\Alnum as AlnumValidator,
|
Phalcon\Validation\Validator\Alnum as AlnumValidator,
|
||||||
|
|
@ -54,7 +58,9 @@ class Registration extends FormBase
|
||||||
'messageMinimum' => 'Username must be at least :min characters long.',
|
'messageMinimum' => 'Username must be at least :min characters long.',
|
||||||
]),
|
]),
|
||||||
new CallbackValidator([
|
new CallbackValidator([
|
||||||
'callback' => function($data) { return User::findFirstByUsername($data['username']) === false; },
|
'callback' => function ($data) {
|
||||||
|
return User::findFirstByUsername($data['username']) === false;
|
||||||
|
},
|
||||||
'message' => 'The username already exists.',
|
'message' => 'The username already exists.',
|
||||||
'attribute' => 'username',
|
'attribute' => 'username',
|
||||||
])
|
])
|
||||||
|
|
@ -63,7 +69,7 @@ class Registration extends FormBase
|
||||||
$this->add($username);
|
$this->add($username);
|
||||||
|
|
||||||
// Names
|
// Names
|
||||||
foreach([ 'first-name' => 'Firstname', 'last-name' => 'Lastname' ] as $id => $label) {
|
foreach (['first-name' => 'Firstname', 'last-name' => 'Lastname'] as $id => $label) {
|
||||||
|
|
||||||
$name = new Text($id, array(
|
$name = new Text($id, array(
|
||||||
'class' => 'form-control',
|
'class' => 'form-control',
|
||||||
|
|
@ -87,7 +93,9 @@ class Registration extends FormBase
|
||||||
|
|
||||||
$email->addValidators([
|
$email->addValidators([
|
||||||
new CallbackValidator([
|
new CallbackValidator([
|
||||||
'callback' => function($data) { return User::findFirstByEmail($data['email']) === false; },
|
'callback' => function ($data) {
|
||||||
|
return User::findFirstByEmail($data['email']) === false;
|
||||||
|
},
|
||||||
'message' => 'This email already exist.',
|
'message' => 'This email already exist.',
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,19 @@ namespace App\Form;
|
||||||
/**
|
/**
|
||||||
* Models
|
* Models
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use App\Model\Data\User as UserModel;
|
use App\Model\Data\User as UserModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Form
|
* Form
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Httpcb\Form as FormBase;
|
use Httpcb\Form as FormBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Element types
|
* Element types
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Phalcon\Forms\Element\Text,
|
use Phalcon\Forms\Element\Text,
|
||||||
Phalcon\Forms\Element\Password,
|
Phalcon\Forms\Element\Password,
|
||||||
Phalcon\Forms\Element\Submit;
|
Phalcon\Forms\Element\Submit;
|
||||||
|
|
@ -22,6 +25,7 @@ use Phalcon\Forms\Element\Text,
|
||||||
/**
|
/**
|
||||||
* Validators
|
* Validators
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Phalcon\Validation\Validator\Callback as CallbackValidator,
|
use Phalcon\Validation\Validator\Callback as CallbackValidator,
|
||||||
Phalcon\Validation\Validator\Uniqueness as UniquenessValidator,
|
Phalcon\Validation\Validator\Uniqueness as UniquenessValidator,
|
||||||
Phalcon\Validation\Validator\Alnum as AlnumValidator,
|
Phalcon\Validation\Validator\Alnum as AlnumValidator,
|
||||||
|
|
@ -56,15 +60,15 @@ class UserSettings extends FormBase
|
||||||
// Id
|
// Id
|
||||||
if ($entity && $entity->getId()) {
|
if ($entity && $entity->getId()) {
|
||||||
|
|
||||||
$id = new Text('id', array(
|
$id = new Text('id', array(
|
||||||
'class' => 'form-control',
|
'class' => 'form-control',
|
||||||
'readonly' => '',
|
'readonly' => '',
|
||||||
'disabled' => 'disabled',
|
'disabled' => 'disabled',
|
||||||
));
|
));
|
||||||
|
|
||||||
$id->addValidator(new IdenticalValidator([
|
$id->addValidator(new IdenticalValidator([
|
||||||
'accepted' => $entity->getId(),
|
'accepted' => $entity->getId(),
|
||||||
'allowEmpty' => true
|
'allowEmpty' => true
|
||||||
]));
|
]));
|
||||||
|
|
||||||
$id->setLabel('ID');
|
$id->setLabel('ID');
|
||||||
|
|
@ -86,7 +90,7 @@ class UserSettings extends FormBase
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($entity && strlen($entity->getUsername())) {
|
if ($entity && strlen($entity->getUsername())) {
|
||||||
$validator_options['except'] = [ $entity->getUsername() ];
|
$validator_options['except'] = [$entity->getUsername()];
|
||||||
}
|
}
|
||||||
|
|
||||||
$username->addValidators([
|
$username->addValidators([
|
||||||
|
|
@ -116,12 +120,12 @@ class UserSettings extends FormBase
|
||||||
'class' => 'form-control',
|
'class' => 'form-control',
|
||||||
'placeholder' => 'Email',
|
'placeholder' => 'Email',
|
||||||
'readonly' => '',
|
'readonly' => '',
|
||||||
'disabled' => 'disabled',
|
'disabled' => 'disabled',
|
||||||
));
|
));
|
||||||
|
|
||||||
$email->addValidator(new IdenticalValidator([
|
$email->addValidator(new IdenticalValidator([
|
||||||
'accepted' => $entity->getEmail(),
|
'accepted' => $entity->getEmail(),
|
||||||
'allowEmpty' => true
|
'allowEmpty' => true
|
||||||
]));
|
]));
|
||||||
} else {
|
} else {
|
||||||
$email = new Text('email', array(
|
$email = new Text('email', array(
|
||||||
|
|
@ -136,7 +140,7 @@ class UserSettings extends FormBase
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($entity && strlen($entity->getEmail())) {
|
if ($entity && strlen($entity->getEmail())) {
|
||||||
$validator_options['except'] = [ $entity->getEmail() ];
|
$validator_options['except'] = [$entity->getEmail()];
|
||||||
}
|
}
|
||||||
|
|
||||||
$email->addValidators([
|
$email->addValidators([
|
||||||
|
|
@ -191,7 +195,7 @@ class UserSettings extends FormBase
|
||||||
|
|
||||||
if ($this->_admin === false && $entity && strlen($entity->getPassword()) > 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'];
|
||||||
if (strlen($new_pw) > 0) {
|
if (strlen($new_pw) > 0) {
|
||||||
$value = $data['passwordCurrent'];
|
$value = $data['passwordCurrent'];
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
namespace Httpcb;
|
namespace Httpcb;
|
||||||
|
|
||||||
use Phalcon\Config,
|
use Phalcon\Config,
|
||||||
Phalcon\Acl\Enum,
|
Phalcon\Acl\Enum,
|
||||||
Phalcon\Acl\Role,
|
Phalcon\Acl\Role,
|
||||||
Phalcon\Acl\Adapter\Memory as Adapter;
|
Phalcon\Acl\Adapter\Memory as Adapter;
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ class Acl
|
||||||
$pos = strpos($resource, '/');
|
$pos = strpos($resource, '/');
|
||||||
if ($pos !== false) {
|
if ($pos !== false) {
|
||||||
// Construct the wildcard resource.
|
// Construct the wildcard resource.
|
||||||
$wildcard = substr($resource, 0, $pos+1) . '*';
|
$wildcard = substr($resource, 0, $pos + 1) . '*';
|
||||||
|
|
||||||
// If we have this wildcard resource, check against that instead.
|
// If we have this wildcard resource, check against that instead.
|
||||||
if ($this->hasResource($wildcard)) {
|
if ($this->hasResource($wildcard)) {
|
||||||
|
|
@ -62,7 +62,7 @@ class Acl
|
||||||
public function fromConfig(Config $config)
|
public function fromConfig(Config $config)
|
||||||
{
|
{
|
||||||
// Add roles.
|
// Add roles.
|
||||||
foreach($config->roles as $name => $def) {
|
foreach ($config->roles as $name => $def) {
|
||||||
|
|
||||||
$inherits = null;
|
$inherits = null;
|
||||||
$description = null;
|
$description = null;
|
||||||
|
|
@ -70,7 +70,6 @@ class Acl
|
||||||
if ($def instanceof Config) {
|
if ($def instanceof Config) {
|
||||||
$inherits = $def->get('inherits');
|
$inherits = $def->get('inherits');
|
||||||
$description = $def->get('description');
|
$description = $def->get('description');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$role = new Role($name, $description);
|
$role = new Role($name, $description);
|
||||||
|
|
@ -78,33 +77,33 @@ class Acl
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zones
|
// Zones
|
||||||
foreach($config->zones as $name => $resources) {
|
foreach ($config->zones as $name => $resources) {
|
||||||
|
|
||||||
if (!($resources instanceof Config)) {
|
if (!($resources instanceof Config)) {
|
||||||
$resources = new Config([ $resources ]);
|
$resources = new Config([$resources]);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($resources as $resource) {
|
foreach ($resources as $resource) {
|
||||||
$this->_adapter->addComponent($resource, 'All');
|
$this->_adapter->addComponent($resource, 'All');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grant access for roles and resources.
|
// Grant access for roles and resources.
|
||||||
foreach($config->roles as $name => $def) {
|
foreach ($config->roles as $name => $def) {
|
||||||
|
|
||||||
$zones = $def->get('allowed-zones', []);
|
$zones = $def->get('allowed-zones', []);
|
||||||
|
|
||||||
if (is_string($zones)) {
|
if (is_string($zones)) {
|
||||||
$zones = [ $zones ];
|
$zones = [$zones];
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($zones as $zone) {
|
foreach ($zones as $zone) {
|
||||||
$resources = $config->zones->get($zone);
|
$resources = $config->zones->get($zone);
|
||||||
if (!($resources instanceof Config)) {
|
if (!($resources instanceof Config)) {
|
||||||
$resources = new Config([ $resources ]);
|
$resources = new Config([$resources]);
|
||||||
}
|
}
|
||||||
foreach($resources as $resource) {
|
foreach ($resources as $resource) {
|
||||||
$this->_adapter->allow($name, $resource, 'All');
|
$this->_adapter->allow($name, $resource, 'All');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ use App\Model\Data\User,
|
||||||
class Auth extends Injectable
|
class Auth extends Injectable
|
||||||
{
|
{
|
||||||
const SESSION_KEY = 'auth';
|
const SESSION_KEY = 'auth';
|
||||||
|
const IMPERSONATOR_ID = 'auth.impersonator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Login using email/user + password combination.
|
* Login using email/user + password combination.
|
||||||
|
|
@ -63,8 +64,11 @@ class Auth extends Injectable
|
||||||
|
|
||||||
$this->setIdentity($user->getId());
|
$this->setIdentity($user->getId());
|
||||||
|
|
||||||
$this->eventsManager->fire('auth:onLogin', $this,
|
$this->eventsManager->fire(
|
||||||
"OAuth {$data->getProvider()}");
|
'auth:onLogin',
|
||||||
|
$this,
|
||||||
|
"OAuth {$data->getProvider()}"
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
return new Result(Result::SUCCESS);
|
return new Result(Result::SUCCESS);
|
||||||
|
|
@ -83,6 +87,40 @@ class Auth extends Injectable
|
||||||
$this->eventsManager->fire('auth:onLogin', $this, 'System');
|
$this->eventsManager->fire('auth:onLogin', $this, 'System');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getImpersonator()
|
||||||
|
{
|
||||||
|
$id = $this->session->get(self::IMPERSONATOR_ID);
|
||||||
|
return $id !== null ? User::findFirst($id) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Impersonate a user
|
||||||
|
*
|
||||||
|
* @param User $user
|
||||||
|
*/
|
||||||
|
public function impersonate(User $user)
|
||||||
|
{
|
||||||
|
$current = $this->getIdentity();
|
||||||
|
if ($current === null) {
|
||||||
|
throw new \InvalidArgumentException("Need to be authenticated to be able to impersonate someone");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($current->getId() === $user->getId()) {
|
||||||
|
// Same user
|
||||||
|
throw new \DomainException("Can't impersonate yourself");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->session->set(self::IMPERSONATOR_ID, $current->getId());
|
||||||
|
$this->setIdentity($user->getId());
|
||||||
|
$this->eventsManager->fire('auth:onImpersonate', $this, $current);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function impersonateClear($imp_id)
|
||||||
|
{
|
||||||
|
$this->session->remove(self::IMPERSONATOR_ID);
|
||||||
|
$this->session->set(self::SESSION_KEY, $imp_id);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $identity
|
* @param $identity
|
||||||
* @return Auth
|
* @return Auth
|
||||||
|
|
@ -132,7 +170,12 @@ class Auth extends Injectable
|
||||||
*/
|
*/
|
||||||
public function clearIdentity()
|
public function clearIdentity()
|
||||||
{
|
{
|
||||||
$this->session->remove(self::SESSION_KEY);
|
$imp_id = $this->session->get(self::IMPERSONATOR_ID);
|
||||||
|
if ($imp_id !== null) {
|
||||||
|
$this->impersonateClear($imp_id);
|
||||||
|
} else {
|
||||||
|
$this->session->remove(self::SESSION_KEY);
|
||||||
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,13 @@
|
||||||
|
|
||||||
namespace Httpcb;
|
namespace Httpcb;
|
||||||
|
|
||||||
class Debug {
|
class Debug
|
||||||
|
{
|
||||||
|
|
||||||
public static function dump($var, $label = null, $echo = true)
|
public static function dump($var, $label = null, $echo = true)
|
||||||
{
|
{
|
||||||
// format the label
|
// format the label
|
||||||
$label = ($label===null) ? '' : rtrim($label) . ' ';
|
$label = ($label === null) ? '' : rtrim($label) . ' ';
|
||||||
// var_dump the variable into a buffer and keep the output
|
// var_dump the variable into a buffer and keep the output
|
||||||
ob_start();
|
ob_start();
|
||||||
var_dump($var);
|
var_dump($var);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ class Form extends FormBase
|
||||||
{
|
{
|
||||||
$options = [
|
$options = [
|
||||||
'label-class' => 'col-form-label text-end',
|
'label-class' => 'col-form-label text-end',
|
||||||
'class' => [ 'col-sm-10' ],
|
'class' => ['col-sm-10'],
|
||||||
'message' => ''
|
'message' => ''
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -31,7 +31,7 @@ class Form extends FormBase
|
||||||
if ($len === 'full') {
|
if ($len === 'full') {
|
||||||
$options['class'] = [];
|
$options['class'] = [];
|
||||||
} else {
|
} else {
|
||||||
$options['class'] = [ 'col-sm-' . $len ];
|
$options['class'] = ['col-sm-' . $len];
|
||||||
}
|
}
|
||||||
|
|
||||||
unset($opt['length']);
|
unset($opt['length']);
|
||||||
|
|
@ -42,10 +42,10 @@ class Form extends FormBase
|
||||||
|
|
||||||
protected function _render(AbstractElement $ele, $opt)
|
protected function _render(AbstractElement $ele, $opt)
|
||||||
{
|
{
|
||||||
$classes = ['class' => 'form-control'];
|
$classes = ['class' => 'form-control'];
|
||||||
if ($ele->hasMessages()) {
|
if ($ele->hasMessages()) {
|
||||||
$classes['class'] .= ' is-invalid';
|
$classes['class'] .= ' is-invalid';
|
||||||
}
|
}
|
||||||
|
|
||||||
$xhtml = '';
|
$xhtml = '';
|
||||||
|
|
||||||
|
|
@ -53,14 +53,17 @@ class Form extends FormBase
|
||||||
|
|
||||||
$xhtml .= sprintf(
|
$xhtml .= sprintf(
|
||||||
'<label class="%s" for="%s">%s</label>',
|
'<label class="%s" for="%s">%s</label>',
|
||||||
$opt['label-class'], $ele->getName(), $ele->getLabel());
|
$opt['label-class'],
|
||||||
|
$ele->getName(),
|
||||||
|
$ele->getLabel()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$xhtml .= '<div class="' . implode(' ', $opt['class']) . '">'
|
$xhtml .= '<div class="' . implode(' ', $opt['class']) . '">'
|
||||||
. $ele->render($classes);
|
. $ele->render($classes);
|
||||||
|
|
||||||
if ($ele->hasMessages()) {
|
if ($ele->hasMessages()) {
|
||||||
$msg = $ele->getMessages()->current();
|
$msg = $ele->getMessages()->current();
|
||||||
$xhtml .= '<span class="invalid-feedback">' . $msg . '</span>';
|
$xhtml .= '<span class="invalid-feedback">' . $msg . '</span>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ class Menu extends Tag
|
||||||
{
|
{
|
||||||
$xhtml = '';
|
$xhtml = '';
|
||||||
|
|
||||||
foreach($nodes as $node) {
|
foreach ($nodes as $node) {
|
||||||
$xhtml .= $this->_renderNode($node, $depth, $max_depth);
|
$xhtml .= $this->_renderNode($node, $depth, $max_depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -126,15 +126,22 @@ class Menu extends Tag
|
||||||
return $xhtml;
|
return $xhtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
$xhtml = self::tagHtml('li', $node->isActive()
|
$xhtml = self::tagHtml(
|
||||||
|
'li',
|
||||||
|
$node->isActive()
|
||||||
? array('class' => $this->_activeClass) : null,
|
? array('class' => $this->_activeClass) : null,
|
||||||
false, false, true);
|
false,
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
// Generate the link.
|
// Generate the link.
|
||||||
$xhtml .= self::linkTo($node->getHref(), $node->getCaption());
|
$xhtml .= self::linkTo($node->getHref(), $node->getCaption());
|
||||||
|
|
||||||
if ($node->isActive() && $node->hasChildren()
|
if (
|
||||||
&& ($max_depth === null || $depth < $max_depth)) {
|
$node->isActive() && $node->hasChildren()
|
||||||
|
&& ($max_depth === null || $depth < $max_depth)
|
||||||
|
) {
|
||||||
|
|
||||||
$xhtml .= $this->_renderMenu($node->getChildren(), $depth + 1, $max_depth);
|
$xhtml .= $this->_renderMenu($node->getChildren(), $depth + 1, $max_depth);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,10 @@ class RandomId extends Behavior implements BehaviorInterface
|
||||||
*/
|
*/
|
||||||
public function notify($type, \Phalcon\Mvc\ModelInterface $model)
|
public function notify($type, \Phalcon\Mvc\ModelInterface $model)
|
||||||
{
|
{
|
||||||
switch($type) {
|
switch ($type) {
|
||||||
case 'beforeValidationOnCreate' :
|
case 'beforeValidationOnCreate':
|
||||||
$this->generateId($model);
|
$this->generateId($model);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,7 +69,7 @@ class RandomId extends Behavior implements BehaviorInterface
|
||||||
if ($model->$field === null) {
|
if ($model->$field === null) {
|
||||||
|
|
||||||
$random = new \Phalcon\Security\Random();
|
$random = new \Phalcon\Security\Random();
|
||||||
for($i = 0; $i < 3; $i++) {
|
for ($i = 0; $i < 3; $i++) {
|
||||||
$id = substr($random->base64Safe(), 0, $len);
|
$id = substr($random->base64Safe(), 0, $len);
|
||||||
|
|
||||||
$count = $model->count(array(
|
$count = $model->count(array(
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ class Navigation extends Navigation\Container
|
||||||
*/
|
*/
|
||||||
public function __construct($config)
|
public function __construct($config)
|
||||||
{
|
{
|
||||||
foreach($config as $node) {
|
foreach ($config as $node) {
|
||||||
$this->addChild($node);
|
$this->addChild($node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ class Container
|
||||||
|
|
||||||
$node = new Node();
|
$node = new Node();
|
||||||
|
|
||||||
foreach($child as $k => $v) {
|
foreach ($child as $k => $v) {
|
||||||
|
|
||||||
if ($k == 'children') {
|
if ($k == 'children') {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -49,7 +49,7 @@ class Container
|
||||||
|
|
||||||
if (isset($child['children'])) {
|
if (isset($child['children'])) {
|
||||||
|
|
||||||
foreach($child['children'] as $c_data) {
|
foreach ($child['children'] as $c_data) {
|
||||||
$node->addChild($c_data);
|
$node->addChild($c_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -75,10 +75,9 @@ class Container
|
||||||
*/
|
*/
|
||||||
public function addChildren($children)
|
public function addChildren($children)
|
||||||
{
|
{
|
||||||
foreach($children as $child) {
|
foreach ($children as $child) {
|
||||||
$this->addChild($child);
|
$this->addChild($child);
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,7 @@ class Node extends Container
|
||||||
}
|
}
|
||||||
|
|
||||||
// first. Check children.
|
// first. Check children.
|
||||||
foreach($this->getChildren() as $child) {
|
foreach ($this->getChildren() as $child) {
|
||||||
|
|
||||||
if ($child->isActive() == true) {
|
if ($child->isActive() == true) {
|
||||||
$this->setActive(true);
|
$this->setActive(true);
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ class League implements AdapterInterface
|
||||||
try {
|
try {
|
||||||
$reflection = new \ReflectionClass($this->_provider);
|
$reflection = new \ReflectionClass($this->_provider);
|
||||||
return $reflection->getShortName();
|
return $reflection->getShortName();
|
||||||
} catch(\ReflectionException $ex) {
|
} catch (\ReflectionException $ex) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,12 @@ use Phalcon\Di\FactoryDefault as DiDefault,
|
||||||
Phalcon\Flash\Direct as FlashDirect,
|
Phalcon\Flash\Direct as FlashDirect,
|
||||||
Phalcon\Mvc\Model\Metadata\Memory as MemoryMetaData,
|
Phalcon\Mvc\Model\Metadata\Memory as MemoryMetaData,
|
||||||
Phalcon\Mvc\Model\MetaData\Apc as ApcMetaData,
|
Phalcon\Mvc\Model\MetaData\Apc as ApcMetaData,
|
||||||
Phalcon\Mvc\ViewBaseInterface,
|
Phalcon\Mvc\ViewBaseInterface,
|
||||||
Phalcon\Cache\Frontend\Data as FrontendDataCache,
|
Phalcon\Cache\Frontend\Data as FrontendDataCache,
|
||||||
Phalcon\Cache\Backend\Apc as BackendApcCache,
|
Phalcon\Cache\Backend\Apc as BackendApcCache,
|
||||||
Phalcon\Translate\Adapter\NativeArray as TranslateAdapter,
|
Phalcon\Translate\Adapter\NativeArray as TranslateAdapter,
|
||||||
|
Phalcon\Storage\AdapterFactory as StorageAdapterFactory,
|
||||||
|
Phalcon\Cache\AdapterFactory as CacheAdapterFactory,
|
||||||
Phalcon\Logger,
|
Phalcon\Logger,
|
||||||
Phalcon\Mvc\Router;
|
Phalcon\Mvc\Router;
|
||||||
|
|
||||||
|
|
@ -30,7 +32,8 @@ use Httpcb\Auth,
|
||||||
|
|
||||||
use App\Listener\AccessListener,
|
use App\Listener\AccessListener,
|
||||||
App\Listener\DispatchListener,
|
App\Listener\DispatchListener,
|
||||||
App\Listener\ActivityLog;
|
App\Listener\ActivityLog,
|
||||||
|
App\Listener\AuthEmailListener;
|
||||||
|
|
||||||
class Services extends DiDefault
|
class Services extends DiDefault
|
||||||
{
|
{
|
||||||
|
|
@ -41,13 +44,12 @@ class Services extends DiDefault
|
||||||
$reflection = new \ReflectionObject($this);
|
$reflection = new \ReflectionObject($this);
|
||||||
$methods = $reflection->getMethods(\ReflectionMethod::IS_PROTECTED);
|
$methods = $reflection->getMethods(\ReflectionMethod::IS_PROTECTED);
|
||||||
|
|
||||||
foreach($methods as $method) {
|
foreach ($methods as $method) {
|
||||||
|
|
||||||
if (substr($method->getName(),0, 11) == '_initShared') {
|
if (substr($method->getName(), 0, 11) == '_initShared') {
|
||||||
$service = lcfirst(substr($method->getName(), 11));
|
$service = lcfirst(substr($method->getName(), 11));
|
||||||
$this->setShared($service, $method->getClosure($this));
|
$this->setShared($service, $method->getClosure($this));
|
||||||
}
|
} else if (substr($method->getName(), 0, 5) == '_init') {
|
||||||
else if (substr($method->getName(),0, 5) == '_init') {
|
|
||||||
$service = lcfirst(substr($method->getName(), 5));
|
$service = lcfirst(substr($method->getName(), 5));
|
||||||
$this->set($service, $method->getClosure($this));
|
$this->set($service, $method->getClosure($this));
|
||||||
}
|
}
|
||||||
|
|
@ -81,7 +83,7 @@ class Services extends DiDefault
|
||||||
try {
|
try {
|
||||||
$tmp = new Config($basePath . $file);
|
$tmp = new Config($basePath . $file);
|
||||||
$config->merge($tmp);
|
$config->merge($tmp);
|
||||||
} catch(\Phalcon\Config\Exception $e) {
|
} catch (\Phalcon\Config\Exception $e) {
|
||||||
// Sometime went wrong. Log here?
|
// Sometime went wrong. Log here?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +117,7 @@ class Services extends DiDefault
|
||||||
|
|
||||||
$eventsManager = new \Phalcon\Events\Manager();
|
$eventsManager = new \Phalcon\Events\Manager();
|
||||||
|
|
||||||
$eventsManager->attach("dispatch", function($event, $dispatcher) {
|
$eventsManager->attach("dispatch", function ($event, $dispatcher) {
|
||||||
$actionName = lcfirst(\Phalcon\Text::camelize($dispatcher->getActionName(), '-_'));
|
$actionName = lcfirst(\Phalcon\Text::camelize($dispatcher->getActionName(), '-_'));
|
||||||
$dispatcher->setActionName($actionName);
|
$dispatcher->setActionName($actionName);
|
||||||
});
|
});
|
||||||
|
|
@ -177,8 +179,11 @@ class Services extends DiDefault
|
||||||
$options = $mdConfig['options'];
|
$options = $mdConfig['options'];
|
||||||
$adapter = $mdConfig['adapter'];
|
$adapter = $mdConfig['adapter'];
|
||||||
|
|
||||||
|
$serializerFactory = new \Phalcon\Storage\SerializerFactory();
|
||||||
|
$factory = new CacheAdapterFactory($serializerFactory);
|
||||||
|
|
||||||
$class = 'Phalcon\Mvc\Model\MetaData\\' . $adapter;
|
$class = 'Phalcon\Mvc\Model\MetaData\\' . $adapter;
|
||||||
return new $class($options);
|
return new $class($factory, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, default to Memory.
|
// Otherwise, default to Memory.
|
||||||
|
|
@ -188,22 +193,25 @@ class Services extends DiDefault
|
||||||
protected function _initSession()
|
protected function _initSession()
|
||||||
{
|
{
|
||||||
$config = $this->get('config');
|
$config = $this->get('config');
|
||||||
$session = new \Phalcon\Session\Manager();
|
$session = new \Phalcon\Session\Manager();
|
||||||
|
|
||||||
if (isset($config->session)) {
|
if (isset($config->session)) {
|
||||||
$data = $config->session->toArray();
|
$data = $config->session->toArray();
|
||||||
$adapter_name = isset($data['adapter']) ? $data['adapter'] : 'Stream';
|
$adapter_name = isset($data['adapter']) ? $data['adapter'] : 'Stream';
|
||||||
$options = $data['options'];
|
$options = $data['options'];
|
||||||
|
|
||||||
|
$serializerFactory = new \Phalcon\Storage\SerializerFactory();
|
||||||
|
$factory = new StorageAdapterFactory($serializerFactory);
|
||||||
|
|
||||||
$class = 'Phalcon\Session\Adapter\\' . $adapter_name;
|
$class = 'Phalcon\Session\Adapter\\' . $adapter_name;
|
||||||
$adapter = new $class($options);
|
$adapter = new $class($factory, $options);
|
||||||
}
|
}
|
||||||
// Default to Stream
|
// Default to Stream
|
||||||
else {
|
else {
|
||||||
$adapter = new \Phalcon\Session\Adapter\Stream();
|
$adapter = new \Phalcon\Session\Adapter\Stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
$session->setAdapter($adapter);
|
$session->setAdapter($adapter);
|
||||||
|
|
||||||
// Start session.
|
// Start session.
|
||||||
$session->start();
|
$session->start();
|
||||||
|
|
@ -219,7 +227,7 @@ class Services extends DiDefault
|
||||||
|
|
||||||
$view = new View();
|
$view = new View();
|
||||||
|
|
||||||
$view->setViewsDir([ $config->application->viewsDir ]);
|
$view->setViewsDir([$config->application->viewsDir]);
|
||||||
$view->setLayoutsDir('_layouts/');
|
$view->setLayoutsDir('_layouts/');
|
||||||
$view->setPartialsDir('_partials/');
|
$view->setPartialsDir('_partials/');
|
||||||
|
|
||||||
|
|
@ -310,10 +318,10 @@ class Services extends DiDefault
|
||||||
$config = $this->get('config')->router;
|
$config = $this->get('config')->router;
|
||||||
|
|
||||||
// Create the router
|
// Create the router
|
||||||
$router = new Router();
|
$router = new Router(false);
|
||||||
$router->removeExtraSlashes($config->get('removeExtraSlashes', false));
|
$router->removeExtraSlashes($config->get('removeExtraSlashes', false));
|
||||||
|
|
||||||
foreach($config->routes as $name => $def) {
|
foreach ($config->routes as $name => $def) {
|
||||||
|
|
||||||
if (!($def instanceof \Phalcon\Config)) {
|
if (!($def instanceof \Phalcon\Config)) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -327,6 +335,9 @@ class Services extends DiDefault
|
||||||
$router->add($def->get('pattern'), $path)
|
$router->add($def->get('pattern'), $path)
|
||||||
->setName($name);
|
->setName($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$router->notFound(['controller' => 'error', 'action' => 'show404']);
|
||||||
|
|
||||||
return $router;
|
return $router;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -337,6 +348,7 @@ class Services extends DiDefault
|
||||||
$eventsManager = new \Phalcon\Events\Manager();
|
$eventsManager = new \Phalcon\Events\Manager();
|
||||||
$eventsManager->attach('user', $activityLog);
|
$eventsManager->attach('user', $activityLog);
|
||||||
$eventsManager->attach('auth', $activityLog);
|
$eventsManager->attach('auth', $activityLog);
|
||||||
|
$eventsManager->attach('auth', new AuthEmailListener);
|
||||||
|
|
||||||
return $eventsManager;
|
return $eventsManager;
|
||||||
}
|
}
|
||||||
|
|
@ -353,10 +365,10 @@ class Services extends DiDefault
|
||||||
|
|
||||||
protected function _initSharedLogger()
|
protected function _initSharedLogger()
|
||||||
{
|
{
|
||||||
$path = $this->get('config')->application->logDir;
|
$path = $this->get('config')->application->logDir;
|
||||||
return new \Phalcon\Logger('default', [
|
return new \Phalcon\Logger('default', [
|
||||||
'main' => new \Phalcon\Logger\Adapter\Stream($path . 'app.txt')
|
'main' => new \Phalcon\Logger\Adapter\Stream($path . 'app.txt')
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function _initTemplate()
|
protected function _initTemplate()
|
||||||
|
|
@ -366,7 +378,7 @@ class Services extends DiDefault
|
||||||
$view = new SimpleView();
|
$view = new SimpleView();
|
||||||
$view->setViewsDir($config->application->templateDir);
|
$view->setViewsDir($config->application->templateDir);
|
||||||
$view->registerEngines([
|
$view->registerEngines([
|
||||||
'.volt' => function (ViewBaseInterface $view) use ($config) {
|
'.volt' => function (ViewBaseInterface $view) use ($config) {
|
||||||
$volt = new VoltEngine($view, $this);
|
$volt = new VoltEngine($view, $this);
|
||||||
|
|
||||||
$volt->setOptions(array(
|
$volt->setOptions(array(
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ class Alpha extends AbstractValidator
|
||||||
* @param string $field
|
* @param string $field
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function validate(\Phalcon\Validation $validation, $field) : bool
|
public function validate(\Phalcon\Validation $validation, $field): bool
|
||||||
{
|
{
|
||||||
$allowSpace = $this->getOption('allowSpace', false);
|
$allowSpace = $this->getOption('allowSpace', false);
|
||||||
|
|
||||||
|
|
@ -44,7 +44,7 @@ class Alpha extends AbstractValidator
|
||||||
$message = $validation->getDefaultMessage('Alpha');
|
$message = $validation->getDefaultMessage('Alpha');
|
||||||
}
|
}
|
||||||
|
|
||||||
$replace = [ ":field" => $label ];
|
$replace = [":field" => $label];
|
||||||
|
|
||||||
$code = $this->getOption("code");
|
$code = $this->getOption("code");
|
||||||
if (is_array($code)) {
|
if (is_array($code)) {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ abstract class AbstractHelper implements InjectionAwareInterface
|
||||||
*
|
*
|
||||||
* @param DiInterface $container
|
* @param DiInterface $container
|
||||||
*/
|
*/
|
||||||
public function setDI(DiInterface $container) : void
|
public function setDI(DiInterface $container): void
|
||||||
{
|
{
|
||||||
$this->_di = $container;
|
$this->_di = $container;
|
||||||
}
|
}
|
||||||
|
|
@ -24,7 +24,7 @@ abstract class AbstractHelper implements InjectionAwareInterface
|
||||||
*
|
*
|
||||||
* @return DiInterface
|
* @return DiInterface
|
||||||
*/
|
*/
|
||||||
public function getDI() : DiInterface
|
public function getDI(): DiInterface
|
||||||
{
|
{
|
||||||
return $this->_di;
|
return $this->_di;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ class Icon extends AbstractHelper
|
||||||
|
|
||||||
if (is_array($args)) {
|
if (is_array($args)) {
|
||||||
|
|
||||||
foreach($args as $arg) {
|
foreach ($args as $arg) {
|
||||||
$classes[] .= 'fa-' . $arg;
|
$classes[] .= 'fa-' . $arg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,8 @@ class ServerUrl extends AbstractHelper
|
||||||
|
|
||||||
// remove port if it's the default port.
|
// remove port if it's the default port.
|
||||||
if (($scheme == 'http' && $port == 80)
|
if (($scheme == 'http' && $port == 80)
|
||||||
|| ($scheme == 'https' && $port == 443)) {
|
|| ($scheme == 'https' && $port == 443)
|
||||||
|
) {
|
||||||
$port = null;
|
$port = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ class Service implements InjectionAwareInterface
|
||||||
*
|
*
|
||||||
* @param DiInterface $container
|
* @param DiInterface $container
|
||||||
*/
|
*/
|
||||||
public function setDI(DiInterface $container) : void
|
public function setDI(DiInterface $container): void
|
||||||
{
|
{
|
||||||
$this->_di = $container;
|
$this->_di = $container;
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +26,7 @@ class Service implements InjectionAwareInterface
|
||||||
*
|
*
|
||||||
* @return DiInterface
|
* @return DiInterface
|
||||||
*/
|
*/
|
||||||
public function getDI() : DiInterface
|
public function getDI(): DiInterface
|
||||||
{
|
{
|
||||||
return $this->_di;
|
return $this->_di;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
namespace App\Listener;
|
namespace App\Listener;
|
||||||
|
|
||||||
use Phalcon\Di\Injectable,
|
use Phalcon\Di\Injectable,
|
||||||
Phalcon\Events\Event,
|
Phalcon\Events\Event,
|
||||||
Phalcon\Mvc\Dispatcher,
|
Phalcon\Mvc\Dispatcher,
|
||||||
Phalcon\Mvc\Dispatcher\Exception as DispatcherException;
|
Phalcon\Mvc\Dispatcher\Exception as DispatcherException;
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@ class AccessListener extends Injectable
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws DispatcherException
|
* @throws DispatcherException
|
||||||
*/
|
*/
|
||||||
public function beforeExecuteRoute(Event $event, Dispatcher $dispatcher) : bool
|
public function beforeExecuteRoute(Event $event, Dispatcher $dispatcher): bool
|
||||||
{
|
{
|
||||||
// If we have an identity, fetch type from authed user.
|
// If we have an identity, fetch type from authed user.
|
||||||
if ($this->auth->hasIdentity()) {
|
if ($this->auth->hasIdentity()) {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,19 @@ class ActivityLog extends Injectable
|
||||||
$this->_log($auth->getUser(), sprintf("Logged in (%s)", $type));
|
$this->_log($auth->getUser(), sprintf("Logged in (%s)", $type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On Impersonate event.
|
||||||
|
*
|
||||||
|
* @param Event $event
|
||||||
|
* @param Auth $auth
|
||||||
|
* @param User $user The user Impersonating the user in $auth
|
||||||
|
*/
|
||||||
|
public function onImpersonate(Event $event, Auth $auth, User $user)
|
||||||
|
{
|
||||||
|
$imp = $auth->getUser();
|
||||||
|
$this->_log($user, sprintf("Impersonated user (%s:%s)", $imp->getId(), $imp->getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Event $event
|
* @param Event $event
|
||||||
* @param User $auth
|
* @param User $auth
|
||||||
|
|
@ -65,11 +78,23 @@ class ActivityLog extends Injectable
|
||||||
$this->_log($user, sprintf("OAuth disconnected (%s)", $providerName));
|
$this->_log($user, sprintf("OAuth disconnected (%s)", $providerName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fired when a activation email is sent.
|
||||||
|
*
|
||||||
|
* @param Event $event
|
||||||
|
* @param User $user
|
||||||
|
* @param string $providerName
|
||||||
|
*/
|
||||||
|
public function onSentActivation(Event $event, User $user)
|
||||||
|
{
|
||||||
|
$this->_log($user, sprintf("Activation email sent"));
|
||||||
|
}
|
||||||
|
|
||||||
protected function _log(User $user, $message)
|
protected function _log(User $user, $message)
|
||||||
{
|
{
|
||||||
$ip = (new \Phalcon\Http\Request())->getClientAddress();
|
$ip = (new \Phalcon\Http\Request())->getClientAddress(true);
|
||||||
|
|
||||||
return (new ActivityLogger())->assign([
|
return (new ActivityLogger())->assign([
|
||||||
'user_id' => $user->getId(),
|
'user_id' => $user->getId(),
|
||||||
'ip' => $ip,
|
'ip' => $ip,
|
||||||
'message' => $message
|
'message' => $message
|
||||||
|
|
|
||||||
25
app/listeners/AuthEmailListener.php
Normal file
25
app/listeners/AuthEmailListener.php
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listener;
|
||||||
|
|
||||||
|
use App\Model\Data\User,
|
||||||
|
App\Model\Data\UserActivation;
|
||||||
|
|
||||||
|
use Phalcon\Di\Injectable,
|
||||||
|
Phalcon\Events\Event;
|
||||||
|
|
||||||
|
class AuthEmailListener extends Injectable
|
||||||
|
{
|
||||||
|
public function onSentActivation(Event $event, User $user)
|
||||||
|
{
|
||||||
|
$activation = new UserActivation();
|
||||||
|
$activation->setUserId($user->getId())
|
||||||
|
->save();
|
||||||
|
|
||||||
|
$content = $this->di->getShared('template')->render('mail/account_activation', [
|
||||||
|
'link' => $activation->getActivationKey()
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->di->getMail()->send('Httpcb account activation', $user->getEmail(), $content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@ namespace App\Listener;
|
||||||
|
|
||||||
use Exception,
|
use Exception,
|
||||||
Phalcon\Events\Event,
|
Phalcon\Events\Event,
|
||||||
Phalcon\Di\Injectable,
|
Phalcon\Di\Injectable,
|
||||||
Phalcon\Mvc\Dispatcher,
|
Phalcon\Mvc\Dispatcher,
|
||||||
Phalcon\Mvc\Dispatcher\Exception as DispatcherException;
|
Phalcon\Mvc\Dispatcher\Exception as DispatcherException;
|
||||||
|
|
||||||
|
|
@ -38,11 +38,11 @@ class DispatchListener extends Injectable
|
||||||
// was that an controller or action was not found.
|
// was that an controller or action was not found.
|
||||||
if ($exception instanceof DispatcherException) {
|
if ($exception instanceof DispatcherException) {
|
||||||
switch ($exception->getCode()) {
|
switch ($exception->getCode()) {
|
||||||
case Dispatcher::EXCEPTION_HANDLER_NOT_FOUND :
|
case Dispatcher::EXCEPTION_HANDLER_NOT_FOUND:
|
||||||
case Dispatcher::EXCEPTION_ACTION_NOT_FOUND :
|
case Dispatcher::EXCEPTION_ACTION_NOT_FOUND:
|
||||||
// in this case, forward to 404 page.
|
// in this case, forward to 404 page.
|
||||||
$dispatcher->forward($this->_route_notfound);
|
$dispatcher->forward($this->_route_notfound);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ class CreateUserTable extends AbstractMigration
|
||||||
$table->addColumn('status', 'enum', [
|
$table->addColumn('status', 'enum', [
|
||||||
'null' => false,
|
'null' => false,
|
||||||
'default' => 'Active',
|
'default' => 'Active',
|
||||||
'values' => [ 'Active', 'Deleted', 'Suspended']
|
'values' => ['Active', 'Deleted', 'Suspended']
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$table->addColumn('password', 'string', [
|
$table->addColumn('password', 'string', [
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,11 @@ class CreateCallbackTable extends AbstractMigration
|
||||||
$table->addColumn('public_id', 'string', [
|
$table->addColumn('public_id', 'string', [
|
||||||
'length' => 12,
|
'length' => 12,
|
||||||
'null' => false,
|
'null' => false,
|
||||||
])->addIndex('public_id', [ 'name' => 'UNIQUE_public_id', 'unique' => true ]);
|
])->addIndex('public_id', ['name' => 'UNIQUE_public_id', 'unique' => true]);
|
||||||
|
|
||||||
$table->addColumn('userid', 'integer', [
|
$table->addColumn('userid', 'integer', [
|
||||||
'null' => true,
|
'null' => true,
|
||||||
])->addForeignKey('userid', 'user', ['id'], [ 'constraint' => 'FK_user' ]);
|
])->addForeignKey('userid', 'user', ['id'], ['constraint' => 'FK_user']);
|
||||||
|
|
||||||
$table->addColumn('name', 'string', [
|
$table->addColumn('name', 'string', [
|
||||||
'length' => 64,
|
'length' => 64,
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,12 @@ class CreateRequestMetaTable extends AbstractMigration
|
||||||
$table = $this->table('request_meta');
|
$table = $this->table('request_meta');
|
||||||
|
|
||||||
$table->addColumn('callbackid', 'integer');
|
$table->addColumn('callbackid', 'integer');
|
||||||
$table->addForeignKey('callbackid', 'callback', [ 'id' ],
|
$table->addForeignKey(
|
||||||
[ 'constraint' => 'FK_callback' ]);
|
'callbackid',
|
||||||
|
'callback',
|
||||||
|
['id'],
|
||||||
|
['constraint' => 'FK_callback']
|
||||||
|
);
|
||||||
|
|
||||||
$table->addColumn('source_ip', 'string', [
|
$table->addColumn('source_ip', 'string', [
|
||||||
'limit' => 50,
|
'limit' => 50,
|
||||||
|
|
@ -21,7 +25,7 @@ class CreateRequestMetaTable extends AbstractMigration
|
||||||
$table->addColumn('method', 'enum', [
|
$table->addColumn('method', 'enum', [
|
||||||
'null' => false,
|
'null' => false,
|
||||||
'default' => 'GET',
|
'default' => 'GET',
|
||||||
'values' => [ 'GET', 'POST' ]
|
'values' => ['GET', 'POST']
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$table->addColumn('uri', 'string', [
|
$table->addColumn('uri', 'string', [
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,12 @@ class CreateRequestObjectTable extends AbstractMigration
|
||||||
{
|
{
|
||||||
$table = $this->table('request_object');
|
$table = $this->table('request_object');
|
||||||
|
|
||||||
$table->addForeignKey('id', 'request_meta', ['id'],
|
$table->addForeignKey(
|
||||||
[ 'constraint' => 'FK_request_meta' ]);
|
'id',
|
||||||
|
'request_meta',
|
||||||
|
['id'],
|
||||||
|
['constraint' => 'FK_request_meta']
|
||||||
|
);
|
||||||
|
|
||||||
$table->addColumn('headers', 'blob', [
|
$table->addColumn('headers', 'blob', [
|
||||||
'null' => true,
|
'null' => true,
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,11 @@ class PasswordLink extends AbstractMigration
|
||||||
public function up()
|
public function up()
|
||||||
{
|
{
|
||||||
$this->table('password_link')
|
$this->table('password_link')
|
||||||
->addColumn('public_id', 'string', ['length' => 12 ])
|
->addColumn('public_id', 'string', ['length' => 12])
|
||||||
->addColumn('user_id', 'integer')
|
->addColumn('user_id', 'integer')
|
||||||
->addForeignKey('user_id', 'user', ['id'], [ 'constraint' => 'FK_password_link_user' ])
|
->addForeignKey('user_id', 'user', ['id'], ['constraint' => 'FK_password_link_user'])
|
||||||
->addColumn('date', 'datetime', [ 'default' => 'CURRENT_TIMESTAMP' ])
|
->addColumn('date', 'datetime', ['default' => 'CURRENT_TIMESTAMP'])
|
||||||
->addColumn('password', 'string', [ 'limit' => 255, 'null' => true ])
|
->addColumn('password', 'string', ['limit' => 255, 'null' => true])
|
||||||
->save();
|
->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ class UserSplitName extends AbstractMigration
|
||||||
// Rename "name" to "firstname" and add "lastname".
|
// Rename "name" to "firstname" and add "lastname".
|
||||||
$this->table('user')
|
$this->table('user')
|
||||||
->renameColumn('name', 'firstname')
|
->renameColumn('name', 'firstname')
|
||||||
->addColumn('lastname','string', [
|
->addColumn('lastname', 'string', [
|
||||||
'length' => 128,
|
'length' => 128,
|
||||||
'after' => 'firstname',
|
'after' => 'firstname',
|
||||||
'null' => true
|
'null' => true
|
||||||
|
|
@ -20,7 +20,7 @@ class UserSplitName extends AbstractMigration
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
// Update row data, moving everything after first space to from lastname.
|
// Update row data, moving everything after first space to from lastname.
|
||||||
foreach($this->fetchAll("SELECT `id`,`firstname` FROM `user`") as $row) {
|
foreach ($this->fetchAll("SELECT `id`,`firstname` FROM `user`") as $row) {
|
||||||
|
|
||||||
$builder = $this->getQueryBuilder()->update('user')
|
$builder = $this->getQueryBuilder()->update('user')
|
||||||
->where(['id' => $row['id']]);
|
->where(['id' => $row['id']]);
|
||||||
|
|
@ -31,7 +31,7 @@ class UserSplitName extends AbstractMigration
|
||||||
$pos = strpos($firstname, ' ');
|
$pos = strpos($firstname, ' ');
|
||||||
if ($pos !== false) {
|
if ($pos !== false) {
|
||||||
// Set everything after the first space to lastname.
|
// Set everything after the first space to lastname.
|
||||||
$builder->set('lastname', substr($firstname, $pos+1));
|
$builder->set('lastname', substr($firstname, $pos + 1));
|
||||||
|
|
||||||
// Remove everything after first space from firstname.
|
// Remove everything after first space from firstname.
|
||||||
$firstname = substr($firstname, 0, $pos);
|
$firstname = substr($firstname, 0, $pos);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ class UserType extends AbstractMigration
|
||||||
->addColumn('type', 'enum', [
|
->addColumn('type', 'enum', [
|
||||||
'null' => false,
|
'null' => false,
|
||||||
'default' => 'user',
|
'default' => 'user',
|
||||||
'values' => [ 'user', 'admin' ],
|
'values' => ['user', 'admin'],
|
||||||
'after' => 'regdate'
|
'after' => 'regdate'
|
||||||
])
|
])
|
||||||
->save();
|
->save();
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ class Base extends Model
|
||||||
* @param boolean $allFields
|
* @param boolean $allFields
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function hasChanged($fieldName = null, bool $allFields = false) : bool
|
public function hasChanged($fieldName = null, bool $allFields = false): bool
|
||||||
{
|
{
|
||||||
return $this->hasSnapshotData() === false
|
return $this->hasSnapshotData() === false
|
||||||
|| parent::hasChanged($fieldName, $allFields);
|
|| parent::hasChanged($fieldName, $allFields);
|
||||||
|
|
|
||||||
|
|
@ -216,8 +216,8 @@ class Callback extends Model
|
||||||
*/
|
*/
|
||||||
public function initialize()
|
public function initialize()
|
||||||
{
|
{
|
||||||
// Set table name mapped in the model.
|
// Set table name mapped in the model.
|
||||||
$this->setSource('callback');
|
$this->setSource('callback');
|
||||||
|
|
||||||
$this->useDynamicUpdate(true);
|
$this->useDynamicUpdate(true);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ class Request extends Model
|
||||||
*/
|
*/
|
||||||
public function setHeaders($headers)
|
public function setHeaders($headers)
|
||||||
{
|
{
|
||||||
foreach($headers as $k => $v) {
|
foreach ($headers as $k => $v) {
|
||||||
|
|
||||||
if (strlen($v) < 1) {
|
if (strlen($v) < 1) {
|
||||||
unset($headers[$k]);
|
unset($headers[$k]);
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,7 @@ class RequestMeta extends Model
|
||||||
$query = (string) parse_url($this->getUri(), PHP_URL_QUERY);
|
$query = (string) parse_url($this->getUri(), PHP_URL_QUERY);
|
||||||
|
|
||||||
$ret = array();
|
$ret = array();
|
||||||
foreach(explode('&', $query) as $v) {
|
foreach (explode('&', $query) as $v) {
|
||||||
@list($k, $v) = explode('=', $v, 2);
|
@list($k, $v) = explode('=', $v, 2);
|
||||||
if (strlen($k) > 0) {
|
if (strlen($k) > 0) {
|
||||||
$ret[$k] = $v;
|
$ret[$k] = $v;
|
||||||
|
|
@ -211,7 +211,7 @@ class RequestMeta extends Model
|
||||||
{
|
{
|
||||||
$headers = $this->getHeaders();
|
$headers = $this->getHeaders();
|
||||||
|
|
||||||
foreach($headers as $k => $v) {
|
foreach ($headers as $k => $v) {
|
||||||
|
|
||||||
if ($k == 'Content-Length') {
|
if ($k == 'Content-Length') {
|
||||||
return $v;
|
return $v;
|
||||||
|
|
@ -224,7 +224,7 @@ class RequestMeta extends Model
|
||||||
{
|
{
|
||||||
$headers = $this->getHeaders();
|
$headers = $this->getHeaders();
|
||||||
|
|
||||||
foreach($headers as $k => $v) {
|
foreach ($headers as $k => $v) {
|
||||||
|
|
||||||
if ($k == 'Content-Type') {
|
if ($k == 'Content-Type') {
|
||||||
return substr($v, strrpos($v, '/') + 1);
|
return substr($v, strrpos($v, '/') + 1);
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ class User extends Base
|
||||||
'message' => 'The username already exists.'
|
'message' => 'The username already exists.'
|
||||||
]),
|
]),
|
||||||
'email' => new CallbackValidator([
|
'email' => new CallbackValidator([
|
||||||
'callback' => function() {
|
'callback' => function () {
|
||||||
return $this->findFirstByEmail($this->getEmail()) === false;
|
return $this->findFirstByEmail($this->getEmail()) === false;
|
||||||
},
|
},
|
||||||
'message' => 'The email address already exists.'
|
'message' => 'The email address already exists.'
|
||||||
|
|
@ -69,7 +69,7 @@ class User extends Base
|
||||||
];
|
];
|
||||||
|
|
||||||
$validation = new Validation();
|
$validation = new Validation();
|
||||||
foreach($rules as $field => $validator) {
|
foreach ($rules as $field => $validator) {
|
||||||
|
|
||||||
// Only validate changed fields.
|
// Only validate changed fields.
|
||||||
if ($this->hasChanged($field)) {
|
if ($this->hasChanged($field)) {
|
||||||
|
|
@ -265,6 +265,16 @@ class User extends Base
|
||||||
return $this->status == self::STATUS_ACTIVE;
|
return $this->status == self::STATUS_ACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this user is suspended.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isSuspended()
|
||||||
|
{
|
||||||
|
return $this->status == self::STATUS_SUSPENDED;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
|
|
@ -404,7 +414,7 @@ class User extends Base
|
||||||
{
|
{
|
||||||
return self::findFirst([
|
return self::findFirst([
|
||||||
"(email = :v: OR username = :v:) AND status != :s:",
|
"(email = :v: OR username = :v:) AND status != :s:",
|
||||||
"bind" => [ 'v' => $value, 's' => self::STATUS_DELETED ]
|
"bind" => ['v' => $value, 's' => self::STATUS_DELETED]
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -412,7 +422,7 @@ class User extends Base
|
||||||
{
|
{
|
||||||
return self::findFirst([
|
return self::findFirst([
|
||||||
"email = :email: AND status != :s:",
|
"email = :email: AND status != :s:",
|
||||||
"bind" => [ 'email' => $email, 's' => self::STATUS_DELETED ]
|
"bind" => ['email' => $email, 's' => self::STATUS_DELETED]
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -420,7 +430,7 @@ class User extends Base
|
||||||
{
|
{
|
||||||
return self::findFirst([
|
return self::findFirst([
|
||||||
"username = :username: AND status != :s:",
|
"username = :username: AND status != :s:",
|
||||||
"bind" => [ 'username' => $username, 's' => self::STATUS_DELETED ]
|
"bind" => ['username' => $username, 's' => self::STATUS_DELETED]
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -430,7 +440,7 @@ class User extends Base
|
||||||
|
|
||||||
return self::findFirst([
|
return self::findFirst([
|
||||||
"{$column}_id = :id: AND status != :s:",
|
"{$column}_id = :id: AND status != :s:",
|
||||||
"bind" => [ 'id' => $oauth->getId(), 's' => self::STATUS_DELETED ]
|
"bind" => ['id' => $oauth->getId(), 's' => self::STATUS_DELETED]
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ class UserActivation extends Base
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @return PasswordLink
|
* @return PasswordLink
|
||||||
*/
|
*/
|
||||||
public function setId(int $id) : UserActivation
|
public function setId(int $id): UserActivation
|
||||||
{
|
{
|
||||||
$this->id = $id;
|
$this->id = $id;
|
||||||
return $this;
|
return $this;
|
||||||
|
|
@ -97,7 +97,7 @@ class UserActivation extends Base
|
||||||
* @param string $public_id
|
* @param string $public_id
|
||||||
* @return UserActivation
|
* @return UserActivation
|
||||||
*/
|
*/
|
||||||
public function setActivationKey(string $key) : UserActivation
|
public function setActivationKey(string $key): UserActivation
|
||||||
{
|
{
|
||||||
$this->activation_key = $key;
|
$this->activation_key = $key;
|
||||||
return $this;
|
return $this;
|
||||||
|
|
@ -115,7 +115,7 @@ class UserActivation extends Base
|
||||||
* @param int $user_id
|
* @param int $user_id
|
||||||
* @return UserActivation
|
* @return UserActivation
|
||||||
*/
|
*/
|
||||||
public function setUserId(int $user_id) : UserActivation
|
public function setUserId(int $user_id): UserActivation
|
||||||
{
|
{
|
||||||
$this->user_id = $user_id;
|
$this->user_id = $user_id;
|
||||||
return $this;
|
return $this;
|
||||||
|
|
@ -133,7 +133,7 @@ class UserActivation extends Base
|
||||||
* @param string $password
|
* @param string $password
|
||||||
* @return UserActivation
|
* @return UserActivation
|
||||||
*/
|
*/
|
||||||
public function setPassword(string $password) : UserActivation
|
public function setPassword(string $password): UserActivation
|
||||||
{
|
{
|
||||||
$this->password = $password;
|
$this->password = $password;
|
||||||
return $this;
|
return $this;
|
||||||
|
|
@ -144,7 +144,7 @@ class UserActivation extends Base
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isUsed() : bool
|
public function isUsed(): bool
|
||||||
{
|
{
|
||||||
return (bool) $this->used;
|
return (bool) $this->used;
|
||||||
}
|
}
|
||||||
|
|
@ -154,7 +154,7 @@ class UserActivation extends Base
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isValid() : bool
|
public function isValid(): bool
|
||||||
{
|
{
|
||||||
// Used links are not valid.
|
// Used links are not valid.
|
||||||
if ($this->isUsed()) {
|
if ($this->isUsed()) {
|
||||||
|
|
@ -175,9 +175,9 @@ class UserActivation extends Base
|
||||||
public function beforeCreate()
|
public function beforeCreate()
|
||||||
{
|
{
|
||||||
// Creating a new link automatically removes old ones.
|
// Creating a new link automatically removes old ones.
|
||||||
$links = self::find(["user_id = ?0", 'bind' => [ $this->user_id ]]);
|
$links = self::find(["user_id = ?0", 'bind' => [$this->user_id]]);
|
||||||
|
|
||||||
foreach($links as $link) {
|
foreach ($links as $link) {
|
||||||
$link->delete();
|
$link->delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,8 @@ abstract class Base implements ModuleDefinitionInterface
|
||||||
$dispatcher->setDefaultNamespace($this->_controllerNamespace);
|
$dispatcher->setDefaultNamespace($this->_controllerNamespace);
|
||||||
|
|
||||||
$di->get('view')->setViewsDir(array_merge(
|
$di->get('view')->setViewsDir(array_merge(
|
||||||
[ $this->_viewDir ],
|
[$this->_viewDir],
|
||||||
(array) $di->get('view')->getViewsDir()
|
(array) $di->get('view')->getViewsDir()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
data-bs-toggle="dropdown" role="button" aria-expanded="false">
|
data-bs-toggle="dropdown" role="button" aria-expanded="false">
|
||||||
|
|
||||||
{{ icon('solid/user') }} <strong>{{ auth.getUser().username }}</strong>
|
{{ icon('solid/user') }} <strong>{{ auth.getUser().username }}</strong>
|
||||||
|
{% set imp = auth.getImpersonator() %}
|
||||||
|
{% if imp %}( {{ icon('solid/user-secret') }} {{ imp.username }} ){% endif %}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<ul class="dropdown-menu navigation-user-menu-dropdown-list">
|
<ul class="dropdown-menu navigation-user-menu-dropdown-list">
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,13 @@
|
||||||
{% if (user.getId()) %}
|
{% if (user.getId()) %}
|
||||||
{% set actions = [ 'Activate': 'Active', 'Suspend': 'Suspended', 'Delete': 'Deleted' ] %}
|
{% set actions = [ 'Activate': 'Active', 'Suspend': 'Suspended', 'Delete': 'Deleted' ] %}
|
||||||
<div class="float-end">
|
<div class="float-end">
|
||||||
|
|
||||||
|
{% if user.isSuspended() %}
|
||||||
|
<a class="button button-info" href="{{ url(['for': 'backend-user-activation-email', 'id': user.getId() ]) }}">
|
||||||
|
Send activation email
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% for label, status in actions %}
|
{% for label, status in actions %}
|
||||||
|
|
||||||
{% if (user.status != status) %}
|
{% if (user.status != status) %}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
<th>Email</th>
|
<th>Email</th>
|
||||||
<th>Type</th>
|
<th>Type</th>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
|
<th> </th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
|
|
@ -36,7 +37,12 @@
|
||||||
<td>{{ item.name }}</td>
|
<td>{{ item.name }}</td>
|
||||||
<td>{{ item.email }}</td>
|
<td>{{ item.email }}</td>
|
||||||
<td>{{ item.type | capitalize }}</td>
|
<td>{{ item.type | capitalize }}</td>
|
||||||
<td>{{ item.status }}</td>
|
<td><span class="badge {{ item.isActive() ? 'badge-success' : 'badge-danger' }}">{{ item.status }}</span></td>
|
||||||
|
<td>
|
||||||
|
<a title="Impersonate" href="{{ url(['for': 'backend-user-impersonate', 'id': item.id ]) }}">
|
||||||
|
{{ icon('solid/user-secret') }}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
"ext-psr": ">=1.2",
|
"ext-psr": ">=1.2",
|
||||||
"ext-redis": "*",
|
"ext-redis": "*",
|
||||||
"ext-yaml": "*",
|
"ext-yaml": "*",
|
||||||
|
"ext-mbstring": "*",
|
||||||
"robmorgan/phinx": "^0.10.6",
|
"robmorgan/phinx": "^0.10.6",
|
||||||
"league/oauth2-client": "^2.3",
|
"league/oauth2-client": "^2.3",
|
||||||
"league/oauth2-github": "^2.0",
|
"league/oauth2-github": "^2.0",
|
||||||
|
|
|
||||||
5
package-lock.json
generated
5
package-lock.json
generated
|
|
@ -1,11 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "httpcb",
|
"name": "httpcb",
|
||||||
"version": "1.1",
|
"version": "1.1.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"version": "1.1",
|
"name": "httpcb",
|
||||||
|
"version": "1.1.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@popperjs/core": "^2.11.5",
|
"@popperjs/core": "^2.11.5",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "httpcb",
|
"name": "httpcb",
|
||||||
"version": "1.1",
|
"version": "1.1.0",
|
||||||
"description": "HTTP Callback Tool",
|
"description": "HTTP Callback Tool",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@popperjs/core": "^2.11.5",
|
"@popperjs/core": "^2.11.5",
|
||||||
|
|
|
||||||
Reference in a new issue