Skip to content

Commit c1e1536

Browse files
committed
Merge pull request #82 from ParsePlatform/sessions
Sessions
2 parents 0171095 + 3ca3e97 commit c1e1536

File tree

9 files changed

+189
-61
lines changed

9 files changed

+189
-61
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Installation
1313
```json
1414
{
1515
"require": {
16-
"parse/php-sdk" : "1.0.*"
16+
"parse/php-sdk" : "1.1.*"
1717
}
1818
}
1919
```

src/Parse/ParseClient.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,24 @@ final class ParseClient
4444
*/
4545
private static $storage;
4646

47+
/**
48+
* @var - Boolean for enabling revocable sessions.
49+
*/
50+
private static $forceRevocableSession = false;
51+
4752
/**
4853
* Constant for version string to include with requests.
4954
* @ignore
5055
*/
51-
const VERSION_STRING = 'php1.0.6';
56+
const VERSION_STRING = 'php1.1.0';
5257

5358
/**
5459
* Parse\Client::initialize, must be called before using Parse features.
5560
*
5661
* @param string $app_id Parse Application ID
5762
* @param string $rest_key Parse REST API Key
5863
* @param string $master_key Parse Master Key
59-
* @param string $enableCurlExceptions Enable or disable Parse curl exceptions
64+
* @param boolean $enableCurlExceptions Enable or disable Parse curl exceptions
6065
*
6166
* @return null
6267
*/
@@ -65,6 +70,7 @@ public static function initialize($app_id, $rest_key, $master_key, $enableCurlEx
6570
ParseUser::registerSubclass();
6671
ParseRole::registerSubclass();
6772
ParseInstallation::registerSubclass();
73+
ParseSession::registerSubclass();
6874
self::$applicationId = $app_id;
6975
self::$restKey = $rest_key;
7076
self::$masterKey = $master_key;
@@ -341,6 +347,9 @@ public static function _getRequestHeaders($sessionToken, $useMasterKey)
341347
} else {
342348
$headers[] = 'X-Parse-REST-API-Key: ' . self::$restKey;
343349
}
350+
if (self::$forceRevocableSession) {
351+
$headers[] = 'X-Parse-Revocable-Session: 1';
352+
}
344353
/**
345354
* Set an empty Expect header to stop the 100-continue behavior for post
346355
* data greater than 1024 bytes.
@@ -384,4 +393,17 @@ public static function getLocalPushDateFormat($value)
384393
$date = date_format($value, $dateFormatString);
385394
return $date;
386395
}
396+
397+
/**
398+
* Allows an existing application to start using revocable sessions, without forcing
399+
* all requests for the app to use them. After calling this method, login & signup requests
400+
* will be returned a unique and revocable session token.
401+
*
402+
* @return null
403+
*/
404+
public static function enableRevocableSessions()
405+
{
406+
self::$forceRevocableSession = true;
407+
}
408+
387409
}

src/Parse/ParseObject.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ public function _mergeAfterFetchWithSelectedKeys($result, $selectedKeys)
532532
private function mergeFromServer($data, $completeData = true)
533533
{
534534
$this->hasBeenFetched = ($this->hasBeenFetched || $completeData) ? true : false;
535-
$this->mergeMagicFields($data);
535+
$this->_mergeMagicFields($data);
536536
foreach ($data as $key => $value) {
537537
if ($key === '__type' && $value === 'className') {
538538
continue;
@@ -567,7 +567,7 @@ private function mergeFromServer($data, $completeData = true)
567567
*
568568
* @return null
569569
*/
570-
private function mergeMagicFields(&$data)
570+
public function _mergeMagicFields(&$data)
571571
{
572572
if (isset($data['objectId'])) {
573573
$this->objectId = $data['objectId'];

src/Parse/ParseSession.php

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
namespace Parse;
4+
5+
use Parse\ParseObject;
6+
use Parse\ParseUser;
7+
8+
/**
9+
* ParseSession - Representation of an expiring user session.
10+
*
11+
* @package Parse
12+
* @author Fosco Marotto <fjm@fb.com>
13+
*/
14+
class ParseSession extends ParseObject
15+
{
16+
17+
public static $parseClassName = "_Session";
18+
19+
private $_sessionToken = null;
20+
21+
/**
22+
* Returns the session token string.
23+
*
24+
* @return string
25+
*/
26+
public function getSessionToken()
27+
{
28+
return $this->_sessionToken;
29+
}
30+
31+
/**
32+
* Retrieves the Session object for the currently logged in user.
33+
*
34+
* @param boolean $useMasterKey If the Master Key should be used to override security.
35+
*
36+
* @return ParseSession
37+
*/
38+
public static function getCurrentSession($useMasterKey = false)
39+
{
40+
$token = ParseUser::getCurrentUser()->getSessionToken();
41+
$response = ParseClient::_request('GET', '/1/sessions/me', $token, null, $useMasterKey);
42+
$session = new ParseSession();
43+
$session->_mergeAfterFetch($response);
44+
$session->handleSaveResult();
45+
return $session;
46+
}
47+
48+
49+
/**
50+
* Determines whether the current session token is revocable.
51+
* This method is useful for migrating an existing app to use
52+
* revocable sessions.
53+
*
54+
* @return boolean
55+
*/
56+
public static function isCurrentSessionRevocable()
57+
{
58+
$user = ParseUser::getCurrentUser();
59+
if ($user) {
60+
return self::_isRevocable($user->getSessionToken());
61+
}
62+
}
63+
64+
/**
65+
* Determines whether a session token is revocable.
66+
*
67+
* @param string $token The session token to check
68+
*
69+
* @return boolean
70+
*/
71+
public static function _isRevocable($token)
72+
{
73+
return strpos($token, "r:") === 0;
74+
}
75+
76+
/**
77+
* After a save, perform Session object specific logic.
78+
*
79+
* @return null
80+
*/
81+
private function handleSaveResult()
82+
{
83+
if (isset($this->serverData['sessionToken'])) {
84+
$this->_sessionToken = $this->serverData['sessionToken'];
85+
unset($this->serverData['sessionToken']);
86+
}
87+
$this->rebuildEstimatedData();
88+
}
89+
90+
}

src/Parse/ParseUser.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,13 +162,20 @@ public static function become($sessionToken)
162162

163163
/**
164164
* Log out the current user. This will clear the storage and future calls
165-
* to current will return null
165+
* to current will return null.
166+
* This will make a network request to /1/logout to invalidate the session
166167
*
167168
* @return null
168169
*/
169170
public static function logOut()
170171
{
171-
if (ParseUser::getCurrentUser()) {
172+
$user = ParseUser::getCurrentUser();
173+
if ($user) {
174+
try {
175+
ParseClient::_request('POST', '/1/logout', $user->getSessionToken());
176+
} catch (ParseException $ex) {
177+
// If this fails, we're going to ignore it.
178+
}
172179
static::$currentUser = null;
173180
}
174181
ParseClient::getStorage()->remove('user');

tests/IncrementTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ public function testIncrementEmptyFieldAndTypeConflict()
211211
$obj->save();
212212
$objAgain->increment('randomkey');
213213
$this->setExpectedException('Parse\ParseException',
214-
"can't increment a field that isn't a number"
214+
"invalid type for key"
215215
);
216216
$objAgain->save();
217217
}

tests/ParseCloudTest.php

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -31,63 +31,11 @@ public function testFunctionsWithGeoPointParamsDoNotThrow()
3131
ParseCloud::run('unknown_function', $params);
3232
}
3333

34-
public function testExplicitFunctionFailure()
35-
{
36-
$params = array('key1' => 'value1');
37-
$this->setExpectedException('Parse\ParseException','bad stuff happened');
38-
ParseCloud::run('bar', $params);
39-
}
40-
4134
public function testUnknownFunctionFailure()
4235
{
4336
$params = array('key1' => 'value1');
4437
$this->setExpectedException('Parse\ParseException','function not found');
4538
ParseCloud::run('unknown_function', $params);
4639
}
4740

48-
public function testFunctions()
49-
{
50-
$params = array(
51-
'key1' => 'value1',
52-
'key2' => array(1,2,3)
53-
);
54-
$response = ParseCloud::run('foo', $params);
55-
$obj = $response['object'];
56-
$this->assertTrue($obj instanceof ParseObject);
57-
$this->assertEquals('Foo', $obj->className);
58-
$this->assertEquals(2, $obj->get('x'));
59-
$relation = $obj->get('relation');
60-
$this->assertTrue($relation instanceof ParseObject);
61-
$this->assertEquals('Bar', $relation->className);
62-
$this->assertEquals(3, $relation->get('x'));
63-
$obj = $response['array'][0];
64-
$this->assertTrue($obj instanceof ParseObject);
65-
$this->assertEquals('Bar', $obj->className);
66-
$this->assertEquals(2, $obj->get('x'));
67-
68-
$response = ParseCloud::run('foo', array('key1' => 'value1'));
69-
$this->assertEquals(2, $response['a']);
70-
71-
try {
72-
$response = ParseCloud::run('bar', array('key1' => 'value1'));
73-
$this->fail('Should have thrown an exception.');
74-
} catch(Parse\ParseException $ex) {
75-
// A parse exception should occur.
76-
}
77-
78-
$response = ParseCloud::run('bar', array('key2' => 'value1'));
79-
$this->assertEquals('Foo', $response);
80-
81-
$obj = ParseObject::create('SomeClass');
82-
$obj->set('name', 'Zanzibar');
83-
$obj->save();
84-
85-
$params = array('key2' => 'value1', 'key1' => $obj);
86-
try {
87-
$response = ParseCloud::run('foo', $params);
88-
$this->fail('Should have thrown an exception.');
89-
} catch (\Exception $ex) {
90-
// An exception should occur.
91-
}
92-
}
9341
}

tests/ParseObjectTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ public function testCanSetBoolean()
271271
public function testInvalidClassName()
272272
{
273273
$obj = ParseObject::create('Foo^bar');
274-
$this->setExpectedException('Parse\ParseException', 'Bad Request');
274+
$this->setExpectedException('Parse\ParseException', 'bad characters in classname');
275275
$obj->save();
276276
}
277277

tests/ParseSessionTest.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
use Parse\ParseClient;
4+
use Parse\ParseObject;
5+
use Parse\ParseQuery;
6+
use Parse\ParseUser;
7+
use Parse\ParseSession;
8+
9+
require_once 'ParseTestHelper.php';
10+
11+
class ParseSessionTest extends PHPUnit_Framework_TestCase
12+
{
13+
14+
public static function setUpBeforeClass()
15+
{
16+
ParseTestHelper::setUp();
17+
ParseTestHelper::clearClass(ParseUser::$parseClassName);
18+
ParseTestHelper::clearClass(ParseSession::$parseClassName);
19+
}
20+
21+
public function tearDown()
22+
{
23+
ParseTestHelper::tearDown();
24+
ParseUser::logOut();
25+
ParseTestHelper::clearClass(ParseUser::$parseClassName);
26+
ParseTestHelper::clearClass(ParseSession::$parseClassName);
27+
}
28+
29+
public static function tearDownAfterClass()
30+
{
31+
ParseUser::_unregisterSubclass();
32+
ParseSession::_unregisterSubclass();
33+
}
34+
35+
public function testRevocableSession()
36+
{
37+
ParseClient::enableRevocableSessions();
38+
$user = new ParseUser();
39+
$user->setUsername("username");
40+
$user->setPassword("password");
41+
$user->signUp();
42+
$session = ParseSession::getCurrentSession();
43+
$this->assertEquals($user->getSessionToken(), $session->getSessionToken());
44+
$this->assertTrue($session->isCurrentSessionRevocable());
45+
46+
ParseUser::logOut();
47+
48+
ParseUser::logIn("username", "password");
49+
$session = ParseSession::getCurrentSession();
50+
$this->assertEquals(ParseUser::getCurrentUser()->getSessionToken(), $session->getSessionToken());
51+
$this->assertTrue($session->isCurrentSessionRevocable());
52+
53+
$sessionToken = $session->getSessionToken();
54+
55+
ParseUser::logOut();
56+
57+
$this->setExpectedException('Parse\ParseException', 'invalid session token');
58+
ParseUser::become($sessionToken);
59+
}
60+
61+
}

0 commit comments

Comments
 (0)