Пример #1
0
 public function index(string $jwt, string $url = '')
 {
     if ($payload = $this->jwtEx->decode($jwt)) {
         if ($user_id = $payload->user_id ?? 0) {
             if ($user = User::find($user_id)) {
                 if (!empty($payload->authorize)) {
                     /** @var User $user */
                     if ($user->verified == 'n') {
                         $user->ip_addr = $this->sniffer->getUserIP();
                         $user->verified = 'y';
                         $user->save();
                     }
                     $this->session->startSession($user_id);
                 }
                 if (!empty($payload->eventName)) {
                     $event = new UserEvent($user_id, $user->toArray());
                     $event->setData($payload->eventData ?? '');
                     $this->dispatcher->fire($payload->eventName, $event);
                 }
             }
         }
     } else {
         $params = ['msg' => 'Sorry this link has expired'];
     }
     return new Redirection($url ?: '/', $params ?? []);
 }
Пример #2
0
 public function parse(GmailEvent $event)
 {
     if (!$event->isHandled()) {
         MSupportTicket::unguard();
         MSupportReply::unguard();
         $info = $event->getFrom();
         $now = Carbon::now();
         if ($email = $info['email'] ?? null) {
             $user = User::where('email', '=', $email)->orWhere('contact_email', '=', $email)->first();
             if (empty($user) || empty($user->user_id)) {
                 $signup = new UserSignupEvent(array_merge($info, ['verified' => 'true']));
                 $this->dispatcher->fire(UserSignupEvent::USER_SIGNUP_BEGIN, $signup);
                 $user = $signup->getUser();
             }
             if (preg_match('/^T(\\d+)$/', $event->getRef(), $matches)) {
                 $ticket = MSupportTicket::find($matches[1]);
             }
             if (empty($ticket) || empty($ticket->ticket_id)) {
                 $ticket = MSupportTicket::where('user_id', '=', $user->user_id)->where('title', '=', $event->getSubject())->first();
                 if (empty($ticket) || empty($ticket->support_ticket_id)) {
                     $ticket = MSupportTicket::create(['user_id' => $user->user_id, 'created_at' => $now, 'updated_at' => $now, 'title' => $event->getSubject(), 'category' => 'General', 'state' => 'open']);
                 }
             }
             /** @var MSupportReply $reply */
             $reply = MSupportReply::create(['support_ticket_id' => $ticket->support_ticket_id, 'user_id' => $user->user_id, 'created_at' => $now, 'reply_safe' => $event->getText()]);
             $event->setHandled($reply->support_reply_id > 0);
         }
     }
 }
Пример #3
0
 public function getCached(ImportEvent $event)
 {
     $data = $this->cache->get('admin-panels-cached', function () use($event) {
         $fresh = new ImportEvent($event->getViewEvent());
         $this->dispatcher->fire(AdminEvent::IMPORT_ADMIN_DASHBOARD_PANELS, $fresh);
         return $fresh->getContent();
     }, 300);
     $event->setContent($data);
 }
Пример #4
0
 public function sendEmail(SupportEvent $event)
 {
     $data = $event->getUserData();
     if ($ticket_id = $data['support_ticket_id'] ?? null) {
         $data['reference'] = $this->blowfish->encrypt('T' . $ticket_id);
         $event->setUserData($data);
     }
     $this->dispatcher->fire("user.send.email", $event);
     //we don't know if mail module is installed
 }
Пример #5
0
 public function index($_params)
 {
     $event = new UserForgotPasswordEvent($_params);
     $this->dispatcher->fire(UserForgotPasswordEvent::USER_FORGOT_PASSWORD, $event);
     if ($event->isHandled()) {
         return json_encode(['update' => 'PASSWORD_SENT']);
     } else {
         throw new UserForgotPasswordError($event->getError() ?: 'UNKNOWN_ERROR');
     }
 }
Пример #6
0
 public function index($_params)
 {
     $event = new UserLoginEvent($_params);
     $this->dispatcher->fire(UserLoginEvent::USER_LOGIN_AUTHENTICATE, $event);
     if ($user = $event->getUser()) {
         $this->session->startSession($user->user_id);
         return json_encode(['update' => ['user' => $user], 'event' => 'session_user_login']);
     } else {
         throw new UserLoginError($event->getError() ?: 'UNKNOWN_ERROR');
     }
 }
Пример #7
0
 public function registerUser($_params)
 {
     $event = new UserSignupEvent($_params);
     $this->dispatcher->fire(UserSignupEvent::USER_SIGNUP_BEGIN, $event);
     if ($user = $event->getUser()) {
         $this->session->startSession($user->user_id);
         return $user;
     } else {
         throw new UserSignupError($event->getError() ?: 'UNKNOWN_ERROR');
     }
 }
Пример #8
0
 public function update($email, $password)
 {
     if (!empty($email) && !empty($password) && filter_var($email, FILTER_VALIDATE_EMAIL)) {
         if ($user = User::find($this->session->getLoggedInUserId())) {
             $event = new UserUpdateDataEvent($user, ['email' => $email, 'password' => $password]);
             $this->dispatcher->fire(UserUpdateDataEvent::USER_UPDATE_DATA, $event);
             if ($event->isHandled()) {
                 return 'pass';
             }
         }
     }
     throw new UserUpdateDataError("Unable to update credentials");
 }
Пример #9
0
 /**
  * Bind listeners defined in plugins, app and Database
  */
 public function bind()
 {
     $listeners = $this->cache->get('app-listeners', function () {
         foreach ($this->resolver->getListeners() as $file) {
             try {
                 $binding = $this;
                 require_once $file;
             } catch (\Throwable $e) {
                 $this->logger->warn("Unable to include {$file}: " . $e->getMessage());
             }
         }
         $listeners = $this->getListeners();
         if ($this->database->isConnected()) {
             /** @var ModelEx $eventModel */
             if ($eventModel = $this->resolver->getModel('Event', true)) {
                 try {
                     foreach ($eventModel::all() as $item) {
                         $attrs = $item->attributesToArray();
                         list($class, $func) = @explode('@', $attrs['handler']);
                         $event = array_merge($attrs, ['event' => $attrs['name'], 'handler' => [sprintf('\\%s', ltrim($class, '\\')), $func ?? 'index']]);
                         $listeners[] = $event;
                     }
                 } catch (\Exception $e) {
                 }
             }
         }
         return $listeners;
     }, 300);
     foreach ($listeners as $listener) {
         $this->dispatcher->listen($listener['event'], $listener['handler'], $listener['priority'] ?? 99, $listener['data'] ?? '');
     }
 }
Пример #10
0
 public function index($_params)
 {
     if (!empty($_params['password'])) {
         if ($user = User::find($this->session->getLoggedInUserId())) {
             $event = new UserUpdateDataEvent($user, ['password' => $_params['password']]);
             $this->dispatcher->fire(UserUpdateDataEvent::USER_UPDATE_DATA, $event);
             if ($event->isHandled()) {
                 return json_encode(['update' => 'PASSWORD_RESET']);
             } else {
                 throw new UserUpdateDataError($event->getError() ?: 'UNKNOWN_ERROR');
             }
         } else {
             throw new UserUpdateDataError('UNKNOWN_USER');
         }
     } else {
         throw new UserUpdateDataError('INVALID_DATA');
     }
 }
Пример #11
0
 public function index(string $_mode, array $_models, RouteEx $_route, array $_parents, string $alias)
 {
     $return = $this->postHandler->index($_mode, $_models, $_route, $_parents, $alias);
     $model = $_models[0];
     if ($model instanceof MSupportTicket) {
         $eventName = 'admin.support.' . 'status';
         $ticketData = $model->attributesToArray();
     } elseif ($model instanceof MSupportReply) {
         $eventName = 'admin.support.' . 'reply';
         /** @var MSupportTicket $ticket */
         if ($ticket = MSupportTicket::find($model->support_ticket_id)) {
             $ticketData = array_merge($model->attributesToArray(), $ticket->attributesToArray());
         }
     }
     if (!empty($eventName) && !empty($ticketData)) {
         $this->dispatcher->fire($eventName, new SupportEvent($model->user_id, $ticketData));
     }
     return $return;
 }
Пример #12
0
 public function authenticate(UserLoginEvent $event)
 {
     if (empty($event->getUser()) && ($email = $event->email) && ($password = $event->password)) {
         //make sure the user isn't already authenticated!
         if ($user = User::where('email', '=', $email)->first()) {
             if (true || password_verify($password, $user->password)) {
                 $event->setUser($user);
                 $this->dispatcher->fire(UserLoginEvent::USER_LOGIN_SUCCESS, $event);
             } else {
                 $event->setError('PASSWORD_INVALID');
             }
         } else {
             $event->setError('EMAIL_INVALID');
         }
     } else {
         $event->setError('INVALID_INPUT');
     }
     if (!$event->getUser()) {
         //for logging
         $this->dispatcher->fire(UserLoginEvent::USER_LOGIN_FAIL, $event);
     }
 }
Пример #13
0
 public function sendMails()
 {
     if ($mails = MArQueue::where('status', '=', 'pending')->where('send_at', '<=', Carbon::now())->get()) {
         /** @var MArQueue $mail */
         foreach ($mails as $mail) {
             $user_id = $mail->user_id;
             if (!empty($seen[$user_id])) {
                 print "Deferring mail to user #{$user_id} for 1 hour\n";
                 $mail->send_at = Carbon::now()->addHours(1);
                 $mail->save();
             } else {
                 $event = new UserMailEvent($user_id);
                 $event->setData(['mail_id', '=', $mail->mail_id]);
                 $this->dispatcher->fire(UserMailEvent::USER_SEND_EMAIL, $event);
                 $mail->status = $event->isHandled() ? 'pass' : 'fail';
                 $mail->save();
                 $seen[$user_id] = $event->isHandled();
                 print ($event->isHandled() ? "Successfully sent" : "Unable to send") . " mail to user #{$user_id}\n";
             }
         }
     }
 }
Пример #14
0
 protected function startQueryLog()
 {
     $this->logFile = $this->tmpDir->getTempDir('logs') . '/query.log';
     @unlink($this->logFile);
     $this->connection->enableQueryLog();
     $this->logger->pushHandler(new StreamHandler($this->logFile, LoggerEx::INFO));
     $this->dispatcher->listen(QueryExecuted::class, function (QueryExecuted $query) {
         $sql = preg_replace_callback('/\\?/', function () use($query, &$index) {
             return sprintf("'%s'", $query->bindings[$index++ ?? 0]);
         }, $query->sql);
         $this->logger->info($sql);
     });
 }
Пример #15
0
 /**
  * @param $provider
  *
  * @throws HybridAuthError
  */
 public function index($provider)
 {
     if (isset($_REQUEST['hauth_start']) || isset($_REQUEST['hauth_done'])) {
         Hybrid_Endpoint::process();
     } else {
         try {
             $map = ['Facebook' => 'id', 'Google' => 'id', 'GitHub' => 'id'];
             $settings = ['Facebook' => ['scope' => 'email', 'display' => 'popup'], 'Google' => ['scope' => 'https://www.googleapis.com/auth/userinfo.email'], 'Twitter' => ['includeEmail' => true]];
             $config = $this->providers->getProvider($provider);
             if (!empty($config['key']) && !empty($config['secret'])) {
                 $pConfig = array_merge(['enabled' => true, "keys" => [$map[$provider] ?? 'key' => $config['key'], 'secret' => $config['secret']]], $settings[$provider] ?? []);
                 $config = ["providers" => [$provider => $pConfig]];
                 $hauth = new Hybrid_Auth($config);
                 $auth = $hauth->authenticate($provider);
                 if ($profile = $auth->getUserProfile()) {
                     $event = 'session_user_login';
                     $data = ['ident' => $profile->identifier, 'email' => $profile->email, 'first_name' => $profile->firstName, 'last_name' => $profile->lastName, 'photo_url' => $profile->photoURL, 'verified' => 'true'];
                     /** @var User $user */
                     if ($user = User::where('ident', '=', $profile->identifier)->first()) {
                         if (empty($user->email) && !empty($profile->email)) {
                             $user->email = $profile->email;
                             $user->save();
                         }
                         if (!empty($profile->email)) {
                             $user->contact_email = $profile->email;
                             $user->save();
                         }
                     } elseif (!empty($profile->email) && ($user = User::where('email', '=', $profile->email)->first())) {
                         $user->ident = $profile->identifier;
                         $user->save();
                     } else {
                         $user = $this->signupHandler->registerUser($data);
                         $event = 'session_user_signup';
                     }
                     if ($user_id = $user->user_id ?? null) {
                         $this->session->startSession($user_id);
                         $socialEvent = new UserSocialEvent($user->user_id, array_merge((array) $profile, ['provider' => $provider]));
                         $this->dispatcher->fire($event === 'session_user_signup' ? UserSocialEvent::USER_SOCIAL_SIGNUP : UserSocialEvent::USER_SOCIAL_LOGIN, $socialEvent);
                         $userData = json_encode(['user' => $user->toArray()]);
                         printf("<scrip" . "t>try { self.opener.Minute.setSessionData(%s, '%s'); } catch(err) { console.log(err); } finally { self.window.close(); }</script>", $userData, $event);
                     }
                 }
             } else {
                 throw new Exception("Configuration for {$provider} is incomplete");
             }
         } catch (\Throwable $e) {
             Hybrid_Auth::logoutAllProviders();
             throw new HybridAuthError($e->getMessage());
         }
     }
 }
Пример #16
0
 /**
  * Get all <event name="$eventName"></event> tags and fire $eventName events,
  * then replace the <event> tag with the response generated by event handlers.
  *
  */
 public function render()
 {
     $html = !empty($this->layout) ? $this->compiler->replaceContentTagInLayout($this->content ?? '', $this->layout) : $this->content ?? '';
     $event = new ViewParserEvent($this, $html);
     $this->dispatcher->fire(ViewParserEvent::VIEWPARSER_RENDER, $event);
     $output = preg_replace_callback('~(<minute-event.*?</minute-event>)~mi', function ($matches) {
         $tag = $matches[1];
         $attrs = (array) new SimpleXMLElement($tag);
         $attrs = current($attrs);
         $event = new ViewEvent($this, $tag, $attrs);
         $eventName = strtolower(strtr($attrs['name'], ['_' => '.']));
         if (preg_match('/^(user|import)\\./i', $eventName)) {
             if (!empty($attrs['as'])) {
                 $importEvent = new ImportEvent($event, $tag, $attrs);
                 $this->dispatcher->fire($eventName, $importEvent);
                 foreach ($attrs as $k => $v) {
                     if ($k !== 'name' && $k !== 'as') {
                         $values[] = sprintf('%s="%s"', $k, htmlentities($v));
                     }
                 }
                 $data = $importEvent->getContent();
                 $import = sprintf('<minute-importer into="%s" data="%s" %s></minute-importer>', $attrs['as'], htmlentities(json_encode($data ?? [])), join(' ', $values ?? []));
                 $event->setContent($import);
             } else {
                 $this->dispatcher->fire($eventName, $event);
             }
         } else {
             throw new ViewError("Server side event '{$eventName}' failed (server side events may start with USER_ or IMPORT_ only)");
         }
         return $event->getContent();
     }, $event->getHtml());
     /** @var Helper $helper */
     foreach ($this->helpers ?? [] as $helper) {
         if ($content = $helper->getTemplate()) {
             $tagName = $helper->getPosition() === Helper::POSITION_BODY ? '</body>' : '</head>';
             $output = $this->tagUtils->insertBeforeTag($tagName, $content, $output);
         }
     }
     $output = preg_replace_callback('~<title></title>~', function () {
         $url = $this->request->getPath();
         $event = new SeoEvent($url);
         $this->dispatcher->fire(SeoEvent::SEO_GET_TITLE, $event);
         $result = sprintf('<title>%s</title>%s', $event->getTitle() ?: ucwords(trim(join(' ', preg_split('/\\W+/', $url)))), PHP_EOL);
         foreach ($event->getMeta() as $meta) {
             $result .= sprintf('<meta name="%s" content="%s" />%s', $meta['name'], $meta['content'], PHP_EOL);
         }
         return $result;
     }, $output);
     return $output;
 }
Пример #17
0
 /**
  * @param string $permission
  * @param bool $isLoggedInUser
  *
  * @return bool
  */
 protected function canAccessModel(string $permission, bool $isLoggedInUser)
 {
     if ($permission === Permission::NOBODY) {
         return false;
     } elseif ($permission === Permission::EVERYONE) {
         return true;
     } elseif ($permission === Permission::GUEST) {
         return !$isLoggedInUser;
     } elseif ($permission === Permission::ANY_USER || $permission === true) {
         return $isLoggedInUser;
     } elseif ($permission === Permission::SAME_USER) {
         return $isLoggedInUser;
         //but do additional checks depending on operation
     } else {
         $event = new AuthEvent($permission);
         $this->dispatcher->fire(AuthEvent::AUTH_CHECK_ACCESS, $event);
         //the permission is a level like 'admin', 'member', etc
         return $event->isAuthorized();
     }
 }
Пример #18
0
 public function run()
 {
     try {
         $this->boot();
         $event = new RequestEvent($this->request);
         $this->dispatcher->fire(RequestEvent::REQUEST_HANDLE, $event);
         $this->response = $event->getResponse();
     } catch (AuthError $e) {
         $this->response->setStatusCode(401);
     } catch (ResourceNotFoundException $e) {
         $this->response->setStatusCode(404);
     } catch (\Throwable $e) {
         http_response_code(500);
         $this->response->setStatusCode(500);
         if ($e instanceof PrintableError) {
             $this->response->setContent($e->getMessage());
         } else {
             if (preg_match("/Duplicate entry '(.*?)' for key '(.*?)'/", $e->getMessage(), $matches)) {
                 $errorStr = sprintf("DUPLICATE: %s ('%s' is already in use).", ucfirst($matches[2]), $matches[1]);
             } else {
                 if ($this->debug->enabled()) {
                     throw $e;
                 } else {
                     $event = new ExceptionEvent($e);
                     $this->dispatcher->fire(ExceptionEvent::EXCEPTION_UNHANDLED, $event);
                 }
                 if (preg_match("/Unknown column 'user_id'.*from (.*?) /", $e->getMessage(), $matches)) {
                     $errorStr = sprintf("Permission::SAME_USER requires a `user_id` column (which is missing in table {$matches['1']})");
                 } else {
                     $errorStr = 'Internal server error';
                 }
             }
             $this->response->setContent($errorStr);
         }
     }
     if ($this->response->getStatusCode() === 200) {
         $this->dispatcher->fire(ResponseEvent::RESPONSE_RENDER, new ResponseEvent($this->response));
     } else {
         $this->dispatcher->fire(ResponseEvent::RESPONSE_ERROR, new ResponseEvent($this->response));
     }
 }
Пример #19
0
 public function signup(UserSignupEvent $event)
 {
     $signup = [];
     $fields = ['ident', 'email', 'contact_email', 'password', 'first_name', 'last_name', 'photo_url', 'tz_offset', 'ip_addr', 'http_referrer', 'http_campaign', 'verified'];
     $default = function ($field) use($event) {
         if ($field == 'photo_url' && ($email = $event->email)) {
             $gravatar = sprintf("http://www.gravatar.com/avatar/%s?d=404", md5(strtolower($email)));
             if ($headers = get_headers($gravatar, 1)) {
                 if (strpos($headers[0], '200')) {
                     return $gravatar;
                 }
             }
         } elseif ($field == 'contact_email') {
             return $event->email ?? null;
         } elseif ($field == 'password') {
             return bin2hex(openssl_random_pseudo_bytes(4));
         } elseif ($field == 'http_referrer') {
             $value = $_COOKIE[Router::HTTP_REFERRER_COOKIE] ?? '/';
             return $value !== '/' ? $value : null;
         } elseif ($field == 'http_campaign') {
             return $_COOKIE[Router::HTTP_CAMPAIGN_COOKIE] ?? null;
         } elseif ($field == 'tz_offset') {
             return $_COOKIE['tz_offset'] ?? 240;
         } elseif ($field == 'verified') {
             return 'false';
         }
         return null;
     };
     foreach ($fields as $field) {
         $signup[$field] = $event->{$field} ?? $default($field);
         if ($field == 'password') {
             $signup[$field] = password_hash($signup[$field], PASSWORD_DEFAULT);
         }
     }
     if (filter_var($signup['email'] ?? null, FILTER_VALIDATE_EMAIL) || !empty($signup['ident'])) {
         try {
             User::unguard();
             $user = new User($signup);
             $this->modelAutoFill->fillMissing($user);
             if ($user->save()) {
                 $event->setUser($user);
                 $signupEvent = (new UserSignupEvent($signup))->setUser($user);
                 try {
                     $this->dispatcher->fire(UserSignupEvent::USER_SIGNUP_COMPLETE, $signupEvent);
                 } catch (\Throwable $e) {
                     $this->logger->warn("Plugin error during signup: " . $e->getMessage());
                 }
             }
         } catch (QueryException $e) {
             $event->setError("EMAIL_IN_USE");
         } catch (\Exception $e) {
             $event->setError($e->getMessage());
         }
     } else {
         $event->setError('INVALID_DATA');
     }
     if (!$event->getUser()) {
         //for logging
         $this->dispatcher->fire(UserSignupEvent::USER_SIGNUP_FAIL, $event);
     }
 }
Пример #20
0
 public function index()
 {
     $this->dispatcher->fire(UserLogoutEvent::USER_LOGOUT_SUCCESS, new UserLogoutEvent($this->session->getLoggedInUserId()));
     $this->session->destroySession();
     return new Redirection('/');
 }
Пример #21
0
 public function execute(ControllerEvent $event)
 {
     try {
         $params = $event->getParams(true) ?? [];
         $ajaxReq = $params['_contentType'] === 'ajax';
         if ($params['_method'] === 'GET' && ($parents = $params['_parents'] ?? null)) {
             $alias = $ajaxReq ? $params['alias'] : null;
             if ($models = $this->modelLoader->loadModels($parents, $alias)) {
                 $event->setParam('_models', $models);
                 foreach ($models as $key => $value) {
                     $event->setParam($key, $value);
                 }
             }
             foreach ($parents as $key => $value) {
                 $event->setParam("_{$key}", $models[$key] ?? []);
             }
         }
         $args = array_merge([':event' => $event], $event->getParams() ?? []);
         $action = $this->getController($event->getController());
         $final = true;
         $response = $output = $this->injector->execute($action, $args);
         if ($response instanceof Redirection) {
             $this->dispatcher->fire(RedirectEvent::REDIRECT, new RedirectEvent($response));
             //chance to do something with redirection
             $response->redirect();
             //exists
         } else {
             if ($response instanceof HttpResponseEx) {
                 $event->setResponse($this->response);
             } else {
                 if ($response instanceof View) {
                     if ($ajaxReq && !empty($alias) && !empty($models)) {
                         $output = '{}';
                         /** @var CollectionEx $model */
                         foreach ($models as $tlp => $model) {
                             if ($array = $model->toArray()) {
                                 if ($child = $tlp === $alias ? $array : $this->findChildByAlias($array, $alias)) {
                                     $output = json_encode($child, JSON_PRETTY_PRINT);
                                 }
                             }
                         }
                     } else {
                         /** @var View $view */
                         $view = $response;
                         $final = $response->isFinal();
                         $this->viewParser->setHelpers($view->getHelpers());
                         $this->viewParser->setLayout($view->getLayout());
                         $this->viewParser->setAdditionalLayoutFiles($view->getAdditionalLayoutFiles());
                         $this->viewParser->setVars(array_merge($event->getParams(true) ?? [], $view->getVars() ?? []));
                         if ($content = $view->getContent()) {
                             if (!empty($view->getViewFile())) {
                                 trigger_error('You should only specify either content or view file');
                             }
                             $this->viewParser->setContent($content);
                         } elseif ($templatePath = $view->getViewFile()) {
                             $this->viewParser->loadViewFile($templatePath, $view->isPathLayouts());
                         } elseif (empty($view->getViewFile())) {
                             if (is_string($event->getController())) {
                                 @(list($class) = explode('@', $event->getController(), 2));
                                 $this->viewParser->loadViewFile($class, $view->isPathLayouts());
                             } else {
                                 throw new ControllerError("View must be explicitly set (when Controller is not a string)");
                             }
                         }
                         $output = $this->viewParser->render();
                     }
                 }
                 $this->response->setStatusCode(200);
                 $this->response->setContent(is_string($output) ? $output : '');
                 $this->response->setFinal($final);
                 $event->setResponse($this->response);
             }
         }
     } catch (InjectionException $e) {
         throw new ControllerError(sprintf("Unable to run controller: %s [%s]", $e->getMessage(), var_export($event->getController(), true)));
     }
 }