Compare commits
6 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
f5d0dc8311 | |
|
|
324b8c2e96 | |
|
|
abd31ca0ef | |
|
|
5dedecb2f3 | |
|
|
9bf5abf964 | |
|
|
ec3b95aabc |
|
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
/*--------------------------------------------------------+
|
||||
| SYSTOPIA CiviProxy |
|
||||
| a simple proxy solution for external access to CiviCRM |
|
||||
| Author: McAndrews (michaelmcandrew@thirdsectordesign.org|
|
||||
+---------------------------------------------------------*/
|
||||
|
||||
function civiproxy_callback_validate_request_method($expected, $actual){
|
||||
if(is_array($expected) && in_array($actual, $expected)){
|
||||
return;
|
||||
}
|
||||
if(is_string($expected) && $expected == $actual){
|
||||
return;
|
||||
}
|
||||
civiproxy_http_error("Invalid request method.", 405);
|
||||
}
|
||||
|
||||
function civiproxy_callback_validate_content_type($expected, $actual){
|
||||
if($expected != $actual){
|
||||
civiproxy_http_error("Forbidden content type.", 403);
|
||||
}
|
||||
}
|
||||
|
||||
function civiproxy_callback_validate_body($expected, $actual, $content_type){
|
||||
switch ($content_type) {
|
||||
case 'application/json':
|
||||
civiproxy_callback_validate_body_json($expected, $actual);
|
||||
break;
|
||||
case 'application/x-www-form-urlencoded':
|
||||
civiproxy_callback_validate_body_xwwwformurlencoded($expected, $actual);
|
||||
break;
|
||||
default:
|
||||
civiproxy_http_error("Forbidden content type (expecting {$expected}).", 403);
|
||||
}
|
||||
}
|
||||
|
||||
function civiproxy_callback_validate_body_json($expected, $actual) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
function civiproxy_callback_validate_body_xwwwformurlencoded($expected, $actual) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
// For now, I have written this 'placeholder' method to pass on post requests.
|
||||
// Sparkpost says that it works OK. Might be a good idea to refactor/improve
|
||||
// civiproxy_redirect() instead/as well.
|
||||
function civiproxy_callback_redirect($target_path, $method) {
|
||||
switch ($method) {
|
||||
case 'POST':
|
||||
civiproxy_callback_redirect_post($target_path);
|
||||
break;
|
||||
case 'GET':
|
||||
civiproxy_callback_redirect_get($target_path);
|
||||
break;
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
// Change the URL, forward the body. Respond with the response
|
||||
function civiproxy_callback_redirect_post($target_path) {
|
||||
global $target_civicrm;
|
||||
$target_url = "$target_civicrm/{$target_path}";
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, file_get_contents('php://input'));
|
||||
curl_setopt($ch, CURLOPT_URL, $target_url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||
$response = curl_exec($ch);
|
||||
if (curl_error($ch)){
|
||||
civiproxy_http_error("CURL error (" . curl_errno($ch) . ") ".curl_error($ch) , 501);
|
||||
}
|
||||
|
||||
// I think that most callbacks just want a response code
|
||||
http_response_code(curl_getinfo($ch, CURLINFO_HTTP_CODE));
|
||||
|
||||
// But some might be interested in the response.
|
||||
echo $response;
|
||||
}
|
||||
|
||||
// Change the URL, forward the body. Respond with the response
|
||||
function civiproxy_callback_redirect_get($target_path) {
|
||||
global $target_civicrm;
|
||||
$target_url = "$target_civicrm/{$target_path}";
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $target_url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||
$response = curl_exec($ch);
|
||||
if (curl_error($ch)){
|
||||
civiproxy_http_error("CURL error (" . curl_errno($ch) . ") ".curl_error($ch) , 501);
|
||||
}
|
||||
|
||||
// I think that most callbacks just want a response code
|
||||
http_response_code(curl_getinfo($ch, CURLINFO_HTTP_CODE));
|
||||
|
||||
// But some might be interested in the response.
|
||||
echo $response;
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
/*--------------------------------------------------------+
|
||||
| SYSTOPIA CiviProxy |
|
||||
| a simple proxy solution for external access to CiviCRM |
|
||||
| Author: McAndrews (michaelmcandrew@thirdsectordesign.org|
|
||||
+---------------------------------------------------------*/
|
||||
|
||||
// Handles callback URLs as follows:
|
||||
// 1. Validates callback
|
||||
// 2. Passes to civicrm if the payload passes validation
|
||||
// 2. Returns an appropriate response (an HTML code)
|
||||
// Note: valid callbacks should be defined as elements of a $callbacks variable
|
||||
// in config.php.
|
||||
// Callback URL should be configured in the service as follows:
|
||||
// "{$proxy_base}/callback.php?source={$callbacks[$key]}&secret={$callbacks[$key]['secret']}"
|
||||
// where $key is a key defined in the $callbacks variable in config.php.
|
||||
|
||||
require_once "config.php";
|
||||
require_once "proxy.php";
|
||||
require_once "callback.functions.php";
|
||||
|
||||
civiproxy_security_check('callback');
|
||||
|
||||
if (!isset($callbacks_enabled) || $callbacks_enabled !==true){
|
||||
civiproxy_http_error("Feature disabled", 403);
|
||||
}
|
||||
|
||||
// Check that this callback has been defined
|
||||
parse_str($_SERVER['QUERY_STRING'], $query_params);
|
||||
if(isset($callbacks[$query_params['source']])){
|
||||
//Retrieve definition from config
|
||||
$definition = $callbacks[$query_params['source']];
|
||||
}else{
|
||||
civiproxy_http_error("Undefined callback", 403);
|
||||
}
|
||||
|
||||
// Check that a secret has been defined
|
||||
if(!isset($definition['secret'])){
|
||||
civiproxy_http_error("No secret defined for this callback", 501);
|
||||
}
|
||||
|
||||
// Check secret has been sent
|
||||
if(!isset($query_params['secret'])){
|
||||
civiproxy_http_error("Secret missing from query parameters", 403);
|
||||
}
|
||||
|
||||
// Check secret
|
||||
if(!isset($query_params['secret']) || $definition['secret'] !== $query_params['secret'] ){
|
||||
civiproxy_http_error("Invalid secret", 403);
|
||||
}
|
||||
|
||||
// Check this is a supported request method
|
||||
if(!in_array($_SERVER['REQUEST_METHOD'], ['GET', 'POST'])){
|
||||
civiproxy_http_error("Unsupported request method", 501);
|
||||
}
|
||||
|
||||
// If a request method has been defined, validate it
|
||||
if(isset($definition['request_method'])){
|
||||
civiproxy_callback_validate_request_method($definition['request_method'], $_SERVER['REQUEST_METHOD']);
|
||||
}
|
||||
|
||||
// Check this is a supported content type
|
||||
if(!in_array($_SERVER['CONTENT_TYPE'], ['application/json', 'application/x-www-form-urlencoded'])){
|
||||
civiproxy_http_error("Unsupported content type", 501);
|
||||
}
|
||||
|
||||
// If a content type has been defined, validate it
|
||||
if(isset($definition['content_type'])){
|
||||
civiproxy_callback_validate_content_type($definition['content_type'], $_SERVER['CONTENT_TYPE']);
|
||||
}
|
||||
|
||||
// TODO? implement body validation
|
||||
if(isset($validator['body'])){
|
||||
civiproxy_callback_validate_body($validator['body'], file_get_contents("php://input"), $_SERVER['CONTENT_TYPE']);
|
||||
}
|
||||
|
||||
// We have passed all the validators, forward the request
|
||||
civiproxy_callback_redirect($definition['target_path'], $_SERVER['REQUEST_METHOD']);
|
||||
|
|
@ -36,6 +36,11 @@ $target_mail_view = $target_civicrm . '/civicrm/mailing/view';
|
|||
** GENERAL OPTIONS **
|
||||
****************************************************************/
|
||||
|
||||
// Set this option to enable or disable callback processing
|
||||
// The individual callbacks still have to be defined
|
||||
// by the $callbacks variable, see below
|
||||
$callbacks_enabled = FALSE;
|
||||
|
||||
// This logo is shown if the proxy server is address with a web browser
|
||||
// add your own logo here
|
||||
$civiproxy_logo = "<img src='{$proxy_base}/static/images/proxy-logo.png' alt='SYSTOPIA Organisationsberatung'></img>";
|
||||
|
|
@ -117,3 +122,19 @@ $rest_allowed_actions = array(
|
|||
),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
/****************************************************************
|
||||
** ALLOWED CALLBACKS **
|
||||
****************************************************************/
|
||||
|
||||
// defines the callbacks that are to be forwarded to the target system
|
||||
// make sure $callbacks_enabled is TRUE for this to work
|
||||
$callbacks = array(
|
||||
'sparkpost_example' => array(
|
||||
'secret' => '85c573b980c3c248f083f9ca6a175659',
|
||||
'request_method' => 'POST', // single value or array
|
||||
'content_type' => 'application/json',
|
||||
'target_path' => 'civicrm/sparkpost/callback'
|
||||
)
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in New Issue