Example #1
1
 public function index()
 {
     $request = RequestWrapper::$request;
     $target = $request->get('player');
     $target_id = $request->get('player_id');
     if ($target_id) {
         $target_player_obj = Player::find($target_id);
     } else {
         $target_player_obj = Player::findByName($target);
     }
     if ($target_player_obj === null) {
         $template = 'no-player.tpl';
         $viewed_name_for_title = null;
         $parts = array();
     } else {
         $attack_error = 'You must become a ninja first.';
         $clan = Clan::findByMember($target_player_obj);
         $combat_skills = null;
         $display_clan_options = false;
         $items = null;
         $same_clan = false;
         $self = false;
         $targeted_skills = null;
         $template = 'player.tpl';
         $viewed_name_for_title = $target_player_obj->name();
         $viewing_player_obj = Player::find(SessionFactory::getSession()->get('player_id'));
         $kills_today = query_item('SELECT sum(killpoints) FROM levelling_log WHERE _player_id = :player_id AND killsdate = CURRENT_DATE AND killpoints > 0', [':player_id' => $target_player_obj->id()]);
         $rank_spot = query_item('SELECT rank_id FROM rankings WHERE player_id = :player_id limit 1', [':player_id' => $target_player_obj->id()]);
         if ($viewing_player_obj !== null) {
             $viewers_clan = Clan::findByMember($viewing_player_obj);
             $self = $viewing_player_obj->id() === $target_player_obj->id();
             $params = ['required_turns' => 0, 'ignores_stealth' => true];
             $AttackLegal = new AttackLegal($viewing_player_obj, $target_player_obj, $params);
             $AttackLegal->check(false);
             $attack_error = $AttackLegal->getError();
             if (!$attack_error && !$self) {
                 // They're not dead or otherwise unattackable.
                 // Pull the items and some necessary data about them.
                 $inventory = new Inventory($viewing_player_obj);
                 $items = $inventory->counts();
                 $skillDAO = new SkillDAO();
                 if (!$viewing_player_obj->isAdmin()) {
                     $combat_skills = $skillDAO->getSkillsByTypeAndClass($viewing_player_obj->_class_id, 'combat', $viewing_player_obj->level);
                     $targeted_skills = $skillDAO->getSkillsByTypeAndClass($viewing_player_obj->_class_id, 'targeted', $viewing_player_obj->level);
                 } else {
                     $combat_skills = $skillDAO->all('combat');
                     $targeted_skills = $skillDAO->all('targeted');
                 }
             }
             if ($clan && $viewers_clan) {
                 $same_clan = $clan->id == $viewers_clan->id;
                 $display_clan_options = !$self && $same_clan && $viewing_player_obj->isClanLeader();
             }
         }
         $parts = ['viewing_player_obj' => $viewing_player_obj, 'target_player_obj' => $target_player_obj, 'combat_skills' => $combat_skills, 'targeted_skills' => $targeted_skills, 'self' => $self, 'rank_spot' => $rank_spot, 'kills_today' => $kills_today, 'status_list' => Player::getStatusList($target_player_obj->id()), 'clan' => $clan, 'items' => $items, 'account' => Account::findByChar($target_player_obj), 'same_clan' => $same_clan, 'display_clan_options' => $display_clan_options, 'attack_error' => $attack_error];
     }
     $parts['authenticated'] = SessionFactory::getSession()->get('authenticated', false);
     $title = 'Ninja' . ($viewed_name_for_title ? ": {$viewed_name_for_title}" : ' Profile');
     return new StreamedViewResponse($title, $template, $parts, ['quickstat' => 'player']);
 }
Example #2
0
 /**
  * Get the account object by id, or false
  *
  * @param int $id
  * @return Account|null
  */
 public static function findById($id)
 {
     $account = new Account($id);
     if (!$account->getIdentity()) {
         return null;
     } else {
         return $account;
     }
 }
Example #3
0
 public function testFindPlayableFromInitialChar()
 {
     $pc = Player::find($this->char_id);
     $acc = Account::findByChar($pc);
     $pc2 = Player::findPlayable($acc->id());
     $this->assertEquals($pc->id(), $pc2->id());
 }
 /**
  * Send a reset link to a given user.
  *
  * @return Response
  * @TODO: Authenticate the csrf, which must match, from the session.
  */
 public function postEmail(Container $p_dependencies)
 {
     $request = RequestWrapper::$request;
     $error = null;
     $message = null;
     $account = null;
     $email = $request->get('email');
     $ninja_name = $request->get('ninja_name');
     if (!$email && !$ninja_name) {
         $error = 'You must specify either an email or a ninja name!';
     } else {
         if ($email) {
             $account = Account::findByEmail($email);
         }
         if (!isset($account)) {
             $account = Account::findByNinjaName($ninja_name);
         }
         if ($account === null || !$account->id()) {
             $error = 'Sorry, unable to find a matching account!';
         } else {
             // PWR created with default nonce
             $request = PasswordResetRequest::generate($account);
             if ($this->sendEmail($request->nonce, $account)) {
                 $message = 'Your reset email was sent!';
             } else {
                 $error = 'Sorry, there was a problem sending to your account!  Please contact support.';
             }
         }
     }
     return new RedirectResponse('/password/?' . ($message ? 'message=' . rawurlencode($message) . '&' : '') . ($error ? 'error=' . rawurlencode($error) : ''));
 }
Example #5
0
 /**
  * Create a mock login, with real created account and character
  */
 public function login()
 {
     SessionFactory::init(new MockArraySessionStorage());
     $this->char = TestAccountCreateAndDestroy::char();
     SessionFactory::getSession()->set('authenticated', true);
     $this->account = Account::findByChar($this->char);
     SessionFactory::getSession()->set('account_id', $this->account->id());
 }
Example #6
0
 public static function canKill($clone1, $clone2)
 {
     // Input is transformed into
     if (!$clone1 instanceof Player) {
         if ($clone1 == Filter::toNonNegativeInt($clone1)) {
             $char1 = Player::find($clone1);
         } elseif (is_string($clone1)) {
             $char1 = Player::find($clone1);
         }
     } else {
         $char1 = $clone1;
     }
     if (!$clone2 instanceof Player) {
         if ($clone2 == Filter::toNonNegativeInt($clone2)) {
             $char2 = Player::find($clone2);
         } elseif (is_string($clone2)) {
             $char2 = Player::find($clone2);
         }
     } else {
         $char2 = $clone2;
     }
     // Reject invalid/nonexistent characters
     if ($char1 === null || $char2 === null) {
         return false;
     }
     // Reject same character
     if ($char1->id() == $char2->id()) {
         return false;
     }
     // Don't clone kill admins.
     if ($char1->isAdmin() || $char2->isAdmin()) {
         return false;
     }
     // Reject inactive characters
     if (!$char1->isActive() || !$char2->isActive()) {
         return false;
     }
     // TODO: Reject inoperative characters
     // TODO: You can't clone kill yourself..
     $host = gethostname();
     $server_ip = gethostbyname($host);
     $untouchable_ips = ['127.0.0.1', '173.203.99.229', $server_ip, '', null];
     $account1 = Account::findByChar($char1);
     $account2 = Account::findByChar($char2);
     // Reject invalid custom ips
     if (in_array($account1->getLastIp(), $untouchable_ips) || in_array($account2->getLastIp(), $untouchable_ips)) {
         return false;
     }
     // If characters have the same joint account, and have been logged in recently...
     if ($account1->getLastIp() === $account2->getLastIp()) {
         // Activity was already tested above.
         return true;
     }
     return false;
 }
 public function setUp()
 {
     SessionFactory::init(new MockArraySessionStorage());
     $char_id = TestAccountCreateAndDestroy::char_id();
     $char = Player::find($char_id);
     $account = Account::findByChar($char);
     $account_id = $account->id();
     SessionFactory::getSession()->set('authenticated', true);
     SessionFactory::getSession()->set('player_id', $char_id);
     SessionFactory::getSession()->set('account_id', $account_id);
 }
Example #8
0
 public function testCantCloneKillSimilarCharactersEvenIfBothHaveIpOf127001()
 {
     $previous = $_SERVER['REMOTE_ADDR'];
     $_SERVER['REMOTE_ADDR'] = '127.0.0.11';
     $char_id = TestAccountCreateAndDestroy::char_id();
     $char_id_2 = TestAccountCreateAndDestroy::char_id_2();
     $_SERVER['REMOTE_ADDR'] = $previous;
     $this->syncIps('127.0.0.1', $char_id, $char_id_2);
     // Must be 127.0.0.1 for this test.
     $p1 = Player::find($char_id);
     $p2 = Player::find($char_id_2);
     $account1 = Account::findByChar($p1);
     $account2 = Account::findByChar($p2);
     $this->assertEquals('127.0.0.1', $account1->getLastIp());
     $this->assertEquals('127.0.0.1', $account2->getLastIp());
     $this->assertFalse(CloneKill::canKill($char_id, $char_id_2));
 }
 /**
  * Display the main admin area
  *
  * Includes player viewing, account duplicates checking, npc balacing
  *
  * @return Response
  */
 public function index()
 {
     $request = RequestWrapper::$request;
     if (!$this->self || !$this->self->isAdmin()) {
         return new RedirectResponse(WEB_ROOT);
     }
     $error = null;
     $char_infos = null;
     $char_inventory = null;
     $first_message = null;
     $first_char = null;
     $first_account = null;
     $first_description = null;
     $dupes = AdminViews::dupedIps();
     $stats = AdminViews::highRollers();
     $npcs = NpcFactory::allNonTrivialNpcs();
     $trivial_npcs = NpcFactory::allTrivialNpcs();
     $char_ids = preg_split("/[,\\s]+/", $request->get('view'));
     $char_name = trim($request->get('char_name'));
     if ($char_name) {
         // View a target non-self character
         $first_char = Player::findByName($char_name);
         if (null !== $first_char && null !== $first_char->id()) {
             $char_ids = [$first_char->id()];
         }
     }
     if (is_array($char_ids)) {
         // Get a different first character if an array is specified
         $first_char = $first_char ? $first_char : Player::find(reset($char_ids));
         if ($first_char) {
             assert($first_char instanceof Player);
             $first_account = Account::findByChar($first_char);
             $char_inventory = AdminViews::charInventory($first_char);
             $first_message = $first_char->messages;
             $first_description = $first_char->description;
         }
         // All the rest multi-character table view
         try {
             $char_infos = AdminViews::charInfos($char_ids);
         } catch (InvalidArgumentException $e) {
             $error = $e->getMessage();
         }
     }
     $parts = ['error' => $error, 'stats' => $stats, 'first_char' => $first_char, 'first_description' => $first_description, 'first_message' => $first_message, 'first_account' => $first_account, 'char_infos' => $char_infos, 'dupes' => $dupes, 'char_inventory' => $char_inventory, 'char_name' => $char_name, 'npcs' => $npcs, 'trivial_npcs' => $trivial_npcs];
     return new StreamedViewResponse('Admin Actions', 'ninjamaster.tpl', $parts);
 }
Example #10
0
 /**
  * Return true on matching ip characteristics.
  *
  * @todo cleanup the allowable IP addresses logic
  * @return boolean
  */
 public function sameDomain(Player $target, Player $self)
 {
     // Get all the various ips that shouldn't be matches, and prevent them from being a problem.
     $server_addr = isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : null;
     $host = gethostname();
     $active_ip = gethostbyname($host);
     $allowable = array_merge(['127.0.0.1', $server_addr, $active_ip], Constants::$trusted_proxies);
     $self_account = Account::findByChar($self);
     $target_account = Account::findByChar($target);
     $self_ip = $self_account->getLastIp();
     if (!$self_ip || in_array($self_ip, $allowable)) {
         return false;
         // Don't have to obtain the target's ip at all if these are the case!
     } else {
         return $self_ip === $target_account->getLastIp();
     }
 }
Example #11
0
 public function testAccountCanHavePlayers()
 {
     $account = Account::findByNinjaName($this->test_ninja_name);
     $pcs = $account->getCharacters();
     $this->assertNotEmpty($pcs);
     $this->assertInstanceOf(Player::class, reset($pcs));
 }
 /**
  * Generate a full password reset request for an account
  *
  * @param Account $account
  * @return PasswordResetRequest
  */
 public static function generate(Account $account, $nonce = null)
 {
     $nonce = $nonce !== null ? $nonce : Crypto::nonce();
     return self::create(['_account_id' => $account->id(), 'nonce' => $nonce]);
 }
 /**
  * Convenience wrapper for the above, but confirms the account and returns the account id.
  */
 public static function create_complete_test_account_and_return_id()
 {
     $player_mock = new Player();
     $player_mock->player_id = TestAccountCreateAndDestroy::create_testing_account(true);
     $account = Account::findByChar($player_mock);
     return $account->id();
 }
 /**
  * Generate a full password reset request for an account
  *
  * @param Account $account
  * @return PasswordResetRequest
  */
 public static function generate(Account $account, $nonce = null)
 {
     $nonce = $nonce !== null ? $nonce : nonce();
     return PasswordResetRequest::create(['_account_id' => $account->id(), 'nonce' => $nonce]);
 }
Example #15
0
 public function testPerformingAResetInvalidatesUsedRequest()
 {
     $account_id = TestAccountCreateAndDestroy::account_id();
     $account = Account::findById($account_id);
     PasswordResetRequest::generate($account, $this->nonce = '77warkwark', false);
     PasswordResetRequest::reset($account, 'new_pass34532');
     $req = PasswordResetRequest::match($this->nonce);
     $this->assertEmpty($req);
     // Request shouldn't match because it should already be used.
 }
Example #16
0
 /**
  * Just do a check whether the input username and password is valid
  *
  * @return boolean
  */
 public static function is_authentic($p_user, $p_pass)
 {
     $account = Account::findByLogin($p_user);
     return $account && $account->authenticate($p_pass);
 }
Example #17
0
 /**
  * Try to store a posted post, and redirect on successes or errors.
  *
  * @return RedirectResponse
  */
 public function store()
 {
     $request = RequestWrapper::$request;
     try {
         $this->hasCreateRole($this->pc);
         $account = $this->pc ? Account::findByChar($this->pc) : null;
         $account_id = $account->id();
     } catch (InvalidArgumentException $e) {
         $error = "Sorry, you must be logged in to try to save a news post.";
         return new RedirectResponse('/news/?error=' . rawurlencode($error));
     } catch (ErrorException $e) {
         $error = "Sorry, you don't have permission to save a news post.";
         return new RedirectResponse('/news/?error=' . rawurlencode($error));
     }
     // Handle POST
     $news_title = $request->get('news_title');
     $news_content = $request->get('news_content');
     $tag = $request->get('tag');
     // Create new post
     if (!empty($news_content)) {
         try {
             // News Model
             $news = new News();
             $news->createPost($news_title, $news_content, $account_id, $tag);
             return new RedirectResponse('/news/?create_successful=1');
         } catch (InvalidArgumentException $e) {
             return new RedirectResponse('/news/?error=' . rawurlencode('Unable to create news post.'));
         }
     } else {
         return new RedirectResponse('/news/create/?error=' . rawurlencode('A News post must have a body.'));
     }
 }
Example #18
0
 public function testAccountHasAnId()
 {
     $account = new Account($this->testAccountId);
     $this->assertGreaterThan(0, $account->getId());
 }
Example #19
0
 /**
  * Leveling up Function
  *
  * @return boolean
  */
 public function levelUp()
 {
     $health_to_add = 100;
     $turns_to_give = 50;
     $ki_to_give = 50;
     $stat_value_to_add = 5;
     $karma_to_give = 1;
     if ($this->isAdmin()) {
         // If the character is an admin, do not auto-level
         return false;
     } else {
         // For normal characters, do auto-level
         // Have to be under the max level and have enough kills.
         $level_up_possible = $this->level + 1 <= MAX_PLAYER_LEVEL && $this->kills >= $this->killsRequiredForNextLevel();
         if ($level_up_possible) {
             // Perform the level up actions
             $this->setHealth($this->health + $health_to_add);
             $this->setTurns($this->turns + $turns_to_give);
             $this->setKi($this->ki + $ki_to_give);
             // Must read from VO for these as accessors return modified values
             $this->setStamina($this->vo->stamina + $stat_value_to_add);
             $this->setStrength($this->vo->strength + $stat_value_to_add);
             $this->setSpeed($this->vo->speed + $stat_value_to_add);
             // no mutator for these yet
             $this->vo->kills = max(0, $this->kills - $this->killsRequiredForNextLevel());
             $this->vo->karma = $this->karma + $karma_to_give;
             $this->vo->level = $this->level + 1;
             $this->save();
             GameLog::recordLevelUp($this->id());
             $account = Account::findByChar($this);
             $account->setKarmaTotal($account->getKarmaTotal() + $karma_to_give);
             $account->save();
             // Send a level-up message, for those times when auto-levelling happens.
             Event::create($this->id(), $this->id(), "You levelled up! Your strength raised by {$stat_value_to_add}, speed by {$stat_value_to_add}, stamina by {$stat_value_to_add}, Karma by {$karma_to_give}, and your Ki raised {$ki_to_give}! You gained some health and turns, as well! You are now a level {$this->level} ninja! Go kill some stuff.");
             return true;
         } else {
             return false;
         }
     }
 }
Example #20
0
 function testThatAccountConfirmationProcessRejectsNinjaNamesOfTheWrongFormat()
 {
     // Same requirements as above, here we test that bad names are rejected.
     $bad_names = ['xz', 'bo', '69numfirst', 'underscorelast_', 'specialChar##', '@!#$#$^#$@#', 'double__underscore', 'double--dash'];
     foreach ($bad_names as $name) {
         $this->assertFalse(!(bool) Account::usernameIsValid($name));
     }
 }
Example #21
0
 /**
  * Authenticate a set of credentials
  *
  * @return Array
  */
 private function authenticate($dirty_login, $p_pass, $limit_login_attempts = true)
 {
     $filter_pattern = "/[^\\w\\d\\s_\\-\\.\\@\\:\\/]/";
     $login = strtolower(preg_replace($filter_pattern, "", (string) $dirty_login));
     $rate_limit = false;
     $pass = (string) $p_pass;
     $account = Account::findByLogin($login);
     if ($limit_login_attempts && $account) {
         $rate_limit = intval($account->login_failure_interval) <= 1;
     }
     if ($login != '' && $pass != '' && !$rate_limit) {
         // Pull the account data regardless of whether the password matches,
         // but create an int about whether it does match or not.
         $sql = "SELECT account_id, account_identity, uname, player_id, accounts.confirmed as confirmed,\n                CASE WHEN phash = crypt(:pass, phash) THEN 1 ELSE 0 END AS authenticated,\n                CASE WHEN accounts.operational THEN 1 ELSE 0 END AS operational\n                FROM accounts\n                JOIN account_players ON account_id = _account_id\n                JOIN players ON player_id = _player_id\n                WHERE (active_email = :login OR lower(uname) = :login)";
         $result = query($sql, [':login' => $login, ':pass' => $pass]);
         if ($result->rowCount() < 1) {
             // Username does not exist
             return [];
         } else {
             if ($result->rowCount() > 1) {
                 // Just for later reference, check for duplicate usernames via:
                 //select array_accum(uname), count(*) from players group by lower(trim(uname)) having count(*) > 1;
                 error_log('Case-insensitive duplicate username found: ' . $login);
             }
             return $result->fetch();
             // account found, return results
         }
     } else {
         if ($account) {
             // Update the last login failure timestamp
             Account::updateLastLoginFailure($account);
         }
         return [];
     }
 }
Example #22
0
 /**
  * Update the time of last failed login.
  */
 public static function updateLastLoginFailure(Account $account)
 {
     $update = "UPDATE accounts SET last_login_failure = now() WHERE account_id = :account_id";
     return query($update, [':account_id' => [$account->id(), PDO::PARAM_INT]]);
 }
 public function testLoginShouldFailOnBlanks()
 {
     $account = Account::findById(TestAccountCreateAndDestroy::account_id());
     $this->assertInstanceOf(Account::class, $account);
     $account->confirmed = 0;
     $account->save();
     $request = new Request([], ['user' => '', 'pass' => '']);
     // TestAccountCreateAndDestroy::$test_password
     RequestWrapper::inject($request);
     $controller = new LoginController();
     $res = $controller->requestLogin($this->m_dependencies);
     $this->assertInstanceOf(RedirectResponse::class, $res);
     $this->assertTrue(stripos($res->getTargetUrl(), 'error') !== false);
 }
 public function testSuccessfulSignupResultsInNoConfirmation()
 {
     $uname = 'KnownGood';
     $email = '*****@*****.**';
     // Due to the nature of hotmail, hotmail emails are listed
     // such that they will not be preconfirmed.  This leaves an account needing confirmation.
     RequestWrapper::inject(new Request(['key' => 'password1', 'cpass' => 'password1', 'send_email' => $email, 'send_name' => $uname]));
     $controller = new SignupController();
     $response = $controller->signup($this->m_dependencies);
     $account = Account::findByEmail($email);
     $player = Player::findByName($uname);
     $this->assertNotNull($player);
     $this->assertNotNull($account);
     $query_relationship = 'SELECT count(*) FROM account_players WHERE _account_id = :id1 AND _player_id = :id2';
     $account_unconfirmed = null;
     if ($account && $player) {
         $relationship_count = query_item($query_relationship, [':id1' => $account->id(), ':id2' => $player->id()]);
         $account_unconfirmed = !$account->isConfirmed();
     } else {
         $relationship_count = 0;
     }
     $delete_player = 'DELETE FROM players WHERE player_id = :id';
     $delete_account = 'DELETE FROM accounts WHERE account_id = :id';
     $delete_relationship = 'DELETE FROM account_players WHERE _account_id = :id1 OR _player_id = :id2';
     query($delete_player, [':id' => $player->id()]);
     query($delete_account, [':id' => $account->id()]);
     query($delete_relationship, [':id1' => $account->id(), ':id2' => $player->id()]);
     $reflection = new \ReflectionProperty(get_class($response), 'data');
     $reflection->setAccessible(true);
     $response_data = $reflection->getValue($response);
     $this->assertTrue($response_data['submit_successful'], 'Signup() returned error: ' . $response_data['error']);
     $this->assertEquals($relationship_count, 1);
     $this->assertTrue($account_unconfirmed);
 }
 public function testPostEmailCanGetAnAccountUsingANinjaName()
 {
     $req = Request::create('/password/post_email/');
     $req->setMethod('POST');
     $char = TestAccountCreateAndDestroy::char();
     $ninja_name = $char->name();
     $req->request->set('ninja_name', $ninja_name);
     RequestWrapper::inject($req);
     $account = Account::findByNinjaName($ninja_name);
     $this->assertNotEmpty($account->id(), 'Unable to find id for newly created account.');
     $controller = new PasswordController();
     $controller->postEmail($this->m_dependencies);
     // Check for a matching request for the appropriate account.
     $pwrr = PasswordResetRequest::where('_account_id', '=', $account->id())->first();
     $this->assertNotEmpty($pwrr, 'Fail: Unable to find a matching password reset request  for account_id: [' . $this->account->id() . '].');
     $this->nonce = $pwrr->nonce;
 }