/**
  * Delegate the request to the correct method and
  * wrap the response (including exceptions) in a
  * JsonDataResponse
  * @param SS_HTTPRequest $request
  * @param DataModel $model
  * @return string|JsonDataResponse|SS_HTTPResponse|null
  * @throws JsonDataResponse
  * @throws SS_HTTPResponse_Exception
  */
 public function handleRequest(SS_HTTPRequest $request, DataModel $model)
 {
     $body = null;
     $verb = strtolower($request->httpMethod());
     $availableVerbs = $this->config()->get('allowed_verbs');
     $id = $request->param('ID');
     $resourceType = 'List';
     if ($id && is_numeric($id)) {
         $resourceType = 'Data';
     }
     $methodName = $verb . $resourceType;
     try {
         if (in_array(strtoupper($verb), $availableVerbs) && $this->hasMethod($methodName)) {
             $body = $this->{$methodName}($request);
         }
     } catch (SS_HTTPResponse_Exception $exception) {
         $response = $exception->getResponse();
         throw new JsonDataResponse_Exception($response->getBody(), $response->getStatusCode(), $response->getStatusDescription());
     }
     if ($body instanceof JsonDataResponse) {
         return $body;
     }
     if ($body instanceof SS_HTTPResponse) {
         return new JsonDataResponse($body->getBody(), $body->getStatusCode(), $body->getStatusDescription());
     }
     if (is_string($body)) {
         return new JsonDataResponse($body);
     }
     throw new JsonDataResponse_Exception("The URI requested has not been implement", 404);
 }
 /**
  * Maps the http method to action handlers. Forces the response to have
  * application/json content type. Unhandled methods will return a 404 response code.
  * @param SS_HTTPRequest $request
  * @return mixed
  * @throws SS_HTTPResponse_Exception
  */
 public function index(SS_HTTPRequest $request)
 {
     $action = ucfirst(strtolower($request->httpMethod()));
     $actionHandler = sprintf('handle%sAction', $action);
     if ($this->hasMethod($actionHandler)) {
         $response = $this->{$actionHandler}($request);
         $response->addHeader('Content-Type', 'application/json');
         return $response;
     }
     throw new SS_HTTPResponse_Exception(json_encode(array('code' => 404, 'description' => 'The action has not been implemented')), 404);
 }
 /**
  * @param  \SS_HTTPRequest $request
  * @return array
  */
 public function process(\SS_HTTPRequest $request)
 {
     $httpMethod = $request->httpMethod();
     if ($httpMethod == 'POST' && $request->param('ID') == 'complete') {
         //get the payment dps txnref from the database
         //1. Get session id for transaction from state
         //2. Get payment from storage
         //3. Use txn ref from storage to complete the payment
         $sessionId = $this->state->getByKey(self::IDENTIFIER . '.sessionid');
         if ($sessionId) {
             // get the PXFusion payment associated with this sessionid
             $payment = \DataList::create('StoredPXFusionPayment')->filter("SessionId", $sessionId)->first();
             if ($payment instanceof \StoredPXFusionPayment && $payment->DpsTxnRef) {
                 // Set the transaction status to processing
                 $this->transaction->setStatus('Processing');
                 // Keep track of the payment status
                 $paymentSuccessful = false;
                 $storedPxPostPayment = false;
                 $paymentResponse = $this->paymentService->completeTransaction($payment->DpsTxnRef);
                 if ($paymentResponse instanceof PXPostPaymentResponse) {
                     // Store the payment response
                     $storedPxPostPayment = $this->storage->process($paymentResponse)[Backend::IDENTIFIER];
                     $paymentResponse->updateTransaction($this->transaction);
                     $paymentSuccessful = (bool) $paymentResponse->Success;
                 }
                 // store the transaction
                 $storedTransaction = $this->storage->process($this->transaction)[Backend::IDENTIFIER];
                 $payment->ParentID = $storedTransaction->ID;
                 if ($storedPxPostPayment && $storedTransaction) {
                     // set the parents of each object
                     $payment->PXPostPaymentID = $storedPxPostPayment->ID;
                     $payment->write();
                     $storedPxPostPayment->ParentID = $storedTransaction->ID;
                     $storedPxPostPayment->write();
                 } else {
                     $payment->write();
                     return ['Success' => false];
                 }
                 return ['Success' => $paymentSuccessful, 'Complete' => true, 'Data' => $paymentResponse];
             }
         }
     } elseif ($httpMethod == 'GET' && $request->param('ID') == 'check') {
         $paymentResponse = $this->paymentService->checkTransaction($request->getVar('sessionid'));
         $this->state->setByKey(self::IDENTIFIER . '.sessionid', $request->getVar('sessionid'));
         $this->storage->process($paymentResponse);
         if ($paymentResponse->StatusCode === 0) {
             return ['Success' => true, 'Data' => $paymentResponse];
         } else {
             return ['Success' => false, 'CheckFailure' => true];
         }
     }
     return ['Success' => false];
 }
 /**
  * @param SS_HTTPRequest $request
  * @return SS_HTTPResponse
  */
 public function update(\SS_HTTPRequest $request)
 {
     switch ($request->httpMethod()) {
         case 'POST':
             $this->checkSecurityToken();
             return $this->createUpdate();
         case 'GET':
             return $this->getUpdateStatus($this->getRequest()->param('ID'));
         default:
             return $this->getAPIResponse(['message' => 'Method not allowed, requires POST or GET/{id}'], 405);
     }
 }
Beispiel #5
0
 /**
  *
  * @param SS_HTTPRequest $request
  * @return SS_HTTPResponse
  */
 public function listProjects(SS_HTTPRequest $request)
 {
     $response = array('href' => Director::absoluteURL($this->Link()), 'projects' => array());
     if ($request->httpMethod() != 'GET') {
         return $this->message('API not found', 404);
     }
     foreach (DNProject::get() as $item) {
         if ($item->canView($this->getMember())) {
             $response['projects'][] = array("name" => $item->Name, "href" => Director::absoluteURL($item->APILink("")));
         }
     }
     return $this->getAPIResponse($response);
 }
 /**
  * @param SS_HTTPRequest $request
  * @return SS_HTTPResponse
  */
 public function fetch(SS_HTTPRequest $request)
 {
     if (!$this->record->canView($this->getMember())) {
         return $this->message('You are not authorized to do that on this environment', 403);
     }
     switch ($request->httpMethod()) {
         case 'GET':
             return $this->getFetch($this->getRequest()->param('ID'));
         case 'POST':
             return $this->createFetch();
         default:
             return $this->message('API not found', 404);
     }
 }
 public function handleRequest(SS_HTTPRequest $request, DataModel $model = null)
 {
     self::$is_at_root = true;
     $this->setDataModel($model);
     $this->pushCurrent();
     $this->init();
     if (!($site = Multisites::inst()->getCurrentSiteId())) {
         return $this->httpError(404);
     }
     $page = SiteTree::get()->filter(array('ParentID' => $site, 'URLSegment' => 'home'));
     if (!($page = $page->first())) {
         return $this->httpError(404);
     }
     $request = new SS_HTTPRequest($request->httpMethod(), $page->RelativeLink(), $request->getVars(), $request->postVars());
     $request->match('$URLSegment//$Action', true);
     $front = new MultisitesFrontController();
     $response = $front->handleRequest($request, $model);
     $this->popCurrent();
     return $response;
 }
 function handleRequest(SS_HTTPRequest $request, DataModel $model)
 {
     $this->request = $request;
     $method = $request->httpMethod();
     if ($this->checkAccessAction($method)) {
         try {
             $request = $this->{$method}($request);
             // TODO: Abstract this out to API module, as it's application specific
             Session::save();
             return $request;
         } catch (Exception $e) {
             if ($e instanceof SS_HTTPResponse_Exception) {
                 throw $e;
             } elseif ($e instanceof RESTException) {
                 $this->respondWithError(array('code' => $e->getCode(), 'exception' => $e));
             } else {
                 $this->respondWithError(array('code' => 500, 'exception' => $e));
             }
         }
     }
     $this->respondWithError(array('code' => 403, 'exception' => new Exception('Method not allowed')));
 }
 /**
  * Main API hub switch
  * All requests pass through here and are redirected depending on HTTP verb and params
  *
  * @todo move authentication check to another methode
  * 
  * @param  SS_HTTPRequest   $request    HTTP request
  * @return string                       json object of the models found
  */
 public function index(SS_HTTPRequest $request)
 {
     //check authentication if enabled
     if ($this->authenticator) {
         $policy = $this->config()->authentication_policy;
         $authALL = $policy === true;
         $authMethod = is_array($policy) && in_array($request->httpMethod(), $policy);
         if ($authALL || $authMethod) {
             $authResult = $this->authenticator->authenticate($request);
             if ($authResult instanceof RESTfulAPI_Error) {
                 //Authentication failed return error to client
                 return $this->error($authResult);
             }
         }
     }
     //pass control to query handler
     $data = $this->queryHandler->handleQuery($request);
     //catch + return errors
     if ($data instanceof RESTfulAPI_Error) {
         return $this->error($data);
     }
     //serialize response
     $json = $this->serializer->serialize($data);
     //catch + return errors
     if ($json instanceof RESTfulAPI_Error) {
         return $this->error($json);
     }
     //all is good reply normally
     return $this->answer($json);
 }
 /**
  * Handle a form submission.  GET and POST requests behave identically.
  * Populates the form with {@link loadDataFrom()}, calls {@link validate()},
  * and only triggers the requested form action/method
  * if the form is valid.
  *
  * @param SS_HTTPRequest $request
  * @throws SS_HTTPResponse_Exception
  */
 public function httpSubmission($request)
 {
     // Strict method check
     if ($this->strictFormMethodCheck) {
         // Throws an error if the method is bad...
         if ($this->formMethod != $request->httpMethod()) {
             $response = Controller::curr()->getResponse();
             $response->addHeader('Allow', $this->formMethod);
             $this->httpError(405, _t("Form.BAD_METHOD", "This form requires a " . $this->formMethod . " submission"));
         }
         // ...and only uses the variables corresponding to that method type
         $vars = $this->formMethod == 'GET' ? $request->getVars() : $request->postVars();
     } else {
         $vars = $request->requestVars();
     }
     // Populate the form
     $this->loadDataFrom($vars, true);
     // Protection against CSRF attacks
     $token = $this->getSecurityToken();
     if (!$token->checkRequest($request)) {
         $securityID = $token->getName();
         if (empty($vars[$securityID])) {
             $this->httpError(400, _t("Form.CSRF_FAILED_MESSAGE", "There seems to have been a technical problem. Please click the back button, " . "refresh your browser, and try again."));
         } else {
             // Clear invalid token on refresh
             $data = $this->getData();
             unset($data[$securityID]);
             Session::set("FormInfo.{$this->FormName()}.data", $data);
             Session::set("FormInfo.{$this->FormName()}.errors", array());
             $this->sessionMessage(_t("Form.CSRF_EXPIRED_MESSAGE", "Your session has expired. Please re-submit the form."), "warning");
             return $this->controller->redirectBack();
         }
     }
     // Determine the action button clicked
     $funcName = null;
     foreach ($vars as $paramName => $paramVal) {
         if (substr($paramName, 0, 7) == 'action_') {
             // Break off querystring arguments included in the action
             if (strpos($paramName, '?') !== false) {
                 list($paramName, $paramVars) = explode('?', $paramName, 2);
                 $newRequestParams = array();
                 parse_str($paramVars, $newRequestParams);
                 $vars = array_merge((array) $vars, (array) $newRequestParams);
             }
             // Cleanup action_, _x and _y from image fields
             $funcName = preg_replace(array('/^action_/', '/_x$|_y$/'), '', $paramName);
             break;
         }
     }
     // If the action wasn't set, choose the default on the form.
     if (!isset($funcName) && ($defaultAction = $this->defaultAction())) {
         $funcName = $defaultAction->actionName();
     }
     if (isset($funcName)) {
         Form::set_current_action($funcName);
         $this->setButtonClicked($funcName);
     }
     // Permission checks (first on controller, then falling back to form)
     if ($this->controller->hasMethod($funcName) && !$this->controller->checkAccessAction($funcName) && !$this->actions->dataFieldByName('action_' . $funcName)) {
         return $this->httpError(403, sprintf('Action "%s" not allowed on controller (Class: %s)', $funcName, get_class($this->controller)));
     } elseif ($this->hasMethod($funcName) && !$this->checkAccessAction($funcName)) {
         return $this->httpError(403, sprintf('Action "%s" not allowed on form (Name: "%s")', $funcName, $this->name));
     }
     // TODO : Once we switch to a stricter policy regarding allowed_actions (meaning actions must be set
     // explicitly in allowed_actions in order to run)
     // Uncomment the following for checking security against running actions on form fields
     /* else {
     			// Try to find a field that has the action, and allows it
     			$fieldsHaveMethod = false;
     			foreach ($this->Fields() as $field){
     				if ($field->hasMethod($funcName) && $field->checkAccessAction($funcName)) {
     					$fieldsHaveMethod = true;
     				}
     			}
     			if (!$fieldsHaveMethod) {
     				return $this->httpError(
     					403,
     					sprintf('Action "%s" not allowed on any fields of form (Name: "%s")', $funcName, $this->Name())
     				);
     			}
     		}*/
     // Validate the form
     if (!$this->validate()) {
         return $this->getValidationErrorResponse();
     }
     // First, try a handler method on the controller (has been checked for allowed_actions above already)
     if ($this->controller->hasMethod($funcName)) {
         return $this->controller->{$funcName}($vars, $this, $request);
         // Otherwise, try a handler method on the form object.
     } elseif ($this->hasMethod($funcName)) {
         return $this->{$funcName}($vars, $this, $request);
     } elseif ($field = $this->checkFieldsForAction($this->Fields(), $funcName)) {
         return $field->{$funcName}($vars, $this, $request);
     }
     return $this->httpError(404);
 }
 /**
  * Check if we're in a login request. If so, we're going to explicitly disable
  * restrictedobjects permission checks. This is poor, but dictated by the core
  * member login code performing writes prior to having a user context.
  * 
  * @param \SS_HTTPRequest $request
  * @param \Session $session
  * @param \DataModel $model
  */
 public function preRequest(\SS_HTTPRequest $request, \Session $session, \DataModel $model)
 {
     if (strtolower($request->httpMethod()) === 'post' && ($request->getURL() === 'Security/LoginForm' || $request->getURL() === 'Security/LostPasswordForm' || $request->getURL() === 'Security/ChangePasswordForm')) {
         Restrictable::set_enabled(false);
     }
 }
 /**
  * Delete object of Class $model and ID $id
  *
  * @todo  Respond with a 204 status message on success?
  * 
  * @param  string          $model     Model class
  * @param  integer 				 $id        Model ID
  * @param  SS_HTTPRequest  $request   Model ID
  * @return NULL|array                 NULL if successful or array with error detail              
  */
 function deleteModel($model, $id, SS_HTTPRequest $request)
 {
     if ($id) {
         $object = DataObject::get_by_id($model, $id);
         if ($object) {
             if (!RESTfulAPI::api_access_control($object, $request->httpMethod())) {
                 return new RESTfulAPI_Error(403, "API access denied.");
             }
             $object->delete();
         } else {
             return new RESTfulAPI_Error(404, "Record not found.");
         }
     } else {
         //shouldn't happen but just in case
         return new RESTfulAPI_Error(400, "Invalid or missing ID. Received '{$id}'.");
     }
     return NULL;
 }
 /**
  * @param \SS_HTTPRequest $request
  * @return \SS_HTTPResponse
  */
 public function abort(\SS_HTTPRequest $request)
 {
     if ($request->httpMethod() !== 'POST') {
         return $this->getAPIResponse(['message' => 'Method not allowed, requires POST'], 405);
     }
     $this->checkSecurityToken();
     if (!self::can_abort_deployment($this->environment)) {
         return $this->getAPIResponse(['message' => 'You are not authorised to perform this action'], 403);
     }
     $deployment = \DNDeployment::get()->byId($request->postVar('id'));
     $errorResponse = $this->validateDeployment($deployment);
     if ($errorResponse instanceof \SS_HTTPResponse) {
         return $errorResponse;
     }
     try {
         $deployment->getMachine()->apply(\DNDeployment::TR_ABORT);
     } catch (\Exception $e) {
         return $this->getAPIResponse(['message' => $e->getMessage()], 400);
     }
     return $this->sendResponse(['message' => 'Deployment abort request successfully received', 'deployment' => $this->formatter->getDeploymentData($deployment)], 200);
 }
 /**
  * Process input requests which are relevant to purchasables
  *
  * @param  \SS_HTTPRequest $request
  * @return array           Success/Failure
  */
 public function process(\SS_HTTPRequest $request)
 {
     if (!in_array($request->httpMethod(), ['POST', 'PUT'])) {
         return $this->failed('Invalid method');
     }
     if (!($id = $request->param('OtherID'))) {
         return $this->failed('No id provided');
     }
     /** @var PurchasableInterface $purchasable */
     $purchasable = $this->getPurchasable($request);
     if (!$purchasable instanceof $this->purchasableClass) {
         return $this->failed("Product doesn't exist");
     }
     $action = $request->param('ID');
     try {
         switch ($action) {
             case 'add':
                 return $this->addPurchasable($request, $purchasable);
                 break;
             case 'set':
                 return $this->setPurchasable($request, $purchasable);
                 break;
             case 'remove':
                 return $this->removePurchasable($request, $purchasable);
                 break;
             default:
                 return $this->failed('Action not allowed');
                 break;
         }
     } catch (OverflowException $e) {
         return $this->failed('Cart bounds exceeded');
     }
 }
 /**
  * @param \SS_HTTPRequest $request
  * @return \SS_HTTPResponse
  */
 public function reject(\SS_HTTPRequest $request)
 {
     if ($request->httpMethod() !== 'POST') {
         return $this->getAPIResponse(['message' => 'Method not allowed, requires POST'], 405);
     }
     $this->checkSecurityToken();
     $deployment = \DNDeployment::get()->byId($request->postVar('id'));
     $errorResponse = $this->validateDeployment($deployment);
     if ($errorResponse instanceof \SS_HTTPResponse) {
         return $errorResponse;
     }
     // reject permissions are the same as can approve
     if (!self::can_approve($this->environment)) {
         return $this->getAPIResponse(['message' => 'You are not authorised to reject this deployment'], 403);
     }
     // if the current user is not the person who was selected for approval on submit, but they got
     // here because they still have permission, then change the approver to the current user
     if (\Member::currentUserID() !== $deployment->ApproverID) {
         $deployment->ApproverID = \Member::currentUserID();
     }
     if ($request->postVar('rejected_reason')) {
         $deployment->RejectedReason = $request->postVar('rejected_reason');
     }
     try {
         $deployment->getMachine()->apply(\DNDeployment::TR_REJECT);
     } catch (\Exception $e) {
         return $this->getAPIResponse(['message' => $e->getMessage()], 400);
     }
     return $this->getAPIResponse(['message' => 'Deployment request has been rejected', 'deployment' => $this->formatter->getDeploymentData($deployment)], 200);
 }
 /**
  * @param SS_HTTPRequest $request
  * @return SS_HTTPResponse
  */
 public function handleRequest(SS_HTTPRequest $request, DataModel $model = null)
 {
     self::$is_at_root = true;
     $this->setDataModel($model);
     $this->pushCurrent();
     $this->init();
     if (!DB::isActive() || !ClassInfo::hasTable('SiteTree')) {
         $this->response = new SS_HTTPResponse();
         $this->response->redirect(Director::absoluteBaseURL() . 'dev/build?returnURL=' . (isset($_GET['url']) ? urlencode($_GET['url']) : null));
         return $this->response;
     }
     $request = new SS_HTTPRequest($request->httpMethod(), self::get_homepage_link() . '/', $request->getVars(), $request->postVars());
     $request->match('$URLSegment//$Action', true);
     $controller = new ModelAsController();
     $result = $controller->handleRequest($request, $model);
     $this->popCurrent();
     return $result;
 }
 /**
  * Returns the http method for this request. If the current environment is a development env, the method can be
  * changed with a `method` variable.
  *
  * @param SS_HTTPRequest $request the current request
  * @return string the used http method as string
  */
 private function getMethodName($request)
 {
     $method = '';
     if (Director::isDev() && ($varMethod = $request->getVar('method'))) {
         if (in_array(strtoupper($varMethod), array('GET', 'POST', 'PUT', 'DELETE', 'HEAD'))) {
             $method = $varMethod;
         }
     } else {
         $method = $request->httpMethod();
     }
     return strtolower($method);
 }