From e29feeecac717eb0507e7da34f772a03b0386f91 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Sat, 9 Aug 2008 07:03:24 +0000 Subject: [PATCH] (merged from branches/roa. use "svn log -c -g " for detailed commit message) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@60235 467b73ca-7a2a-4603-9d3b-597d59a354a9 --- code/ModelAdmin.php | 16 ++- javascript/ModelAdmin.js | 5 +- tests/RestfulServerTest.php | 216 ++++++++++++++++++++++++++++++++++++ tests/RestfulServerTest.yml | 38 +++++++ 4 files changed, 271 insertions(+), 4 deletions(-) create mode 100644 tests/RestfulServerTest.php create mode 100644 tests/RestfulServerTest.yml diff --git a/code/ModelAdmin.php b/code/ModelAdmin.php index 43b3b47a..dbdaa479 100644 --- a/code/ModelAdmin.php +++ b/code/ModelAdmin.php @@ -46,6 +46,16 @@ abstract class ModelAdmin extends LeftAndMain { 'handleItem' ); + /** + * @param string $collection_controller_class Override for controller class + */ + protected static $collection_controller_class = "ModelAdmin_CollectionController"; + + /** + * @param string $collection_controller_class Override for controller class + */ + protected static $record_controller_class = "ModelAdmin_RecordController"; + /** * Forward control to the default action handler */ @@ -129,7 +139,8 @@ abstract class ModelAdmin extends LeftAndMain { * Base scaffolding method for returning a generic model instance. */ public function bindModelController($model, $request = null) { - return new ModelAdmin_CollectionController($this, $model); + $class = $this->stat('collection_controller_class'); + return new $class($this, $model); } /** @@ -319,7 +330,8 @@ class ModelAdmin_CollectionController extends Controller { * @return RecordController */ function handleID($request) { - return new ModelAdmin_RecordController($this, $request); + $class = $this->parentController->stat('record_controller_class'); + return new $class($this, $request); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/javascript/ModelAdmin.js b/javascript/ModelAdmin.js index dd1478c1..de2f0f9d 100644 --- a/javascript/ModelAdmin.js +++ b/javascript/ModelAdmin.js @@ -75,9 +75,10 @@ jQuery(document).ready(function() { /** * attach generic action handler to all forms displayed in the #right panel */ - jQuery('#right .action').livequery('click', function(){ + jQuery('#right #form_actions_right .action').livequery('click', function(){ form = jQuery('#right form'); - saveRecord(form.attr('action'), formData(form)); + var formAction = form.attr('action') + '?' + jQuery(this).fieldSerialize(); + saveRecord(formAction, formData(form)); return false; }); diff --git a/tests/RestfulServerTest.php b/tests/RestfulServerTest.php new file mode 100644 index 00000000..c8983a2f --- /dev/null +++ b/tests/RestfulServerTest.php @@ -0,0 +1,216 @@ +assertEquals($response->getStatusCode(), 200); + + $_SERVER['PHP_AUTH_USER'] = 'user@test.com'; + $_SERVER['PHP_AUTH_PW'] = 'user'; + + // even with logged in user a GET with $api_access disabled should fail + $url = "/api/v1/RestfulServerTest_Page/1"; + $response = Director::test($url, null, null, 'GET'); + $this->assertEquals($response->getStatusCode(), 403); + } + + /* + public function testAuthenticatedGET() { + // @todo create additional mock object with authenticated VIEW permissions + $url = "/api/v1/RestfulServerTest_Comment/1"; + $response = Director::test($url, null, null, 'GET'); + $this->assertEquals($response->getStatusCode(), 403); + + $_SERVER['PHP_AUTH_USER'] = 'user@test.com'; + $_SERVER['PHP_AUTH_PW'] = 'user'; + + $url = "/api/v1/RestfulServerTest_Comment/1"; + $response = Director::test($url, null, null, 'GET'); + $this->assertEquals($response->getStatusCode(), 200); + } + */ + + public function testAuthenticatedPUT() { + $url = "/api/v1/RestfulServerTest_Comment/1"; + $data = array('Comment' => 'created'); + + $response = Director::test($url, $data, null, 'PUT'); + $this->assertEquals($response->getStatusCode(), 403); // Permission failure + + $_SERVER['PHP_AUTH_USER'] = 'editor@test.com'; + $_SERVER['PHP_AUTH_PW'] = 'editor'; + $response = Director::test($url, $data, null, 'PUT'); + $this->assertEquals($response->getStatusCode(), 200); // Success + } + + public function testPUTWithFormEncoded() { + $_SERVER['PHP_AUTH_USER'] = 'editor@test.com'; + $_SERVER['PHP_AUTH_PW'] = 'editor'; + + $url = "/api/v1/RestfulServerTest_Comment/1"; + $data = array('Comment' => 'updated'); + $response = Director::test($url, $data, null, 'PUT'); + $this->assertEquals($response->getStatusCode(), 200); // Success + // Assumption: XML is default output + $responseArr = Convert::xml2array($response->getBody()); + $this->assertEquals($responseArr['ID'], 1); + $this->assertEquals($responseArr['Comment'], 'updated'); + } + + public function testPOSTWithFormEncoded() { + $_SERVER['PHP_AUTH_USER'] = 'editor@test.com'; + $_SERVER['PHP_AUTH_PW'] = 'editor'; + + $url = "/api/v1/RestfulServerTest_Comment"; + $data = array('Comment' => 'created'); + $response = Director::test($url, $data, null, 'POST'); + $this->assertEquals($response->getStatusCode(), 201); // Created + // Assumption: XML is default output + $responseArr = Convert::xml2array($response->getBody()); + $this->assertEquals($responseArr['ID'], 2); + $this->assertEquals($responseArr['Comment'], 'created'); + } + + public function testPUTwithJSON() { + $_SERVER['PHP_AUTH_USER'] = 'editor@test.com'; + $_SERVER['PHP_AUTH_PW'] = 'editor'; + + // by mimetype + $url = "/api/v1/RestfulServerTest_Comment/1"; + $body = '{"Comment":"updated"}'; + $response = Director::test($url, null, null, 'PUT', $body, array('Content-Type'=>'application/json')); + $this->assertEquals($response->getStatusCode(), 200); // Updated + $obj = Convert::json2obj($response->getBody()); + $this->assertEquals($obj->ID, 1); + $this->assertEquals($obj->Comment, 'updated'); + + // by extension + $url = "/api/v1/RestfulServerTest_Comment/1.json"; + $body = '{"Comment":"updated"}'; + $response = Director::test($url, null, null, 'PUT', $body); + $this->assertEquals($response->getStatusCode(), 200); // Updated + $obj = Convert::json2obj($response->getBody()); + $this->assertEquals($obj->ID, 1); + $this->assertEquals($obj->Comment, 'updated'); + } + + public function testPUTwithXML() { + $_SERVER['PHP_AUTH_USER'] = 'editor@test.com'; + $_SERVER['PHP_AUTH_PW'] = 'editor'; + + // by mimetype + $url = "/api/v1/RestfulServerTest_Comment/1"; + $body = 'updated'; + $response = Director::test($url, null, null, 'PUT', $body, array('Content-Type'=>'text/xml')); + $this->assertEquals($response->getStatusCode(), 200); // Updated + $obj = Convert::xml2array($response->getBody()); + $this->assertEquals($obj['ID'], 1); + $this->assertEquals($obj['Comment'], 'updated'); + + // by extension + $url = "/api/v1/RestfulServerTest_Comment/1.xml"; + $body = 'updated'; + $response = Director::test($url, null, null, 'PUT', $body); + $this->assertEquals($response->getStatusCode(), 200); // Updated + $obj = Convert::xml2array($response->getBody()); + $this->assertEquals($obj['ID'], 1); + $this->assertEquals($obj['Comment'], 'updated'); + } + + public function testHTTPAcceptAndContentType() { + $url = "/api/v1/RestfulServerTest_Comment/1"; + + $headers = array('Accept' => 'application/json'); + $response = Director::test($url, null, null, 'GET', null, $headers); + $this->assertEquals($response->getStatusCode(), 200); // Success + $obj = Convert::json2obj($response->getBody()); + $this->assertEquals($obj->ID, 1); + $this->assertEquals($response->getHeader('Content-Type'), 'application/json'); + } + + public function testNotFound(){ + $_SERVER['PHP_AUTH_USER'] = 'user@test.com'; + $_SERVER['PHP_AUTH_PW'] = 'user'; + + $url = "/api/v1/RestfulServerTest_Comment/99"; + $response = Director::test($url, null, null, 'GET'); + $this->assertEquals($response->getStatusCode(), 404); + } + + public function testMethodNotAllowed() { + $url = "/api/v1/RestfulServerTest_Comment/1"; + $response = Director::test($url, null, null, 'UNKNOWNHTTPMETHOD'); + $this->assertEquals($response->getStatusCode(), 405); + } + + public function testUnsupportedMediaType() { + $url = "/api/v1/RestfulServerTest_Comment/1"; + $data = "Comment||\/||updated"; // weird format + $headers = array('Content-Type' => 'text/weirdformat'); + $response = Director::test($url, null, null, 'POST', $data, $headers); + $this->assertEquals($response->getStatusCode(), 415); + } + +} + +/** + * Everybody can view comments, logged in members in the "users" group can create comments, + * but only "editors" can edit or delete them. + * + */ +class RestfulServerTest_Comment extends DataObject implements PermissionProvider,TestOnly { + + static $api_access = true; + + static $db = array( + "Name" => "Varchar(255)", + "Comment" => "Text" + ); + + public function providePermissions(){ + return array( + 'EDIT_Comment' => 'Edit Comment Objects', + 'CREATE_Comment' => 'Create Comment Objects', + 'DELETE_Comment' => 'Delete Comment Objects', + ); + } + + public function canView($member = null) { + return true; + } + + public function canEdit($member = null) { + return Permission::checkMember($member, 'EDIT_Comment'); + } + + public function canDelete($member = null) { + return Permission::checkMember($member, 'DELETE_Comment'); + } + + public function canCreate($member = null) { + return Permission::checkMember($member, 'CREATE_Comment'); + } + +} + +class RestfulServerTest_Page extends DataObject implements TestOnly { + + static $api_access = false; + + static $db = array( + 'Title' => 'Text', + 'Content' => 'HTMLText', + ); +} +?> \ No newline at end of file diff --git a/tests/RestfulServerTest.yml b/tests/RestfulServerTest.yml new file mode 100644 index 00000000..cdc371ad --- /dev/null +++ b/tests/RestfulServerTest.yml @@ -0,0 +1,38 @@ +RestfulServerTest_Comment: + comment1: + Name: Joe + Comment: This is a test comment +Member: + editor: + FirstName: Editor + Email: editor@test.com + Password: editor + user: + FirstName: User + Email: user@test.com + Password: user +Group: + editorgroup: + Title: Editors + Code: editors + Members: =>Member.editor + usergroup: + Title: Users + Code: users + Members: =>Member.user +Permission: + perm1: + Code: CREATE_Comment + Group: =>Group.usergroup + perm3: + Code: EDIT_Comment + Group: =>Group.editorgroup + perm4: + Code: DELETE_Comment + Group: =>Group.editorgroup + perm5: + Code: CREATE_Comment + Group: =>Group.editorgroup +RestfulServerTest_Page: + page1: + Title: Testpage without API Access \ No newline at end of file