Compare commits
No commits in common. "dev" and "v1.1" have entirely different histories.
53 changed files with 193 additions and 398 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,61 +4,58 @@ router:
|
||||||
routes:
|
routes:
|
||||||
home-route:
|
home-route:
|
||||||
pattern: '/'
|
pattern: '/'
|
||||||
path: Index::index
|
path:
|
||||||
|
controller: index
|
||||||
|
action: index
|
||||||
about-route:
|
about-route:
|
||||||
pattern: '/about'
|
pattern: '/about'
|
||||||
path: Index::about
|
path:
|
||||||
|
controller: index
|
||||||
# Callbacks
|
action: about
|
||||||
|
|
||||||
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: Callback::created
|
path:
|
||||||
cb-show:
|
controller: callback
|
||||||
pattern: '/callback/show/{id}'
|
action: created
|
||||||
path: Callback::show
|
|
||||||
cb-endpoint:
|
cb-endpoint:
|
||||||
pattern: '/cb/{id}/:params'
|
pattern: '/cb/{id}/:params'
|
||||||
path: Api::endpoint
|
path:
|
||||||
|
controller: api
|
||||||
# login
|
action: endpoint
|
||||||
|
|
||||||
login:
|
login:
|
||||||
pattern: '/login'
|
pattern: '/login'
|
||||||
path: Auth::index
|
path:
|
||||||
|
controller: auth
|
||||||
|
action: index
|
||||||
logout:
|
logout:
|
||||||
pattern: '/logout'
|
pattern: '/logout'
|
||||||
path: Auth::logout
|
path:
|
||||||
|
controller: auth
|
||||||
|
action: logout
|
||||||
oauth:
|
oauth:
|
||||||
pattern: '/login/{strategy:([a-z]+)}/:params'
|
pattern: '/login/{strategy:([a-z]+)}/:params'
|
||||||
path: Auth::oauth
|
path:
|
||||||
|
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: User::settings
|
path:
|
||||||
user-activity-log:
|
controller: user
|
||||||
pattern: '/user/activity'
|
action: settings
|
||||||
path: User::activity
|
|
||||||
activation-link:
|
activation-link:
|
||||||
pattern: '/activate/{link}'
|
pattern: '/activate/{link}'
|
||||||
path: Api::activationlink
|
path:
|
||||||
|
controller: api
|
||||||
|
action: activationlink
|
||||||
|
|
||||||
# Backend
|
# Backend
|
||||||
backend-home:
|
backend-home:
|
||||||
|
|
@ -73,15 +70,12 @@ 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]+)}/status/{type}'
|
pattern: '/admin/user/{id:([0-9]+)}/{type}'
|
||||||
path: backend::user::status
|
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
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ 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
|
||||||
|
|
|
||||||
|
|
@ -118,11 +118,8 @@ class AuthController extends ControllerBase
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = new User();
|
$user = new User();
|
||||||
$user->assign(
|
$user->assign($data->toArray(), null,
|
||||||
$data->toArray(),
|
[ 'email', 'username', 'firstname', 'lastname' ]);
|
||||||
null,
|
|
||||||
['email', 'username', 'firstname', 'lastname']
|
|
||||||
);
|
|
||||||
|
|
||||||
$form = new RegistrationForm($user);
|
$form = new RegistrationForm($user);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,7 @@ 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);
|
||||||
|
|
@ -72,6 +71,8 @@ class CallbackController extends ControllerBase
|
||||||
$msg .= '</ul>';
|
$msg .= '</ul>';
|
||||||
$this->flash->message('error', $msg);
|
$this->flash->message('error', $msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->view->form = $form;
|
$this->view->form = $form;
|
||||||
|
|
@ -84,6 +85,7 @@ 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,7 +18,6 @@ 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,3 +15,4 @@ class IndexController extends ControllerBase
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,11 +44,8 @@ class UserController extends ControllerBase
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Send the email.
|
// Send the email.
|
||||||
$this->di->getMail()->send(
|
$this->di->getMail()->send('Httpcb password activation',
|
||||||
'Httpcb password activation',
|
$user->getEmail(), $content);
|
||||||
$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 "
|
||||||
|
|
|
||||||
|
|
@ -97,33 +97,4 @@ 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,14 +7,12 @@ 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,7 +7,6 @@ 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;
|
||||||
|
|
@ -15,7 +14,6 @@ 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,19 +5,16 @@ 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;
|
||||||
|
|
@ -25,7 +22,6 @@ 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,
|
||||||
|
|
@ -58,9 +54,7 @@ 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) {
|
'callback' => function($data) { return User::findFirstByUsername($data['username']) === false; },
|
||||||
return User::findFirstByUsername($data['username']) === false;
|
|
||||||
},
|
|
||||||
'message' => 'The username already exists.',
|
'message' => 'The username already exists.',
|
||||||
'attribute' => 'username',
|
'attribute' => 'username',
|
||||||
])
|
])
|
||||||
|
|
@ -93,9 +87,7 @@ class Registration extends FormBase
|
||||||
|
|
||||||
$email->addValidators([
|
$email->addValidators([
|
||||||
new CallbackValidator([
|
new CallbackValidator([
|
||||||
'callback' => function ($data) {
|
'callback' => function($data) { return User::findFirstByEmail($data['email']) === false; },
|
||||||
return User::findFirstByEmail($data['email']) === false;
|
|
||||||
},
|
|
||||||
'message' => 'This email already exist.',
|
'message' => 'This email already exist.',
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,16 @@ 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;
|
||||||
|
|
@ -25,7 +22,6 @@ 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,
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ 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);
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ 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.
|
||||||
|
|
@ -64,11 +63,8 @@ class Auth extends Injectable
|
||||||
|
|
||||||
$this->setIdentity($user->getId());
|
$this->setIdentity($user->getId());
|
||||||
|
|
||||||
$this->eventsManager->fire(
|
$this->eventsManager->fire('auth:onLogin', $this,
|
||||||
'auth:onLogin',
|
"OAuth {$data->getProvider()}");
|
||||||
$this,
|
|
||||||
"OAuth {$data->getProvider()}"
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return new Result(Result::SUCCESS);
|
return new Result(Result::SUCCESS);
|
||||||
|
|
@ -87,40 +83,6 @@ 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
|
||||||
|
|
@ -170,12 +132,7 @@ class Auth extends Injectable
|
||||||
*/
|
*/
|
||||||
public function clearIdentity()
|
public function clearIdentity()
|
||||||
{
|
{
|
||||||
$imp_id = $this->session->get(self::IMPERSONATOR_ID);
|
|
||||||
if ($imp_id !== null) {
|
|
||||||
$this->impersonateClear($imp_id);
|
|
||||||
} else {
|
|
||||||
$this->session->remove(self::SESSION_KEY);
|
$this->session->remove(self::SESSION_KEY);
|
||||||
}
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,7 @@ 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'],
|
$opt['label-class'], $ele->getName(), $ele->getLabel());
|
||||||
$ele->getName(),
|
|
||||||
$ele->getLabel()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$xhtml .= '<div class="' . implode(' ', $opt['class']) . '">'
|
$xhtml .= '<div class="' . implode(' ', $opt['class']) . '">'
|
||||||
|
|
|
||||||
|
|
@ -126,22 +126,15 @@ class Menu extends Tag
|
||||||
return $xhtml;
|
return $xhtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
$xhtml = self::tagHtml(
|
$xhtml = self::tagHtml('li', $node->isActive()
|
||||||
'li',
|
|
||||||
$node->isActive()
|
|
||||||
? array('class' => $this->_activeClass) : null,
|
? array('class' => $this->_activeClass) : null,
|
||||||
false,
|
false, false, true);
|
||||||
false,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
// Generate the link.
|
// Generate the link.
|
||||||
$xhtml .= self::linkTo($node->getHref(), $node->getCaption());
|
$xhtml .= self::linkTo($node->getHref(), $node->getCaption());
|
||||||
|
|
||||||
if (
|
if ($node->isActive() && $node->hasChildren()
|
||||||
$node->isActive() && $node->hasChildren()
|
&& ($max_depth === null || $depth < $max_depth)) {
|
||||||
&& ($max_depth === null || $depth < $max_depth)
|
|
||||||
) {
|
|
||||||
|
|
||||||
$xhtml .= $this->_renderMenu($node->getChildren(), $depth + 1, $max_depth);
|
$xhtml .= $this->_renderMenu($node->getChildren(), $depth + 1, $max_depth);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,3 +81,4 @@ class Container
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,6 @@ use Phalcon\Di\FactoryDefault as DiDefault,
|
||||||
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;
|
||||||
|
|
||||||
|
|
@ -32,8 +30,7 @@ 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
|
||||||
{
|
{
|
||||||
|
|
@ -49,7 +46,8 @@ class Services extends DiDefault
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
@ -179,11 +177,8 @@ 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($factory, $options);
|
return new $class($options);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, default to Memory.
|
// Otherwise, default to Memory.
|
||||||
|
|
@ -200,11 +195,8 @@ class Services extends DiDefault
|
||||||
$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($factory, $options);
|
$adapter = new $class($options);
|
||||||
}
|
}
|
||||||
// Default to Stream
|
// Default to Stream
|
||||||
else {
|
else {
|
||||||
|
|
@ -318,7 +310,7 @@ class Services extends DiDefault
|
||||||
$config = $this->get('config')->router;
|
$config = $this->get('config')->router;
|
||||||
|
|
||||||
// Create the router
|
// Create the router
|
||||||
$router = new Router(false);
|
$router = new Router();
|
||||||
$router->removeExtraSlashes($config->get('removeExtraSlashes', false));
|
$router->removeExtraSlashes($config->get('removeExtraSlashes', false));
|
||||||
|
|
||||||
foreach($config->routes as $name => $def) {
|
foreach($config->routes as $name => $def) {
|
||||||
|
|
@ -335,9 +327,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -348,7 +337,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,19 +23,6 @@ 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
|
||||||
|
|
@ -78,21 +65,9 @@ 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(true);
|
$ip = (new \Phalcon\Http\Request())->getClientAddress();
|
||||||
|
|
||||||
return (new ActivityLogger())->assign([
|
return (new ActivityLogger())->assign([
|
||||||
'user_id' => $user->getId(),
|
'user_id' => $user->getId(),
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
<?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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -10,12 +10,8 @@ class CreateRequestMetaTable extends AbstractMigration
|
||||||
$table = $this->table('request_meta');
|
$table = $this->table('request_meta');
|
||||||
|
|
||||||
$table->addColumn('callbackid', 'integer');
|
$table->addColumn('callbackid', 'integer');
|
||||||
$table->addForeignKey(
|
$table->addForeignKey('callbackid', 'callback', [ 'id' ],
|
||||||
'callbackid',
|
[ 'constraint' => 'FK_callback' ]);
|
||||||
'callback',
|
|
||||||
['id'],
|
|
||||||
['constraint' => 'FK_callback']
|
|
||||||
);
|
|
||||||
|
|
||||||
$table->addColumn('source_ip', 'string', [
|
$table->addColumn('source_ip', 'string', [
|
||||||
'limit' => 50,
|
'limit' => 50,
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,8 @@ class CreateRequestObjectTable extends AbstractMigration
|
||||||
{
|
{
|
||||||
$table = $this->table('request_object');
|
$table = $this->table('request_object');
|
||||||
|
|
||||||
$table->addForeignKey(
|
$table->addForeignKey('id', 'request_meta', ['id'],
|
||||||
'id',
|
[ 'constraint' => 'FK_request_meta' ]);
|
||||||
'request_meta',
|
|
||||||
['id'],
|
|
||||||
['constraint' => 'FK_request_meta']
|
|
||||||
);
|
|
||||||
|
|
||||||
$table->addColumn('headers', 'blob', [
|
$table->addColumn('headers', 'blob', [
|
||||||
'null' => true,
|
'null' => true,
|
||||||
|
|
|
||||||
|
|
@ -265,16 +265,6 @@ 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
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -44,3 +44,4 @@ abstract class Base implements ModuleDefinitionInterface
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@
|
||||||
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,13 +56,6 @@
|
||||||
{% 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,7 +20,6 @@
|
||||||
<th>Email</th>
|
<th>Email</th>
|
||||||
<th>Type</th>
|
<th>Type</th>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<th> </th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
|
|
@ -37,12 +36,7 @@
|
||||||
<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><span class="badge {{ item.isActive() ? 'badge-success' : 'badge-danger' }}">{{ item.status }}</span></td>
|
<td>{{ item.status }}</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,7 +7,6 @@
|
||||||
"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,12 +1,11 @@
|
||||||
{
|
{
|
||||||
"name": "httpcb",
|
"name": "httpcb",
|
||||||
"version": "1.1.0",
|
"version": "1.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "httpcb",
|
"version": "1.1",
|
||||||
"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.0",
|
"version": "1.1",
|
||||||
"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