public function testDeleteActionRemoveRelation()
 {
     $this->logInWithPermission('ADMIN');
     $config = GridFieldConfig::create()->addComponent(new GridFieldDeleteAction(true));
     $gridField = new GridField('testfield', 'testfield', $this->list, $config);
     $form = new Form(new Controller(), 'mockform', new FieldList(array($this->gridField)), new FieldList());
     $stateID = 'testGridStateActionField';
     Session::set($stateID, array('grid' => '', 'actionName' => 'deleterecord', 'args' => array('RecordID' => $this->idFromFixture('GridFieldAction_Delete_Team', 'team1'))));
     $token = SecurityToken::inst();
     $request = new SS_HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID=' . $stateID => true, $token->getName() => $token->getValue()));
     $this->gridField->gridFieldAlterAction(array('StateID' => $stateID), $this->form, $request);
     $this->assertEquals(2, $this->list->count(), 'User should be able to delete records with ADMIN permission.');
 }
 /**
  * Invoke a batch action
  *
  * @param SS_HTTPRequest $request
  * @return SS_HTTPResponse
  */
 public function handleBatchAction($request)
 {
     // This method can't be called without ajax.
     if (!$request->isAjax()) {
         return $this->parentController->redirectBack();
     }
     // Protect against CSRF on destructive action
     if (!SecurityToken::inst()->checkRequest($request)) {
         return $this->httpError(400);
     }
     // Find the action handler
     $action = $request->param('BatchAction');
     $actionHandler = $this->actionByName($action);
     // Sanitise ID list and query the database for apges
     $csvIDs = $request->requestVar('csvIDs');
     $ids = $this->cleanIDs($csvIDs);
     // Filter ids by those which are applicable to this action
     // Enforces front end filter in LeftAndMain.BatchActions.js:refreshSelected
     $ids = $actionHandler->applicablePages($ids);
     // Query ids and pass to action to process
     $pages = $this->getPages($ids);
     return $actionHandler->run($pages);
 }
 /**
  * Update the position and parent of a tree node.
  * Only saves the node if changes were made.
  *
  * Required data:
  * - 'ID': The moved node
  * - 'ParentID': New parent relation of the moved node (0 for root)
  * - 'SiblingIDs': Array of all sibling nodes to the moved node (incl. the node itself).
  *   In case of a 'ParentID' change, relates to the new siblings under the new parent.
  *
  * @param HTTPRequest $request
  * @return HTTPResponse JSON string with a
  * @throws HTTPResponse_Exception
  */
 public function savetreenode($request)
 {
     if (!SecurityToken::inst()->checkRequest($request)) {
         return $this->httpError(400);
     }
     if (!Permission::check('SITETREE_REORGANISE') && !Permission::check('ADMIN')) {
         $this->getResponse()->setStatusCode(403, _t('LeftAndMain.CANT_REORGANISE', "You do not have permission to rearange the site tree. Your change was not saved."));
         return;
     }
     $className = $this->stat('tree_class');
     $statusUpdates = array('modified' => array());
     $id = $request->requestVar('ID');
     $parentID = $request->requestVar('ParentID');
     if ($className == 'SilverStripe\\CMS\\Model\\SiteTree' && ($page = DataObject::get_by_id('Page', $id))) {
         $root = $page->getParentType();
         if (($parentID == '0' || $root == 'root') && !SiteConfig::current_site_config()->canCreateTopLevel()) {
             $this->getResponse()->setStatusCode(403, _t('LeftAndMain.CANT_REORGANISE', "You do not have permission to alter Top level pages. Your change was not saved."));
             return;
         }
     }
     $siblingIDs = $request->requestVar('SiblingIDs');
     $statusUpdates = array('modified' => array());
     if (!is_numeric($id) || !is_numeric($parentID)) {
         throw new InvalidArgumentException();
     }
     $node = DataObject::get_by_id($className, $id);
     if ($node && !$node->canEdit()) {
         return Security::permissionFailure($this);
     }
     if (!$node) {
         $this->getResponse()->setStatusCode(500, _t('LeftAndMain.PLEASESAVE', "Please Save Page: This page could not be updated because it hasn't been saved yet."));
         return;
     }
     // Update hierarchy (only if ParentID changed)
     if ($node->ParentID != $parentID) {
         $node->ParentID = (int) $parentID;
         $node->write();
         $statusUpdates['modified'][$node->ID] = array('TreeTitle' => $node->TreeTitle);
         // Update all dependent pages
         if (class_exists('SilverStripe\\CMS\\Model\\VirtualPage')) {
             $virtualPages = VirtualPage::get()->filter("CopyContentFromID", $node->ID);
             foreach ($virtualPages as $virtualPage) {
                 $statusUpdates['modified'][$virtualPage->ID] = array('TreeTitle' => $virtualPage->TreeTitle());
             }
         }
         $this->getResponse()->addHeader('X-Status', rawurlencode(_t('LeftAndMain.REORGANISATIONSUCCESSFUL', 'Reorganised the site tree successfully.')));
     }
     // Update sorting
     if (is_array($siblingIDs)) {
         $counter = 0;
         foreach ($siblingIDs as $id) {
             if ($id == $node->ID) {
                 $node->Sort = ++$counter;
                 $node->write();
                 $statusUpdates['modified'][$node->ID] = array('TreeTitle' => $node->TreeTitle);
             } else {
                 if (is_numeric($id)) {
                     // Nodes that weren't "actually moved" shouldn't be registered as
                     // having been edited; do a direct SQL update instead
                     ++$counter;
                     DB::prepared_query("UPDATE \"{$className}\" SET \"Sort\" = ? WHERE \"ID\" = ?", array($counter, $id));
                 }
             }
         }
         $this->getResponse()->addHeader('X-Status', rawurlencode(_t('LeftAndMain.REORGANISATIONSUCCESSFUL', 'Reorganised the site tree successfully.')));
     }
     return Convert::raw2json($statusUpdates);
 }
 public function testInstReturnsSingleton()
 {
     $inst1 = SecurityToken::inst();
     $inst2 = SecurityToken::inst();
     $this->assertEquals($inst1, $inst2);
 }
 /**
  * Returns the value of an the global SecurityToken in the current session
  * @return int
  */
 public static function getSecurityID()
 {
     $token = SecurityToken::inst();
     return $token->getValue();
 }
 /**
  * REST endpoint to publish a {@link ChangeSet} and all of its items.
  *
  * @param HTTPRequest $request
  *
  * @return HTTPResponse
  */
 public function publishCampaign(HTTPRequest $request)
 {
     // Protect against CSRF on destructive action
     if (!SecurityToken::inst()->checkRequest($request)) {
         return new HTTPResponse(null, 400);
     }
     $id = $request->param('ID');
     if (!$id || !is_numeric($id)) {
         return new HTTPResponse(null, 400);
     }
     /** @var ChangeSet $record */
     $record = ChangeSet::get()->byID($id);
     if (!$record) {
         return new HTTPResponse(null, 404);
     }
     if (!$record->canPublish()) {
         return new HTTPResponse(null, 403);
     }
     try {
         $record->publish();
     } catch (LogicException $e) {
         return (new HTTPResponse(json_encode(['status' => 'error', 'message' => $e->getMessage()]), 401))->addHeader('Content-Type', 'application/json');
     }
     return (new HTTPResponse(Convert::raw2json($this->getChangeSetResource($record)), 200))->addHeader('Content-Type', 'application/json');
 }
 public function testDisableSecurityTokenAcceptsSubmissionWithoutToken()
 {
     SecurityToken::enable();
     $expectedToken = SecurityToken::inst()->getValue();
     $response = $this->get('FormTest_ControllerWithSecurityToken');
     // can't use submitForm() as it'll automatically insert SecurityID into the POST data
     $response = $this->post('FormTest_ControllerWithSecurityToken/Form', array('Email' => '*****@*****.**', 'action_doSubmit' => 1));
     $this->assertEquals(400, $response->getStatusCode(), 'Submission fails without security token');
     // Generate a new token which doesn't match the current one
     $generator = new RandomGenerator();
     $invalidToken = $generator->randomToken('sha1');
     $this->assertNotEquals($invalidToken, $expectedToken);
     // Test token with request
     $response = $this->get('FormTest_ControllerWithSecurityToken');
     $response = $this->post('FormTest_ControllerWithSecurityToken/Form', array('Email' => '*****@*****.**', 'action_doSubmit' => 1, 'SecurityID' => $invalidToken));
     $this->assertEquals(200, $response->getStatusCode(), 'Submission reloads form if security token invalid');
     $this->assertTrue(stripos($response->getBody(), 'name="SecurityID" value="' . $expectedToken . '"') !== false, 'Submission reloads with correct security token after failure');
     $this->assertTrue(stripos($response->getBody(), 'name="SecurityID" value="' . $invalidToken . '"') === false, 'Submission reloads without incorrect security token after failure');
     $matched = $this->cssParser()->getBySelector('#Form_Form_Email');
     $attrs = $matched[0]->attributes();
     $this->assertEquals('*****@*****.**', (string) $attrs['value'], 'Submitted data is preserved');
     $response = $this->get('FormTest_ControllerWithSecurityToken');
     $tokenEls = $this->cssParser()->getBySelector('#Form_Form_SecurityID');
     $this->assertEquals(1, count($tokenEls), 'Token form field added for controller without disableSecurityToken()');
     $token = (string) $tokenEls[0];
     $response = $this->submitForm('Form_Form', null, array('Email' => '*****@*****.**', 'SecurityID' => $token));
     $this->assertEquals(200, $response->getStatusCode(), 'Submission suceeds with security token');
 }
 /**
  * Creates a single folder, within an optional parent folder.
  *
  * @param HTTPRequest $request
  * @return HTTPRequest|HTTPResponse
  */
 public function apiCreateFolder(HTTPRequest $request)
 {
     $data = $request->postVars();
     $class = 'SilverStripe\\Assets\\Folder';
     // CSRF check
     $token = SecurityToken::inst();
     if (empty($data[$token->getName()]) || !$token->check($data[$token->getName()])) {
         return new HTTPResponse(null, 400);
     }
     // check addchildren permissions
     /** @var Folder $parentRecord */
     $parentRecord = null;
     if (!empty($data['ParentID']) && is_numeric($data['ParentID'])) {
         $parentRecord = DataObject::get_by_id($class, $data['ParentID']);
     }
     $data['Parent'] = $parentRecord;
     $data['ParentID'] = $parentRecord ? (int) $parentRecord->ID : 0;
     // Build filename
     $baseFilename = isset($data['Name']) ? basename($data['Name']) : _t('SilverStripe\\AssetAdmin\\Controller\\AssetAdmin.NEWFOLDER', "NewFolder");
     if ($parentRecord && $parentRecord->ID) {
         $baseFilename = $parentRecord->getFilename() . '/' . $baseFilename;
     }
     // Ensure name is unique
     $nameGenerator = $this->getNameGenerator($baseFilename);
     $filename = null;
     foreach ($nameGenerator as $filename) {
         if (!File::find($filename)) {
             break;
         }
     }
     $data['Name'] = basename($filename);
     // Create record
     /** @var Folder $record */
     $record = Injector::inst()->create($class);
     // check create permissions
     if (!$record->canCreate(null, $data)) {
         return (new HTTPResponse(null, 403))->addHeader('Content-Type', 'application/json');
     }
     $record->ParentID = $data['ParentID'];
     $record->Name = $record->Title = basename($data['Name']);
     $record->write();
     $result = $this->getObjectFromData($record);
     return (new HTTPResponse(json_encode($result)))->addHeader('Content-Type', 'application/json');
 }