/** * 创建并返回一个 token * * @param string $purpose * @param string|null $identifier 唯一标识,为空则不需要 * @param int $expireAt * @param mixed $data * @param int $length * @return array * @throws InvalidArgumentException * @throws \Exception * @throws \MongoException */ public function generate($purpose, $identifier, $expireAt, $data = null, $length = 30) { if (!is_string($purpose)) { throw new InvalidArgumentException('purpose', 'type_invalid'); } if (!mb_check_encoding($purpose, 'UTF-8')) { throw new InvalidArgumentException('purpose', 'encoding_invalid'); } if (!Validator::int()->validate($expireAt)) { throw new InvalidArgumentException('expireAt', 'type_invalid'); } $token = Application::get('random')->generateString($length, VJ::RANDOM_CHARS); try { if ($identifier !== null) { if (!is_string($identifier)) { throw new InvalidArgumentException('identifier', 'type_invalid'); } if (!mb_check_encoding($identifier, 'UTF-8')) { throw new InvalidArgumentException('identifier', 'encoding_invalid'); } $result = Application::coll('Token')->update(['purpose' => $purpose, 'identifier' => $identifier], ['$set' => ['token' => $token, 'expireat' => new \MongoDate($expireAt), 'data' => $data]], ['upsert' => true]); return ['token' => $token, 'update' => $result['updatedExisting']]; } else { $result = Application::coll('Token')->insert(['purpose' => $purpose, 'identifier' => null, 'token' => $token, 'expireat' => new \MongoDate($expireAt), 'data' => $data]); return ['token' => $token]; } } catch (\MongoException $ex) { if ($ex->getCode() === 12) { throw new InvalidArgumentException('data', 'encoding_invalid'); } else { throw $ex; } } }
public function testUpgradeUserCredentialPassed() { $service = Application::get('vj2_credential_upgrade_service'); $this->assertTrue($service->upgradeUserCredential(1, 'this_is_test_password')); $user = $service->user_credential->checkPasswordCredential('世界你好', 'this_is_test_password', true); $this->assertFalse($service->user_credential->password_encoder->isOutdated($user['hash'])); }
private function send($type, array $to, $subject, $template, $params) { if (!Validator::arr()->each(Validator::email())->validate($to)) { throw new InvalidArgumentException('to', 'format_invalid'); } $html = Application::get('templating')->render($template, array_merge(['SUBJECT' => $subject], $params)); $this->provider->send($type, $to, $subject, $html); }
public function onEvent(GenericEvent $event, $eventName) { if (!$this->userManager->isLoggedIn() && $this->userManager->isRememberMeTokenProvided()) { try { Application::get('user_manager')->rememberMeTokenLogin(); } catch (\Exception $e) { } } }
public static function bootstrap() { Application::Instance(); Application::get('templating')->addFunction(new \Twig_SimpleFunction('url', function ($relative) { return VJ::makeUrl($relative); })); Application::get('templating')->addFunction(new \Twig_SimpleFunction('getUser', function () { return Application::get('user_session')->getUser(); })); }
public function testSimpleKeywords() { $redis = Application::get('redis'); $filter = new KeywordFilter($redis, $this->prefix); $miss = function () { return ['foo', 'bar', 'baz', 'quux', 'thud', 'grunt']; }; $this->assertEquals($filter->contains('The quick brown foo jumps over the lazy dog', $this->key, $miss), 'foo'); $this->assertEquals($filter->contains('The quick brown fox jumps over the lazy dog', $this->key, $miss), false); $this->assertEquals($filter->contains('The quick brown bar jumps over the lazy baz', $this->key, $miss), 'bar'); $this->assertEquals($filter->contains('The quick brown BAR jumps over the lazy dog', $this->key, $miss), 'bar'); $this->assertEquals($filter->contains('The quick brown FOX jumps over the lazy dog', $this->key, $miss), false); $this->assertEquals($filter->contains('The quick brown quux grunts over the lazy thud', $this->key, $miss), 'quux'); }
/** * @throws NotFoundException */ public static function route() { $dispatcher = Application::get('dispatcher'); $request = Application::get('request'); $response = Application::get('response'); Application::emit('route.dispatch.before'); //判断Event是否已经发送过响应 if (headers_sent()) { return; } $urlParts = parse_url($request->getRequestUri()); $route = $dispatcher->dispatch($request->getMethod(), $urlParts['path']); //[0]: Dispatch Status, [1]: handler, [2]: vars Application::emit('route.dispatch', $route); //同上 if (headers_sent()) { return; } switch ($route[0]) { case Dispatcher::NOT_FOUND: case Dispatcher::METHOD_NOT_ALLOWED: throw new NotFoundException(); break; case Dispatcher::FOUND: list(, $handler, $vars) = $route; $controller = new $handler['className']($request, $response); $ret = call_user_func([$controller, $handler['actionName']], $vars); if (headers_sent() || $ret === null) { return; } if ($ret instanceof Response && $ret !== $response) { // overwrite response $response = $ret; } else { if (is_string($ret)) { $response->setContent($ret); } if ($response->headers->get('content-type') === null) { $response->headers->set('content-type', 'text/html'); } $response->setCharset('UTF-8'); } $response->prepare($request); $response->send(); break; } }
/** * 导入 Vijos 数据库用户表 * * @param callable $progress * @param callable $done * @return bool * @throws UserException */ public function import(callable $progress = null) { if (Application::coll('User')->count() > 0) { throw new UserException('User.Importer.VijosImporter.userCollectionNotEmpty'); } $MAX_USER_ID = 1; $cursor = $this->source->selectCollection('User')->find()->sort(['_id' => 1]); foreach ($cursor as $user) { $_id = new \MongoId(); $uid = (int) $user['_id']; if ($uid > $MAX_USER_ID) { $MAX_USER_ID = $uid; } // vijos 中,username 被 escape 过 $user['user'] = htmlspecialchars_decode($user['user']); if (is_callable($progress)) { $progress($uid, $user['user']); } $doc = ['_id' => $_id, 'uid' => $uid, 'user' => $user['user'], 'luser' => UserUtil::canonicalizeUsername($user['user']), 'g' => $user['g'], 'gender' => (int) $user['sex'] + 1, 'regat' => (int) $user['treg'], 'regip' => $user['ipreg'], 'loginat' => (int) $user['tlogin'], 'loginip' => '255.255.255.255']; // 检查是否有 Email 重叠 $count = $this->source->selectCollection('User')->find(['lmail' => mb_strtolower($user['mail'], 'UTF-8')])->count(); if ($count > 1) { $doc['mail'] = Application::get('random')->generateString(20, VJ::RANDOM_CHARS) . '@openvj'; $doc['lmail'] = mb_strtolower($doc['mail'], 'UTF-8'); $doc['omail'] = $user['mail']; } else { $doc['mail'] = $user['mail']; $doc['lmail'] = UserUtil::canonicalizeEmail($doc['mail']); $doc['salt'] = $user['salt']; $doc['hash'] = 'vj2|' . base64_encode(mb_strtolower($user['user'], 'UTF-8')) . '|' . $user['pass']; } try { Application::coll('User')->insert($doc); Application::emit('user.created', [$uid]); } catch (\MongoCursorException $e) { // TODO: Duplicate user } } // Update UID counter Application::coll('System')->update(['_id' => 'UserCounter'], ['$set' => ['count' => $MAX_USER_ID + 1]], ['upsert' => true]); return true; }
public function getMongoConnection() { $connection = new Connector(Application::get('mongo_client')); $connection->setDb(Application::get('config')['mongodb']['db']); return $connection; }
/** * 创建一个记忆会话 * * @param array $user * @param int|null $expire */ public function generateRememberMeTokenForObject(array $user, $expire = null) { $token_field = Application::get('config')['session']['remember_token']; if ($expire === null) { $expire = time() + (int) Application::get('config')['session']['remember_ttl']; } $clientToken = $this->user_credential->createRememberMeToken($user['uid'], $this->request->getClientIp(), $this->request->getUserAgent(), $expire); $this->request->cookies->set($token_field, $clientToken); $this->response->headers->setCookie(new Cookie($token_field, $clientToken, $expire)); }
public function testSetCredential() { $ret = Application::get('user_credential')->setCredential(0, 'new_password'); $this->assertEquals(1, $ret); $user = Application::get('user_credential')->checkPasswordCredential('test_user', 'new_password', true); $this->assertNotNull($user); $this->assertEquals('test_user', $user['luser']); }
/** * 生成盐 * * @return string */ public function generateSalt() { return Application::get('random_secure')->generateString(60, VJ::RANDOM_CHARS); }
/** * 为当前 SESSION 生成 CSRFToken */ public function generateCsrfToken() { $this->set('csrfToken', Application::get('random')->generateString(30, VJ::RANDOM_CHARS)); }
public function testGenerateHash() { $hash = Application::get('password_encoder')->generateHash('hello_world'); $this->assertNotNull($hash['salt']); $this->assertNotNull($hash['hash']); $this->assertFalse(Application::get('password_encoder')->verify('hello', $hash['salt'], $hash['hash'])); $this->assertTrue(Application::get('password_encoder')->verify('hello_world', $hash['salt'], $hash['hash'])); }
/** * @param string $template * @param array $param * @return string */ public function render($template, $param = []) { return Application::get('templating')->render($template, $param); }
/** * 测试是否包含用于用户名的额外关键字 * * @param $text * @return bool|string */ public static function isContainName($text) { return Application::get('keyword_filter')->contains($text, 'name', function () { $rec = Application::coll('System')->findOne(['_id' => 'FilterKeyword']); if (!$rec) { return []; } else { return $rec['name']; } }); }
/** * 使一个 记住我 token 无效 * * @param string $clientToken * @return bool */ public function invalidateRememberMeToken($token) { try { return Application::get('token_manager')->invalidate('rememberme', $token); } catch (\InvalidArgumentException $e) { return false; } }
private static function initParser() { if (self::$parser === null) { self::$parser = new MarkdownParser(Application::get('config')['filter']['comment']); } }
public function logoutAction() { Application::get('user_manager')->logout(); $this->response->redirect('/'); }
private static function initTemplating() { self::set('templating', function () { $loader = new \Twig_Loader_Filesystem(self::$TEMPLATES_DIRECTORY); $twig = new \Twig_Environment($loader, ['cache' => self::$CACHE_DIRECTORY, 'debug' => self::get('config')['debug']]); $twig->addGlobal('GET', $_GET); $twig->addGlobal('POST', $_POST); $twig->addFunction(new \Twig_SimpleFunction('trans', function ($id, ...$argv) { return Application::get('i18n')->trans($id, $argv); })); return $twig; }); }
<?php namespace PHPSTORM_META; // we want to avoid the pollution /** @noinspection PhpUnusedLocalVariableInspection */ // just to have a green code below /** @noinspection PhpIllegalArrayKeyTypeInspection */ $STATIC_METHOD_TYPES = [\VJ\Core\Application::get('') => ['dispatcher' instanceof \FastRoute\Dispatcher, 'i18n' instanceof \Symfony\Component\Translation\Translator, 'request' instanceof \VJ\Core\Request, 'response' instanceof \VJ\Core\Response, 'templating' instanceof \Twig_Environment, 'redis' instanceof \Redis, 'mongo_client' instanceof \MongoClient, 'mongodb' instanceof \MongoDB, 'es_client' instanceof \Elastica\Client, 'es' instanceof \Elastica\Index, 'log' instanceof \Monolog\Logger, 'event' instanceof \Symfony\Component\EventDispatcher\EventDispatcher, 'random_factory' instanceof \RandomLib\Factory, 'random' instanceof \RandomLib\Generator, 'random_secure' instanceof \RandomLib\Generator, 'session_storage' instanceof \Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface, 'vj_redirection_service' instanceof \VJ\EventListener\VJRedirectionService, 'https_redirection_service' instanceof \VJ\EventListener\HttpsRedirectionService, 'login_log_service' instanceof \VJ\EventListener\LoginLogService, 'vj2_credential_upgrade_service' instanceof \VJ\EventListener\VJCredentialUpgradeService, 'keyword_filter' instanceof \VJ\Security\KeywordFilter, 'token_manager' instanceof \VJ\Security\TokenManager, 'message_signer' instanceof \VJ\Security\MessageSigner, 'user_session' instanceof \VJ\User\UserSession, 'domain_manager' instanceof \VJ\User\DomainManager, 'password_encoder' instanceof \VJ\User\PasswordEncoder, 'user_credential' instanceof \VJ\User\UserCredential, 'user_manager' instanceof \VJ\User\UserManager, 'bgservice_mailing_provider' instanceof \VJ\Mail\BgServiceMailingProvider, 'mail_sender' instanceof \VJ\Mail\Sender]];
/** * @param string $event * @param array $argv */ public static function emit($event, $argv = []) { Application::get('event')->dispatch($event, new GenericEvent($argv)); }