Skip to content

Sessions #82

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 25, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Installation
```json
{
"require": {
"parse/php-sdk" : "1.0.*"
"parse/php-sdk" : "1.1.*"
}
}
```
Expand Down
26 changes: 24 additions & 2 deletions src/Parse/ParseClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,24 @@ final class ParseClient
*/
private static $storage;

/**
* @var - Boolean for enabling revocable sessions.
*/
private static $forceRevocableSession = false;

/**
* Constant for version string to include with requests.
* @ignore
*/
const VERSION_STRING = 'php1.0.6';
const VERSION_STRING = 'php1.1.0';

/**
* Parse\Client::initialize, must be called before using Parse features.
*
* @param string $app_id Parse Application ID
* @param string $rest_key Parse REST API Key
* @param string $master_key Parse Master Key
* @param string $enableCurlExceptions Enable or disable Parse curl exceptions
* @param boolean $enableCurlExceptions Enable or disable Parse curl exceptions
*
* @return null
*/
Expand All @@ -65,6 +70,7 @@ public static function initialize($app_id, $rest_key, $master_key, $enableCurlEx
ParseUser::registerSubclass();
ParseRole::registerSubclass();
ParseInstallation::registerSubclass();
ParseSession::registerSubclass();
self::$applicationId = $app_id;
self::$restKey = $rest_key;
self::$masterKey = $master_key;
Expand Down Expand Up @@ -341,6 +347,9 @@ public static function _getRequestHeaders($sessionToken, $useMasterKey)
} else {
$headers[] = 'X-Parse-REST-API-Key: ' . self::$restKey;
}
if (self::$forceRevocableSession) {
$headers[] = 'X-Parse-Revocable-Session: 1';
}
/**
* Set an empty Expect header to stop the 100-continue behavior for post
* data greater than 1024 bytes.
Expand Down Expand Up @@ -384,4 +393,17 @@ public static function getLocalPushDateFormat($value)
$date = date_format($value, $dateFormatString);
return $date;
}

/**
* Allows an existing application to start using revocable sessions, without forcing
* all requests for the app to use them. After calling this method, login & signup requests
* will be returned a unique and revocable session token.
*
* @return null
*/
public static function enableRevocableSessions()
{
self::$forceRevocableSession = true;
}

}
4 changes: 2 additions & 2 deletions src/Parse/ParseObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ public function _mergeAfterFetchWithSelectedKeys($result, $selectedKeys)
private function mergeFromServer($data, $completeData = true)
{
$this->hasBeenFetched = ($this->hasBeenFetched || $completeData) ? true : false;
$this->mergeMagicFields($data);
$this->_mergeMagicFields($data);
foreach ($data as $key => $value) {
if ($key === '__type' && $value === 'className') {
continue;
Expand Down Expand Up @@ -567,7 +567,7 @@ private function mergeFromServer($data, $completeData = true)
*
* @return null
*/
private function mergeMagicFields(&$data)
public function _mergeMagicFields(&$data)
{
if (isset($data['objectId'])) {
$this->objectId = $data['objectId'];
Expand Down
90 changes: 90 additions & 0 deletions src/Parse/ParseSession.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

namespace Parse;

use Parse\ParseObject;
use Parse\ParseUser;

/**
* ParseSession - Representation of an expiring user session.
*
* @package Parse
* @author Fosco Marotto <fjm@fb.com>
*/
class ParseSession extends ParseObject
{

public static $parseClassName = "_Session";

private $_sessionToken = null;

/**
* Returns the session token string.
*
* @return string
*/
public function getSessionToken()
{
return $this->_sessionToken;
}

/**
* Retrieves the Session object for the currently logged in user.
*
* @param boolean $useMasterKey If the Master Key should be used to override security.
*
* @return ParseSession
*/
public static function getCurrentSession($useMasterKey = false)
{
$token = ParseUser::getCurrentUser()->getSessionToken();
$response = ParseClient::_request('GET', '/1/sessions/me', $token, null, $useMasterKey);
$session = new ParseSession();
$session->_mergeAfterFetch($response);
$session->handleSaveResult();
return $session;
}


/**
* Determines whether the current session token is revocable.
* This method is useful for migrating an existing app to use
* revocable sessions.
*
* @return boolean
*/
public static function isCurrentSessionRevocable()
{
$user = ParseUser::getCurrentUser();
if ($user) {
return self::_isRevocable($user->getSessionToken());
}
}

/**
* Determines whether a session token is revocable.
*
* @param string $token The session token to check
*
* @return boolean
*/
public static function _isRevocable($token)
{
return strpos($token, "r:") === 0;
}

/**
* After a save, perform Session object specific logic.
*
* @return null
*/
private function handleSaveResult()
{
if (isset($this->serverData['sessionToken'])) {
$this->_sessionToken = $this->serverData['sessionToken'];
unset($this->serverData['sessionToken']);
}
$this->rebuildEstimatedData();
}

}
11 changes: 9 additions & 2 deletions src/Parse/ParseUser.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,20 @@ public static function become($sessionToken)

/**
* Log out the current user. This will clear the storage and future calls
* to current will return null
* to current will return null.
* This will make a network request to /1/logout to invalidate the session
*
* @return null
*/
public static function logOut()
{
if (ParseUser::getCurrentUser()) {
$user = ParseUser::getCurrentUser();
if ($user) {
try {
ParseClient::_request('POST', '/1/logout', $user->getSessionToken());
} catch (ParseException $ex) {
// If this fails, we're going to ignore it.
}
static::$currentUser = null;
}
ParseClient::getStorage()->remove('user');
Expand Down
2 changes: 1 addition & 1 deletion tests/IncrementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ public function testIncrementEmptyFieldAndTypeConflict()
$obj->save();
$objAgain->increment('randomkey');
$this->setExpectedException('Parse\ParseException',
"can't increment a field that isn't a number"
"invalid type for key"
);
$objAgain->save();
}
Expand Down
52 changes: 0 additions & 52 deletions tests/ParseCloudTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,63 +31,11 @@ public function testFunctionsWithGeoPointParamsDoNotThrow()
ParseCloud::run('unknown_function', $params);
}

public function testExplicitFunctionFailure()
{
$params = array('key1' => 'value1');
$this->setExpectedException('Parse\ParseException','bad stuff happened');
ParseCloud::run('bar', $params);
}

public function testUnknownFunctionFailure()
{
$params = array('key1' => 'value1');
$this->setExpectedException('Parse\ParseException','function not found');
ParseCloud::run('unknown_function', $params);
}

public function testFunctions()
{
$params = array(
'key1' => 'value1',
'key2' => array(1,2,3)
);
$response = ParseCloud::run('foo', $params);
$obj = $response['object'];
$this->assertTrue($obj instanceof ParseObject);
$this->assertEquals('Foo', $obj->className);
$this->assertEquals(2, $obj->get('x'));
$relation = $obj->get('relation');
$this->assertTrue($relation instanceof ParseObject);
$this->assertEquals('Bar', $relation->className);
$this->assertEquals(3, $relation->get('x'));
$obj = $response['array'][0];
$this->assertTrue($obj instanceof ParseObject);
$this->assertEquals('Bar', $obj->className);
$this->assertEquals(2, $obj->get('x'));

$response = ParseCloud::run('foo', array('key1' => 'value1'));
$this->assertEquals(2, $response['a']);

try {
$response = ParseCloud::run('bar', array('key1' => 'value1'));
$this->fail('Should have thrown an exception.');
} catch(Parse\ParseException $ex) {
// A parse exception should occur.
}

$response = ParseCloud::run('bar', array('key2' => 'value1'));
$this->assertEquals('Foo', $response);

$obj = ParseObject::create('SomeClass');
$obj->set('name', 'Zanzibar');
$obj->save();

$params = array('key2' => 'value1', 'key1' => $obj);
try {
$response = ParseCloud::run('foo', $params);
$this->fail('Should have thrown an exception.');
} catch (\Exception $ex) {
// An exception should occur.
}
}
}
2 changes: 1 addition & 1 deletion tests/ParseObjectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ public function testCanSetBoolean()
public function testInvalidClassName()
{
$obj = ParseObject::create('Foo^bar');
$this->setExpectedException('Parse\ParseException', 'Bad Request');
$this->setExpectedException('Parse\ParseException', 'bad characters in classname');
$obj->save();
}

Expand Down
61 changes: 61 additions & 0 deletions tests/ParseSessionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

use Parse\ParseClient;
use Parse\ParseObject;
use Parse\ParseQuery;
use Parse\ParseUser;
use Parse\ParseSession;

require_once 'ParseTestHelper.php';

class ParseSessionTest extends PHPUnit_Framework_TestCase
{

public static function setUpBeforeClass()
{
ParseTestHelper::setUp();
ParseTestHelper::clearClass(ParseUser::$parseClassName);
ParseTestHelper::clearClass(ParseSession::$parseClassName);
}

public function tearDown()
{
ParseTestHelper::tearDown();
ParseUser::logOut();
ParseTestHelper::clearClass(ParseUser::$parseClassName);
ParseTestHelper::clearClass(ParseSession::$parseClassName);
}

public static function tearDownAfterClass()
{
ParseUser::_unregisterSubclass();
ParseSession::_unregisterSubclass();
}

public function testRevocableSession()
{
ParseClient::enableRevocableSessions();
$user = new ParseUser();
$user->setUsername("username");
$user->setPassword("password");
$user->signUp();
$session = ParseSession::getCurrentSession();
$this->assertEquals($user->getSessionToken(), $session->getSessionToken());
$this->assertTrue($session->isCurrentSessionRevocable());

ParseUser::logOut();

ParseUser::logIn("username", "password");
$session = ParseSession::getCurrentSession();
$this->assertEquals(ParseUser::getCurrentUser()->getSessionToken(), $session->getSessionToken());
$this->assertTrue($session->isCurrentSessionRevocable());

$sessionToken = $session->getSessionToken();

ParseUser::logOut();

$this->setExpectedException('Parse\ParseException', 'invalid session token');
ParseUser::become($sessionToken);
}

}