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
|
||||
prefix: _httpcb_sess_
|
||||
|
||||
#sendgrid
|
||||
#sendgrid:
|
||||
#key: value
|
||||
|
||||
# OAuth
|
||||
|
|
|
|||
|
|
@ -4,58 +4,61 @@ router:
|
|||
routes:
|
||||
home-route:
|
||||
pattern: '/'
|
||||
path:
|
||||
controller: index
|
||||
action: index
|
||||
path: Index::index
|
||||
about-route:
|
||||
pattern: '/about'
|
||||
path:
|
||||
controller: index
|
||||
action: about
|
||||
path: Index::about
|
||||
|
||||
# Callbacks
|
||||
|
||||
cb-list:
|
||||
pattern: '/callback/list'
|
||||
path: Callback::list
|
||||
cb-new:
|
||||
pattern: '/callback/new'
|
||||
path: Callback::new
|
||||
cb-created:
|
||||
pattern: '/callback/created/{id}'
|
||||
path:
|
||||
controller: callback
|
||||
action: created
|
||||
path: Callback::created
|
||||
cb-show:
|
||||
pattern: '/callback/show/{id}'
|
||||
path: Callback::show
|
||||
cb-endpoint:
|
||||
pattern: '/cb/{id}/:params'
|
||||
path:
|
||||
controller: api
|
||||
action: endpoint
|
||||
path: Api::endpoint
|
||||
|
||||
# login
|
||||
|
||||
login:
|
||||
pattern: '/login'
|
||||
path:
|
||||
controller: auth
|
||||
action: index
|
||||
path: Auth::index
|
||||
logout:
|
||||
pattern: '/logout'
|
||||
path:
|
||||
controller: auth
|
||||
action: logout
|
||||
path: Auth::logout
|
||||
oauth:
|
||||
pattern: '/login/{strategy:([a-z]+)}/:params'
|
||||
path:
|
||||
controller: auth
|
||||
action: oauth
|
||||
path: Auth::oauth
|
||||
oauth-disconnect:
|
||||
pattern: '/oauth/{provider:([a-z]+)}/disconnect'
|
||||
path: 'User::oauthdisconnect'
|
||||
oauth-disconnect-confirm:
|
||||
pattern: '/oauth/{provider:([a-z]+)}/disconnect/{confirm}'
|
||||
path: 'User::oauthdisconnect'
|
||||
|
||||
# User
|
||||
|
||||
user-register:
|
||||
pattern: '/register'
|
||||
path: Auth::register
|
||||
user-settings:
|
||||
pattern: '/settings'
|
||||
path:
|
||||
controller: user
|
||||
action: settings
|
||||
path: User::settings
|
||||
user-activity-log:
|
||||
pattern: '/user/activity'
|
||||
path: User::activity
|
||||
activation-link:
|
||||
pattern: '/activate/{link}'
|
||||
path:
|
||||
controller: api
|
||||
action: activationlink
|
||||
path: Api::activationlink
|
||||
|
||||
# Backend
|
||||
backend-home:
|
||||
|
|
@ -70,12 +73,15 @@ router:
|
|||
backend-user-edit:
|
||||
pattern: '/admin/user/{id:([0-9]+)}'
|
||||
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:
|
||||
pattern: '/admin/user/{id:([0-9]+)}/{type}'
|
||||
path:
|
||||
module: backend
|
||||
controller: user
|
||||
action: status
|
||||
pattern: '/admin/user/{id:([0-9]+)}/status/{type}'
|
||||
path: backend::user::status
|
||||
backend-log:
|
||||
pattern: '/admin/log{page:/?([0-9]+)?}'
|
||||
path: backend::log::index
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use App\Controller\ControllerBase,
|
|||
App\Model\Data\Callback as CallbackModel,
|
||||
App\Model\Data\Request as RequestModel,
|
||||
App\Model\Data\RequestMeta as RequestMetaModel,
|
||||
App\Model\Data\User,
|
||||
App\Model\Data\UserActivation;
|
||||
|
||||
class ApiController extends ControllerBase
|
||||
|
|
|
|||
|
|
@ -118,8 +118,11 @@ class AuthController extends ControllerBase
|
|||
}
|
||||
|
||||
$user = new User();
|
||||
$user->assign($data->toArray(), null,
|
||||
[ 'email', 'username', 'firstname', 'lastname' ]);
|
||||
$user->assign(
|
||||
$data->toArray(),
|
||||
null,
|
||||
['email', 'username', 'firstname', 'lastname']
|
||||
);
|
||||
|
||||
$form = new RegistrationForm($user);
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ class CallbackController extends ControllerBase
|
|||
|
||||
return $this->response->redirect(array(
|
||||
'for' => 'cb-created',
|
||||
'id' => $callback->getPublicId()));
|
||||
'id' => $callback->getPublicId()
|
||||
));
|
||||
} else {
|
||||
foreach ($callback->getMessages() as $msg) {
|
||||
$this->flash->error($msg);
|
||||
|
|
@ -71,8 +72,6 @@ class CallbackController extends ControllerBase
|
|||
$msg .= '</ul>';
|
||||
$this->flash->message('error', $msg);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
$this->view->form = $form;
|
||||
|
|
@ -85,7 +84,6 @@ class CallbackController extends ControllerBase
|
|||
{
|
||||
$row = CallbackModel::get($id);
|
||||
if (!$row) {
|
||||
|
||||
}
|
||||
$this->view->id = $id;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ class ControllerBase extends Controller
|
|||
protected function _forward404()
|
||||
{
|
||||
$this->dispatcher->forward(array(
|
||||
'namespace' => 'App\\Controller',
|
||||
'controller' => 'error',
|
||||
'action' => 'show404'
|
||||
));
|
||||
|
|
|
|||
|
|
@ -15,4 +15,3 @@ class IndexController extends ControllerBase
|
|||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,8 +44,11 @@ class UserController extends ControllerBase
|
|||
]);
|
||||
|
||||
// Send the email.
|
||||
$this->di->getMail()->send('Httpcb password activation',
|
||||
$user->getEmail(), $content);
|
||||
$this->di->getMail()->send(
|
||||
'Httpcb password activation',
|
||||
$user->getEmail(),
|
||||
$content
|
||||
);
|
||||
|
||||
$msg = "For security reasons. Before a password can be created "
|
||||
. "a email has been sent to <strong>{$user->getEmail()}</strong> with "
|
||||
|
|
|
|||
|
|
@ -97,4 +97,33 @@ class UserController extends \Phalcon\Mvc\Controller
|
|||
$this->flash->success('The account was: ' . $status);
|
||||
$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
|
||||
*/
|
||||
|
||||
use Phalcon\Forms\Element\Text;
|
||||
use Phalcon\Forms\Element\Submit;
|
||||
|
||||
/**
|
||||
* Validators
|
||||
*/
|
||||
|
||||
use Phalcon\Validation\Validator\StringLength;
|
||||
|
||||
class CallbackCreate extends Form
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use Phalcon\Forms\Form;
|
|||
/**
|
||||
* Element types
|
||||
*/
|
||||
|
||||
use Phalcon\Forms\Element\Text;
|
||||
use Phalcon\Forms\Element\Password;
|
||||
use Phalcon\Forms\Element\Submit;
|
||||
|
|
@ -14,6 +15,7 @@ use Phalcon\Forms\Element\Submit;
|
|||
/**
|
||||
* Validators
|
||||
*/
|
||||
|
||||
use Phalcon\Validation\Validator\PresenceOf;
|
||||
use Phalcon\Validation\Validator\Email as EmailValidator;
|
||||
use Phalcon\Validation\Validator\StringLength;
|
||||
|
|
|
|||
|
|
@ -5,16 +5,19 @@ namespace App\Form;
|
|||
/**
|
||||
* Models
|
||||
*/
|
||||
|
||||
use App\Model\Data\User;
|
||||
|
||||
/**
|
||||
* Phalcon Form
|
||||
*/
|
||||
|
||||
use Httpcb\Form as FormBase;
|
||||
|
||||
/**
|
||||
* Element types
|
||||
*/
|
||||
|
||||
use Phalcon\Forms\Element\Text,
|
||||
Phalcon\Forms\Element\Password,
|
||||
Phalcon\Forms\Element\Submit;
|
||||
|
|
@ -22,6 +25,7 @@ use Phalcon\Forms\Element\Text,
|
|||
/**
|
||||
* Validators
|
||||
*/
|
||||
|
||||
use Phalcon\Validation,
|
||||
Phalcon\Validation\Validator\Callback as CallbackValidator,
|
||||
Phalcon\Validation\Validator\Alnum as AlnumValidator,
|
||||
|
|
@ -54,7 +58,9 @@ class Registration extends FormBase
|
|||
'messageMinimum' => 'Username must be at least :min characters long.',
|
||||
]),
|
||||
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.',
|
||||
'attribute' => 'username',
|
||||
])
|
||||
|
|
@ -87,7 +93,9 @@ class Registration extends FormBase
|
|||
|
||||
$email->addValidators([
|
||||
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.',
|
||||
])
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -5,16 +5,19 @@ namespace App\Form;
|
|||
/**
|
||||
* Models
|
||||
*/
|
||||
|
||||
use App\Model\Data\User as UserModel;
|
||||
|
||||
/**
|
||||
* Form
|
||||
*/
|
||||
|
||||
use Httpcb\Form as FormBase;
|
||||
|
||||
/**
|
||||
* Element types
|
||||
*/
|
||||
|
||||
use Phalcon\Forms\Element\Text,
|
||||
Phalcon\Forms\Element\Password,
|
||||
Phalcon\Forms\Element\Submit;
|
||||
|
|
@ -22,6 +25,7 @@ use Phalcon\Forms\Element\Text,
|
|||
/**
|
||||
* Validators
|
||||
*/
|
||||
|
||||
use Phalcon\Validation\Validator\Callback as CallbackValidator,
|
||||
Phalcon\Validation\Validator\Uniqueness as UniquenessValidator,
|
||||
Phalcon\Validation\Validator\Alnum as AlnumValidator,
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@ class Acl
|
|||
if ($def instanceof Config) {
|
||||
$inherits = $def->get('inherits');
|
||||
$description = $def->get('description');
|
||||
|
||||
}
|
||||
|
||||
$role = new Role($name, $description);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use App\Model\Data\User,
|
|||
class Auth extends Injectable
|
||||
{
|
||||
const SESSION_KEY = 'auth';
|
||||
const IMPERSONATOR_ID = 'auth.impersonator';
|
||||
|
||||
/**
|
||||
* Login using email/user + password combination.
|
||||
|
|
@ -63,8 +64,11 @@ class Auth extends Injectable
|
|||
|
||||
$this->setIdentity($user->getId());
|
||||
|
||||
$this->eventsManager->fire('auth:onLogin', $this,
|
||||
"OAuth {$data->getProvider()}");
|
||||
$this->eventsManager->fire(
|
||||
'auth:onLogin',
|
||||
$this,
|
||||
"OAuth {$data->getProvider()}"
|
||||
);
|
||||
|
||||
|
||||
return new Result(Result::SUCCESS);
|
||||
|
|
@ -83,6 +87,40 @@ class Auth extends Injectable
|
|||
$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
|
||||
* @return Auth
|
||||
|
|
@ -132,7 +170,12 @@ class Auth extends Injectable
|
|||
*/
|
||||
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);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
namespace Httpcb;
|
||||
|
||||
class Debug {
|
||||
class Debug
|
||||
{
|
||||
|
||||
public static function dump($var, $label = null, $echo = true)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -53,7 +53,10 @@ class Form extends FormBase
|
|||
|
||||
$xhtml .= sprintf(
|
||||
'<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']) . '">'
|
||||
|
|
|
|||
|
|
@ -126,15 +126,22 @@ class Menu extends Tag
|
|||
return $xhtml;
|
||||
}
|
||||
|
||||
$xhtml = self::tagHtml('li', $node->isActive()
|
||||
$xhtml = self::tagHtml(
|
||||
'li',
|
||||
$node->isActive()
|
||||
? array('class' => $this->_activeClass) : null,
|
||||
false, false, true);
|
||||
false,
|
||||
false,
|
||||
true
|
||||
);
|
||||
|
||||
// Generate the link.
|
||||
$xhtml .= self::linkTo($node->getHref(), $node->getCaption());
|
||||
|
||||
if ($node->isActive() && $node->hasChildren()
|
||||
&& ($max_depth === null || $depth < $max_depth)) {
|
||||
if (
|
||||
$node->isActive() && $node->hasChildren()
|
||||
&& ($max_depth === null || $depth < $max_depth)
|
||||
) {
|
||||
|
||||
$xhtml .= $this->_renderMenu($node->getChildren(), $depth + 1, $max_depth);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,4 +81,3 @@ class Container
|
|||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ use Phalcon\Di\FactoryDefault as DiDefault,
|
|||
Phalcon\Cache\Frontend\Data as FrontendDataCache,
|
||||
Phalcon\Cache\Backend\Apc as BackendApcCache,
|
||||
Phalcon\Translate\Adapter\NativeArray as TranslateAdapter,
|
||||
Phalcon\Storage\AdapterFactory as StorageAdapterFactory,
|
||||
Phalcon\Cache\AdapterFactory as CacheAdapterFactory,
|
||||
Phalcon\Logger,
|
||||
Phalcon\Mvc\Router;
|
||||
|
||||
|
|
@ -30,7 +32,8 @@ use Httpcb\Auth,
|
|||
|
||||
use App\Listener\AccessListener,
|
||||
App\Listener\DispatchListener,
|
||||
App\Listener\ActivityLog;
|
||||
App\Listener\ActivityLog,
|
||||
App\Listener\AuthEmailListener;
|
||||
|
||||
class Services extends DiDefault
|
||||
{
|
||||
|
|
@ -46,8 +49,7 @@ class Services extends DiDefault
|
|||
if (substr($method->getName(), 0, 11) == '_initShared') {
|
||||
$service = lcfirst(substr($method->getName(), 11));
|
||||
$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));
|
||||
$this->set($service, $method->getClosure($this));
|
||||
}
|
||||
|
|
@ -177,8 +179,11 @@ class Services extends DiDefault
|
|||
$options = $mdConfig['options'];
|
||||
$adapter = $mdConfig['adapter'];
|
||||
|
||||
$serializerFactory = new \Phalcon\Storage\SerializerFactory();
|
||||
$factory = new CacheAdapterFactory($serializerFactory);
|
||||
|
||||
$class = 'Phalcon\Mvc\Model\MetaData\\' . $adapter;
|
||||
return new $class($options);
|
||||
return new $class($factory, $options);
|
||||
}
|
||||
|
||||
// Otherwise, default to Memory.
|
||||
|
|
@ -195,8 +200,11 @@ class Services extends DiDefault
|
|||
$adapter_name = isset($data['adapter']) ? $data['adapter'] : 'Stream';
|
||||
$options = $data['options'];
|
||||
|
||||
$serializerFactory = new \Phalcon\Storage\SerializerFactory();
|
||||
$factory = new StorageAdapterFactory($serializerFactory);
|
||||
|
||||
$class = 'Phalcon\Session\Adapter\\' . $adapter_name;
|
||||
$adapter = new $class($options);
|
||||
$adapter = new $class($factory, $options);
|
||||
}
|
||||
// Default to Stream
|
||||
else {
|
||||
|
|
@ -310,7 +318,7 @@ class Services extends DiDefault
|
|||
$config = $this->get('config')->router;
|
||||
|
||||
// Create the router
|
||||
$router = new Router();
|
||||
$router = new Router(false);
|
||||
$router->removeExtraSlashes($config->get('removeExtraSlashes', false));
|
||||
|
||||
foreach ($config->routes as $name => $def) {
|
||||
|
|
@ -327,6 +335,9 @@ class Services extends DiDefault
|
|||
$router->add($def->get('pattern'), $path)
|
||||
->setName($name);
|
||||
}
|
||||
|
||||
$router->notFound(['controller' => 'error', 'action' => 'show404']);
|
||||
|
||||
return $router;
|
||||
}
|
||||
|
||||
|
|
@ -337,6 +348,7 @@ class Services extends DiDefault
|
|||
$eventsManager = new \Phalcon\Events\Manager();
|
||||
$eventsManager->attach('user', $activityLog);
|
||||
$eventsManager->attach('auth', $activityLog);
|
||||
$eventsManager->attach('auth', new AuthEmailListener);
|
||||
|
||||
return $eventsManager;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@ class ServerUrl extends AbstractHelper
|
|||
|
||||
// remove port if it's the default port.
|
||||
if (($scheme == 'http' && $port == 80)
|
||||
|| ($scheme == 'https' && $port == 443)) {
|
||||
|| ($scheme == 'https' && $port == 443)
|
||||
) {
|
||||
$port = null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,19 @@ class ActivityLog extends Injectable
|
|||
$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 User $auth
|
||||
|
|
@ -65,9 +78,21 @@ class ActivityLog extends Injectable
|
|||
$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)
|
||||
{
|
||||
$ip = (new \Phalcon\Http\Request())->getClientAddress();
|
||||
$ip = (new \Phalcon\Http\Request())->getClientAddress(true);
|
||||
|
||||
return (new ActivityLogger())->assign([
|
||||
'user_id' => $user->getId(),
|
||||
|
|
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -10,8 +10,12 @@ class CreateRequestMetaTable extends AbstractMigration
|
|||
$table = $this->table('request_meta');
|
||||
|
||||
$table->addColumn('callbackid', 'integer');
|
||||
$table->addForeignKey('callbackid', 'callback', [ 'id' ],
|
||||
[ 'constraint' => 'FK_callback' ]);
|
||||
$table->addForeignKey(
|
||||
'callbackid',
|
||||
'callback',
|
||||
['id'],
|
||||
['constraint' => 'FK_callback']
|
||||
);
|
||||
|
||||
$table->addColumn('source_ip', 'string', [
|
||||
'limit' => 50,
|
||||
|
|
|
|||
|
|
@ -9,8 +9,12 @@ class CreateRequestObjectTable extends AbstractMigration
|
|||
{
|
||||
$table = $this->table('request_object');
|
||||
|
||||
$table->addForeignKey('id', 'request_meta', ['id'],
|
||||
[ 'constraint' => 'FK_request_meta' ]);
|
||||
$table->addForeignKey(
|
||||
'id',
|
||||
'request_meta',
|
||||
['id'],
|
||||
['constraint' => 'FK_request_meta']
|
||||
);
|
||||
|
||||
$table->addColumn('headers', 'blob', [
|
||||
'null' => true,
|
||||
|
|
|
|||
|
|
@ -265,6 +265,16 @@ class User extends Base
|
|||
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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -44,4 +44,3 @@ abstract class Base implements ModuleDefinitionInterface
|
|||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
data-bs-toggle="dropdown" role="button" aria-expanded="false">
|
||||
|
||||
{{ icon('solid/user') }} <strong>{{ auth.getUser().username }}</strong>
|
||||
{% set imp = auth.getImpersonator() %}
|
||||
{% if imp %}( {{ icon('solid/user-secret') }} {{ imp.username }} ){% endif %}
|
||||
</a>
|
||||
|
||||
<ul class="dropdown-menu navigation-user-menu-dropdown-list">
|
||||
|
|
|
|||
|
|
@ -56,6 +56,13 @@
|
|||
{% if (user.getId()) %}
|
||||
{% set actions = [ 'Activate': 'Active', 'Suspend': 'Suspended', 'Delete': 'Deleted' ] %}
|
||||
<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 %}
|
||||
|
||||
{% if (user.status != status) %}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
<th>Email</th>
|
||||
<th>Type</th>
|
||||
<th>Status</th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
|
|
@ -36,7 +37,12 @@
|
|||
<td>{{ item.name }}</td>
|
||||
<td>{{ item.email }}</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>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
"ext-psr": ">=1.2",
|
||||
"ext-redis": "*",
|
||||
"ext-yaml": "*",
|
||||
"ext-mbstring": "*",
|
||||
"robmorgan/phinx": "^0.10.6",
|
||||
"league/oauth2-client": "^2.3",
|
||||
"league/oauth2-github": "^2.0",
|
||||
|
|
|
|||
5
package-lock.json
generated
5
package-lock.json
generated
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"name": "httpcb",
|
||||
"version": "1.1",
|
||||
"version": "1.1.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"version": "1.1",
|
||||
"name": "httpcb",
|
||||
"version": "1.1.0",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@popperjs/core": "^2.11.5",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "httpcb",
|
||||
"version": "1.1",
|
||||
"version": "1.1.0",
|
||||
"description": "HTTP Callback Tool",
|
||||
"devDependencies": {
|
||||
"@popperjs/core": "^2.11.5",
|
||||
|
|
|
|||
Reference in a new issue