diff --git a/src/LeanCloud/Client.php b/src/LeanCloud/Client.php index 1ed250d..b9a7719 100644 --- a/src/LeanCloud/Client.php +++ b/src/LeanCloud/Client.php @@ -400,6 +400,7 @@ public static function request($method, $path, $data, } $reqId = rand(100,999); if (self::$debugMode) { + error_log("[DEBUG] HEADERS {$reqId}:" . json_encode($headersList)); error_log("[DEBUG] REQUEST {$reqId}: {$method} {$url} {$json}"); } $resp = curl_exec($req); diff --git a/src/LeanCloud/Object.php b/src/LeanCloud/Object.php index a302758..be8df91 100644 --- a/src/LeanCloud/Object.php +++ b/src/LeanCloud/Object.php @@ -13,6 +13,8 @@ * */ class Object { + + const PRESERVED_KEYS = array("objectId", "updatedAt", "createdAt"); /** * Map of registered className to class. * @@ -141,15 +143,15 @@ public function getClassName() { } public function disableBeforeHook() { - $this->set("__before", - Client::signHook("__before_for_{$this->getClassName()}", - round(microtime(true) * 1000))); + $this->_set("__before", + Client::signHook("__before_for_{$this->getClassName()}", + round(microtime(true) * 1000))); } public function disableAfterHook() { - $this->set("__after", - Client::signHook("__after_for_{$this->getClassName()}", - round(microtime(true) * 1000))); + $this->_set("__after", + Client::signHook("__after_for_{$this->getClassName()}", + round(microtime(true) * 1000))); } /** @@ -230,6 +232,18 @@ public function getUpdatedAt() { return $this->get("updatedAt"); } + private function _set($key, $val) { + if ($key === "ACL" && + !($val instanceof ACL)) { + throw new RuntimeException("Invalid ACL."); + } + if (!($val instanceof IOperation)) { + $val = new SetOperation($key, $val); + } + $this->_applyOperation($val); + return $this; + } + /** * Set field value by key * @@ -239,14 +253,10 @@ public function getUpdatedAt() { * @throws RuntimeException */ public function set($key, $val) { - if (in_array($key, array("objectId", "createdAt", "updatedAt"))) { + if (in_array($key, self::PRESERVED_KEYS)) { throw new \RuntimeException("Preserved field could not be set."); } - if (!($val instanceof IOperation)) { - $val = new SetOperation($key, $val); - } - $this->_applyOperation($val); - return $this; + return $this->_set($key, $val); } /** @@ -256,7 +266,7 @@ public function set($key, $val) { * @return self */ public function setACL(ACL $acl) { - return $this->set("ACL", $acl); + return $this->_set("ACL", $acl); } /** diff --git a/src/LeanCloud/User.php b/src/LeanCloud/User.php index e5e1da7..377bb1d 100644 --- a/src/LeanCloud/User.php +++ b/src/LeanCloud/User.php @@ -232,6 +232,53 @@ private static function clearCurrentUser() { self::setCurrentSessionToken(null); } + /** + * Refresh session token + */ + public function refreshSessionToken() { + $resp = Client::put("/users/{$this->getObjectId()}/refreshSessionToken", + null); + $this->mergeAfterFetch($resp); + static::saveCurrentUser($this); + } + + /** + * Test if user logged in and session token is valid. + * + * @return bool + */ + public function isAuthenticated() { + $token = $this->getSessionToken(); + if (!$token) { + return false; + } + try { + $resp = Client::get("/users/me", + array("session_token" => $token)); + } catch(CloudException $ex) { + if ($ex->getCode() === 211) { + return false; + } + throw ex; + } + return true; + } + + /** + * Get roles the user belongs to + * + * @return array Array of Role + */ + public function getRoles() { + if (!$this->getObjectId()) { + return array(); + } + $query = new Query("_Role"); + $query->equalTo("users", $this); + $roles = $query->find(); + return $roles; + } + /** * Log-in user by session token * diff --git a/test/UserTest.php b/test/UserTest.php index e22b5c0..1023802 100644 --- a/test/UserTest.php +++ b/test/UserTest.php @@ -2,6 +2,8 @@ use LeanCloud\Client; use LeanCloud\User; +use LeanCloud\Role; +use LeanCloud\ACL; use LeanCloud\File; use LeanCloud\Query; use LeanCloud\CloudException; @@ -122,6 +124,19 @@ public function testBecome() { $this->assertEquals($user2, User::getCurrentUser()); } + public function testRefreshSessionToken() { + $user = new User(); + $user->setUsername("alice4"); + $user->setPassword("blabla"); + $user->signUp(); + + $token = $user->getSessionToken(); + $user->refreshSessionToken(); + $this->assertNotEmpty($user->getSessionToken()); + $this->assertNotEquals($token, $user->getSessionToken()); + $user->destroy(); + } + public function testLogOut() { $user = User::logIn("alice", "blabla"); $this->assertEquals($user, User::getCurrentUser()); @@ -191,6 +206,42 @@ public function testUnlinkService() { $user2->destroy(); } + public function testGetRoles() { + $user = new User(); + $user->setUsername("alice3"); + $user->setPassword("blabla"); + $user->signUp(); + + $role = new Role(); + $role->setName("test_role"); + $acl = new ACL(); + $acl->setPublicWriteAccess(true); + $acl->setPublicReadAccess(true); + + $role->setACL($acl); + $rel = $role->getUsers(); + $rel->add($user); + $role->save(); + $this->assertNotEmpty($role->getObjectId()); + + $roles = $user->getRoles(); + $this->assertEquals("test_role", $roles[0]->getName()); + + $user->destroy(); + $role->destroy(); + } + + public function testIsAuthenticated() { + $user = User::logIn("alice", "blabla"); + $this->assertTrue($user->isAuthenticated()); + + $user->mergeAfterFetch(array("sessionToken" => "invalid-token")); + $this->assertFalse($user->isAuthenticated()); + + $user = new User(); + $this->assertFalse($user->isAuthenticated()); + } + /* * Get current user with file attribute shall not * circularly invoke getCurrentUser.