Commit: 9f12bf9a1838cfd97d3b24d9ffa4bfd5fc2681ff

Author: gwoo | Date: 2009-11-30 10:57:15 -0800
working on server/provider interface
diff --git a/config/routes.php b/config/routes.php new file mode 100644 index 0000000..4a2117d --- /dev/null +++ b/config/routes.php @@ -0,0 +1,10 @@ +<?php + +use \lithium\http\Router; + + +Router::connect('/oauth/{:action}/{:args}', array( + 'plugin' => 'li3_oauth', 'controller' => 'server', 'action' => 'index' +)); + +?> \ No newline at end of file diff --git a/controllers/ServerController.php b/controllers/ServerController.php new file mode 100644 index 0000000..9ae0bd6 --- /dev/null +++ b/controllers/ServerController.php @@ -0,0 +1,69 @@ +<?php +/** + * Lithium: the most rad php framework + * + * @copyright Copyright 2009, Union of RAD (http://union-of-rad.org) + * @license http://opensource.org/licenses/bsd-license.php The BSD License + */ + +namespace li3_oauth\controllers; + +use \li3_oauth\models\Provider; +use \lithium\storage\Session; + +class ServerController extends \lithium\action\Controller { + + protected function _init() { + parent::_init(); + Provider::config(array( + 'host' => 'localhost', + 'request_token' => 'union-of-rad/rad-dev/plugins/oauth/request_token', + 'access_token' => 'union-of-rad/rad-dev/plugins/oauth/access_token', + 'port' => 30500 + )); + } + + public function request_token() { + if (empty($this->request->data)) { + return 'Invalid Request'; + } + $consumer = Provider::fetch($this->request->data['oauth_consumer_key']); + $request = array( + 'params' => $this->request->data, 'url' => 'request_token', + ) + (array) $consumer; + if (Provider::verify($request)) { + $token = Provider::create('token'); + $data = (array) $consumer + (array) $token; + Provider::store($consumer->oauth_consumer_key, $data); + Provider::store($token->oauth_token, $data); + return http_build_query((array) $token); + } + } + + public function authorize() { + if (!empty($this->request->query['oauth_token'])) { + $token = $this->request->query['oauth_token']; + $data = Provider::fetch($token); + } + + if (!empty($this->request->data['allow'])) { + + } + if (!empty($this->request->data['deny'])) { + + } + return compact('token'); + } + + public function access_token() { + + } + + public function account() { + $token = Provider::create('consumer'); + Provider::store($token->oauth_consumer_key, $token); + return compact('token'); + } +} + +?> \ No newline at end of file diff --git a/extensions/service/Oauth.php b/extensions/service/Oauth.php index 3002d6c..09508cf 100644 --- a/extensions/service/Oauth.php +++ b/extensions/service/Oauth.php @@ -61,7 +61,7 @@ class Oauth extends \lithium\core\Object { public function _init() { parent::_init(); $this->service = new $this->_classes['service']($this->_config); - $this->store = new $this->_classes['storage']($this->_config); + $this->storage = new $this->_classes['storage']($this->_config); } /** @@ -80,7 +80,7 @@ class Oauth extends \lithium\core\Object { } return $this->_config; } - + /** * Send request * @@ -95,7 +95,7 @@ class Oauth extends \lithium\core\Object { $method = !empty($options['method']) ? $options['method'] : 'post'; $data = $this->sign($data + compact('url')); $response = $this->service->send($method, $url, $data, $options); - if (strpos($response, 'oauth') !== false) { + if (in_array($path, array('request_token', 'access_token'))) { return $this->_decode($response); } return $response; @@ -126,22 +126,25 @@ class Oauth extends \lithium\core\Object { */ public function sign($options = array()) { $defaults = array( - 'hash' => 'HMAC-SHA1', 'secret' => $this->_config['oauth_consumer_secret'], - 'params' => array(), 'method' => 'POST', 'url' => '/', 'data' => array(), + 'url' => '', 'method' => 'POST', 'hash' => 'HMAC-SHA1', + 'oauth_consumer_secret' => $this->_config['oauth_consumer_secret'], + 'params' => array(), 'data' => array(), 'token' => array('oauth_token' => null, 'oauth_token_secret' => null), ); $options += $defaults; $params = $this->_build($options['params'] + (array)$options['token']) + $options['data']; - $base = $this->_base($options['type'], $options['url'], $params); + $base = $this->_base($options['method'], $options['url'], $params); $key = join("&", array( - rawurlencode($options['secret']), rawurlencode($options['token']['oauth_token_secret']) + rawurlencode($options['oauth_consumer_secret']), + rawurlencode($options['token']['oauth_token_secret']) )); + switch ($options['hash']) { case 'HMAC-SHA1': $signature = base64_encode(hash_hmac('sha1', $base, $key, true)); break; default: - return $options['secret']; + return $options['token']['oauth_token']; break; } $params['oauth_signature'] = $signature; diff --git a/extensions/storage/File.php b/extensions/storage/File.php index 077b641..1afe919 100644 --- a/extensions/storage/File.php +++ b/extensions/storage/File.php @@ -10,26 +10,70 @@ namespace li3_oauth\extensions\storage; class File extends \lithium\core\Object { - public $file = null; + protected $_file = null; + protected $_autoConfig = array('file'); + + /** + * undocumented function + * + * @return void + */ protected function _init() { parent::_init(); - $this->file = LITHIUM_APP_PATH . '/tmp/storage/oauth.ini'; + if (empty($this->_file)) { + $this->_file = LITHIUM_APP_PATH . '/tmp/storage/oauth.json'; + return; + } + if ($this->_file[0] !== '/') { + $this->_file = LITHIUM_APP_PATH . '/tmp/'. $this->_file; + } } + /** + * undocumented function + * + * @param string $key + * @param string $value + * @return void + */ public function write($key, $value) { - $value = json_encode($value); - $data = "{$key}=\"{$value}\""; - return file_put_contents($this->file, $data, FILE_APPEND); + $data = (array) $this->read(); + $data[$key] = $value; + $data = json_encode($data); + return file_put_contents($this->_file, $data); } - public function read($key) { - $data = parse_ini_file($this->file); + /** + * undocumented function + * + * @param string $key + * @return void + */ + public function read($key = null) { + if (!file_exists($this->_file)) { + return null; + } + $data = json_decode(file_get_contents($this->_file)); + if (isset($data->{$key})) { + return $data->{$key}; + } + return $data; + } + + /** + * undocumented function + * + * @param string $key + * @return void + */ + public function remove($key) { + $data = (array) $this->read(); if (isset($data[$key])) { - return json_decode($data[$key]); + unset($data[$key]); } - return null; + $data = json_encode($data); + return file_put_contents($this->_file, $data); } - } ?> \ No newline at end of file diff --git a/models/Provider.php b/models/Provider.php new file mode 100644 index 0000000..3b7f7c0 --- /dev/null +++ b/models/Provider.php @@ -0,0 +1,118 @@ +<?php +/** + * Lithium: the most rad php framework + * + * @copyright Copyright 2009, Union of RAD (http://union-of-rad.org) + * @license http://opensource.org/licenses/bsd-license.php The BSD License + */ + +namespace li3_oauth\models; + +use \li3_oauth\extensions\service\Oauth; + +class Provider extends \lithium\core\StaticObject { + + /** + * Holds an instance of the oauth service class + * + * @see \li3_oauth\extensions\services\Oauth + */ + protected static $_service = null; + + /** + * Configure the Consumer to access the Oauth service layer + * {{{ + * Provider::config(array( + * 'host' => 'localhost', + * 'oauth_consumer_key' => 'key', + * 'oauth_consumer_secret' => 'secret', + * 'request_token' => 'libraries/oauth_php/example/request_token.php', + * 'access_token' => 'libraries/oauth_php/example/access_token.php', + * )); + * }}} + * + * @param array $config + * - host: the oauth domain + * - oauth_consumer_key: key from oauth service provider + * - oauth_consumer_secret: secret from oauth service provider + * - oauth_consumer_key: key from oauth service provider + * - authorize: path to authorize url + * - request_token: path to request token url + * - access_token: path to access token url + * + * @return void + */ + public static function config($config) { + static::$_service = new Oauth($config); + } + + /** + * generate a consumer or token + * + * @param string $type + * - consumer: creates object with oauth_consumer_key and oauth_consumer_secret + * - token: creates query string with aoauth_token and oauth_token_secret + * @param string $key + * @param string $secret + * @return void + */ + public static function create($type, $key = null, $secret = null) { + $key = $key ?: sha1(mt_rand()); + $secret = $secret ?: sha1(mt_rand()); + switch($type) { + case 'token': + return (object) array( + 'oauth_token' => $key, 'oauth_token_secret' => $secret + ); + break; + default: + case 'consumer': + return (object) array( + 'oauth_consumer_key' => $key, 'oauth_consumer_secret' => $secret + ); + break; + } + } + + /** + * undocumented function + * + * @param string $query + * @return void + */ + public static function verify($request) { + if (!empty($request['params']['oauth_signature'])) { + $sig = $request['params']['oauth_signature']; + unset($request['params']['oauth_signature']); + $test = static::$_service->sign($request); + + if ($sig == $test['oauth_signature']) { + return true; + } + } + return false; + } + + /** + * undocumented function + * + * @param string $key + * @param string $value + * @return void + */ + public static function store($key, $value) { + return static::$_service->storage->write($key, $value); + } + + /** + * undocumented function + * + * @param string $key + * @return void + */ + public static function fetch($key) { + return static::$_service->storage->read($key); + } +} + +?> \ No newline at end of file diff --git a/tests/cases/extensions/storage/FileTest.php b/tests/cases/extensions/storage/FileTest.php index b723c65..7058dbe 100644 --- a/tests/cases/extensions/storage/FileTest.php +++ b/tests/cases/extensions/storage/FileTest.php @@ -6,12 +6,67 @@ * @license http://opensource.org/licenses/bsd-license.php The BSD License */ -namespace li3_oauth\test\cases\extensions\storage; +namespace li3_oauth\tests\cases\extensions\storage; use \li3_oauth\extensions\storage\File; class FileTest extends \lithium\test\Unit { + public $path = null; + + public $file = null; + + public function setUp() { + $this->path = LITHIUM_APP_PATH . '/tmp/test_oauth.json'; + $this->file = new File(array('file' => $this->path)); + } + + public function tearDown() { + unlink($this->path); + } + + public function testReadWrite() { + $expected = ''; + $result = $this->file->read(); + $this->assertEqual($expected, $result); + + $expected = true; + $result = $this->file->write('some_key', array( + 'oauth_consumer_key' => 'some_key', + 'oauth_consumer_secret' => 'some_secret' + )); + $this->assertEqual($expected, $result); + + $expected = (object) array('some_key' => (object) array( + 'oauth_consumer_key' => 'some_key','oauth_consumer_secret' => 'some_secret' + )); + $result = $this->file->read(); + $this->assertEqual($expected, $result); + + } + + public function testWriteReadRemove() { + $expected = true; + $result = $this->file->write('some_key', array( + 'oauth_consumer_key' => 'some_key', + 'oauth_consumer_secret' => 'some_secret' + )); + $this->assertEqual($expected, $result); + + $expected = (object) array('some_key' => (object) array( + 'oauth_consumer_key' => 'some_key','oauth_consumer_secret' => 'some_secret' + )); + $result = $this->file->read(); + $this->assertEqual($expected, $result); + + $expected = true; + $result = $this->file->remove('some_key'); + $this->assertEqual($expected, $result); + + $expected = array(); + $result = $this->file->read(); + $this->assertEqual($expected, $result); + } } diff --git a/tests/cases/models/ProviderTest.php b/tests/cases/models/ProviderTest.php index 8ff768d..ebdf37b 100644 --- a/tests/cases/models/ProviderTest.php +++ b/tests/cases/models/ProviderTest.php @@ -6,13 +6,87 @@ * @license http://opensource.org/licenses/bsd-license.php The BSD License */ -namespace li3_oauth\test\cases\models; +namespace li3_oauth\tests\cases\models; use \li3_oauth\models\Provider; class ProviderTest extends \lithium\test\Unit { + public function setUp() { + Provider::config(array( + 'host' => 'localhost', + 'oauth_consumer_key' => 'key', + 'oauth_consumer_secret' => 'secret', + 'port' => 30500 + )); + } + public function testCreateConsumer() { + $expected = (object) array( + 'oauth_consumer_key' => 'key', 'oauth_consumer_secret' => 'secret' + ); + $result = Provider::create('consumer', 'key', 'secret'); + $this->assertEqual($expected, $result); + + $consumer = Provider::create('consumer'); + + $expected = '/[a-z0-9]{40}/'; + $result = $consumer->oauth_consumer_key; + $this->assertPattern($expected, $result); + + $expected = '/[a-z0-9]{40}/'; + $result = $consumer->oauth_consumer_secret; + $this->assertPattern($expected, $result); + } + + public function testCreateToken() { + $expected = (object) array( + 'oauth_token' => 'request_token', 'oauth_token_secret' => 'request_secret' + ); + $result = Provider::create('token', 'request_token', 'request_secret'); + $this->assertEqual($expected, $result); + + $token = Provider::create('token'); + + $expected = '/[a-z0-9]{40}/'; + $result = $token->oauth_token; + $this->assertPattern($expected, $result); + + $expected = '/[a-z0-9]{40}/'; + $result = $token->oauth_token_secret; + $this->assertPattern($expected, $result); + } + + public function testVerify() { + $request = array( + 'params' => array( + 'oauth_consumer_key' => 'key', + 'oauth_nonce' => '4d31073c8ce205ecd3145d6cc0a3a4f6', + 'oauth_signature' => 'fKMyRb/Pysuu0XqRoxANOkyiL8I=', + 'oauth_signature_method' => 'HMAC-SHA1', 'oauth_timestamp' => '1259606608', + 'oauth_version' => '1.0', + ) + ); + $result = Provider::verify($request); + $this->assertTrue($result); + } + + public function testVerifyWithToken() { + $request = array( + 'params' => array( + 'oauth_consumer_key' => 'key', + 'oauth_nonce' => '4d31073c8ce205ecd3145d6cc0a3a4f6', + 'oauth_signature' => 'G/ZDnJOVbvVasoHH/XbDVzdwJ+U=', + 'oauth_signature_method' => 'HMAC-SHA1', 'oauth_timestamp' => '1259606608', + 'oauth_version' => '1.0', + ), + 'token' => array( + 'oauth_token' => 'request_token', 'oauth_token_secret' => 'request_secret' + ) + ); + $result = Provider::verify($request); + $this->assertTrue($result); + } } ?> \ No newline at end of file diff --git a/views/layouts/default.html.php b/views/layouts/default.html.php new file mode 100644 index 0000000..6c293f7 --- /dev/null +++ b/views/layouts/default.html.php @@ -0,0 +1,27 @@ +<?php +/** + * Lithium: the most rad php framework + * + * @copyright Copyright 2009, Union of RAD (http://union-of-rad.org) + * @license http://opensource.org/licenses/bsd-license.php The BSD License + */ +?> +<!doctype html> +<html> +<head> + <?php echo $this->html->charset(); ?> + <title><?=$this->title(); ?></title> + <?php echo $this->html->style('base'); ?> + <?php echo $this->scripts(); ?> + <?php echo $this->html->link('Icon', null, array('type' => 'icon')); ?> +</head> +<body> + <div id="container"> + <div id="header"></div> + <div id="content"> + <?php echo $this->content; ?> + </div> + <div id="footer"></div> + </div> +</body> +</html> diff --git a/views/server/account.html.php b/views/server/account.html.php new file mode 100644 index 0000000..e313e97 --- /dev/null +++ b/views/server/account.html.php @@ -0,0 +1,6 @@ +<div class="account"> + <ul> + <li>Key: <?=$token->oauth_consumer_key;?></li> + <li>Secret: <?=$token->oauth_consumer_secret;?></li> + </ul> +</div> \ No newline at end of file diff --git a/views/server/authorize.html.php b/views/server/authorize.html.php new file mode 100644 index 0000000..1c25527 --- /dev/null +++ b/views/server/authorize.html.php @@ -0,0 +1,6 @@ +<div class="authorize"> + <form method="POST"> + <input type="submit" name="deny" value="deny"> + <input type="submit" name="allow" value="allow"> + </form> +</div> \ No newline at end of file