--- /dev/null
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 4.6 |
+ +--------------------------------------------------------------------+
+ | Copyright (C) 2011 Marty Wright |
+ | Licensed to CiviCRM under the Academic Free License version 3.0. |
+ +--------------------------------------------------------------------+
+ | This file is a part of CiviCRM. |
+ | |
+ | CiviCRM is free software; you can copy, modify, and distribute it |
+ | under the terms of the GNU Affero General Public License |
+ | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
+ | |
+ | CiviCRM is distributed in the hope that it will be useful, but |
+ | WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
+ | See the GNU Affero General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Affero General Public |
+ | License and the CiviCRM Licensing Exception along |
+ | with this program; if not, contact CiviCRM LLC |
+ | at info[AT]civicrm[DOT]org. If you have questions about the |
+ | GNU Affero General Public License or the licensing of CiviCRM, |
+ | see the CiviCRM license FAQ at http://civicrm.org/licensing |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ *
+ * @package CRM
+ * @copyright CiviCRM LLC (c) 2004-2014
+ * $Id$
+ *
+ */
+
+/**
+ * This class helps to manage connections to third-party apps.
+ */
+class CRM_Cxn_BAO_Cxn extends CRM_Cxn_DAO_Cxn {
+ public static function getSiteCallbackUrl() {
+ $config = CRM_Core_Config::singleton();
+ if (preg_match('/^(http|https):/', $config->resourceBase)) {
+ $civiUrl = $config->resourceBase;
+ }
+ else {
+ $civiUrl = rtrim(CRM_Utils_System::baseURL(), '/') . '/' . ltrim($config->resourceBase, '/');
+ }
+ return rtrim($civiUrl, '/') . '/extern/cxn.php';
+ }
+
+ public static function updateAppMeta($appMeta) {
+ \Civi\Cxn\Rpc\AppMeta::validate($appMeta);
+ CRM_Core_DAO::executeQuery('UPDATE civicrm_cxn SET app_meta = %1 WHERE app_id = %2', array(
+ 1 => array(json_encode($appMeta), 'String'),
+ 2 => array($appMeta['appId'], 'String'),
+ ));
+ }
+}
--- /dev/null
+<?php
+
+class CRM_Cxn_CiviCxnStore implements Civi\Cxn\Rpc\CxnStore\CxnStoreInterface {
+
+ protected $cxns = array();
+
+ /**
+ * @inheritDoc
+ */
+ public function getAll() {
+ if (!$this->cxns) {
+ $this->cxns = array();
+ $dao = new CRM_Cxn_DAO_Cxn();
+ $dao->find();
+ while ($dao->fetch()) {
+ $cxn = $this->convertDaoToCxn($dao);
+ $this->cxns[$cxn['cxnId']] = $cxn;
+ }
+ }
+ return $this->cxns;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getByCxnId($cxnId) {
+ if (isset($this->cxns[$cxnId])) {
+ return $this->cxns[$cxnId];
+ }
+ $dao = new CRM_Cxn_DAO_Cxn();
+ $dao->cxn_id = $cxnId;
+ if ($dao->find(TRUE)) {
+ $this->cxns[$cxnId] = $this->convertDaoToCxn($dao);
+ return $this->cxns[$cxnId];
+ }
+ else {
+ return NULL;
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getByAppId($appId) {
+ $dao = new CRM_Cxn_DAO_Cxn();
+ $dao->app_id = $appId;
+ if ($dao->find(TRUE)) {
+ $this->cxns[$dao->cxn_id] = $this->convertDaoToCxn($dao);
+ return $this->cxns[$dao->cxn_id];
+ }
+ else {
+ return NULL;
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function add($cxn) {
+ $dao = new CRM_Cxn_DAO_Cxn();
+ $dao->cxn_id = $cxn['cxnId'];
+ $dao->find(TRUE);
+ $this->convertCxnToDao($cxn, $dao);
+ $dao->save();
+
+ $sql = '
+ UPDATE civicrm_cxn SET created_date = modified_date
+ WHERE created_date IS NULL
+ AND cxn_guid = %1
+ ';
+ CRM_Core_DAO::executeQuery($sql, array(
+ 1 => array($cxn['cxnId'], 'String'),
+ ));
+
+ $this->cxns[$cxn['cxnId']] = $cxn;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function remove($cxnId) {
+ CRM_Core_DAO::executeQuery('DELETE FROM civicrm_cxn WHERE cxn_id = %1', array(
+ 1 => array($cxnId, 'String'),
+ ));
+ unset($this->cxns[$cxnId]);
+ }
+
+ /**
+ * @param CRM_Cxn_DAO_Cxn $dao
+ * @return array
+ * Array-encoded connection details.
+ */
+ protected function convertDaoToCxn($dao) {
+ $appMeta = json_decode($dao->app_meta, TRUE);
+ return array(
+ 'cxnId' => $dao->cxn_id,
+ 'secret' => $dao->secret,
+ 'appId' => $dao->app_id,
+ 'appUrl' => $appMeta['appUrl'],
+ 'siteUrl' => CRM_Cxn_BAO_Cxn::getSiteCallbackUrl(),
+ 'perm' => json_decode($dao->perm, TRUE),
+ );
+ }
+
+ /**
+ * @param array $cxn
+ * Array-encoded connection details.
+ * @param CRM_Cxn_DAO_Cxn $dao
+ */
+ protected function convertCxnToDao($cxn, $dao) {
+ $dao->cxn_id = $cxn['cxnId'];
+ $dao->secret = $cxn['secret'];
+ $dao->app_id = $cxn['appId'];
+ $dao->perm = json_encode($cxn['perm']);
+
+ // Note: we don't save siteUrl because it's more correct to regenerate on-demand.
+ // Note: we don't save appUrl, but other processes will update appMeta.
+ }
+}
--- /dev/null
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 4.6 |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2014 |
+ +--------------------------------------------------------------------+
+ | This file is a part of CiviCRM. |
+ | |
+ | CiviCRM is free software; you can copy, modify, and distribute it |
+ | under the terms of the GNU Affero General Public License |
+ | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
+ | |
+ | CiviCRM is distributed in the hope that it will be useful, but |
+ | WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
+ | See the GNU Affero General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Affero General Public |
+ | License and the CiviCRM Licensing Exception along |
+ | with this program; if not, contact CiviCRM LLC |
+ | at info[AT]civicrm[DOT]org. If you have questions about the |
+ | GNU Affero General Public License or the licensing of CiviCRM, |
+ | see the CiviCRM license FAQ at http://civicrm.org/licensing |
+ +--------------------------------------------------------------------+
+ */
+
+
+/**
+ * @param array $params
+ * Array with keys:
+ * - appMeta: the application's metadata.
+ * @return array
+ */
+function civicrm_api3_cxn_register($params) {
+ if (empty($params['appMeta']) && !empty($params['appMetaUrl'])) {
+ if (defined('CIVICRM_CXN_VERIFY') && !CIVICRM_CXN_VERIFY) {
+ list ($status, $json) = CRM_Utils_HttpClient::singleton()->get($params['appMetaUrl']);
+ if (CRM_Utils_HttpClient::STATUS_OK != $status) {
+ throw new API_Exception("Failed to download appMeta.");
+ }
+ $params['appMeta'] = json_decode($json, TRUE);
+ }
+ else {
+ // Note: The metadata includes a cert, but the details aren't signed.
+ // This is very useful in testing/development. In ordinary usage, we
+ // rely on a general signature for the full batch of all metadata.
+ throw new API_Exception('This site is configured to only use verified metadata.');
+ }
+ }
+
+ if (empty($params['appMeta']) || !is_array($params['appMeta'])) {
+ throw new API_Exception("Missing expected parameter: appMeta (array)");
+ }
+ \Civi\Cxn\Rpc\AppMeta::validate($params['appMeta']);
+
+ // FIXME Move cxnStore and client into Container.
+ $cxnStore = new CRM_Cxn_CiviCxnStore();
+ try {
+ $client = new \Civi\Cxn\Rpc\RegistrationClient(NULL, $cxnStore, CRM_Cxn_BAO_Cxn::getSiteCallbackUrl());
+ $client->setLog(new CRM_Utils_SystemLogger());
+ list($cxnId, $isOk) = $client->register($params['appMeta']);
+ CRM_Cxn_BAO_Cxn::updateAppMeta($params['appMeta']);
+ }
+ catch (Exception $e) {
+ CRM_Cxn_BAO_Cxn::updateAppMeta($params['appMeta']);
+ throw $e;
+ }
+
+ if ($isOk) {
+ $result = array(
+ 'cxnId' => $cxnId,
+ );
+ return civicrm_api3_create_success();
+ }
+ else {
+ return civicrm_api3_create_error('Connection failed');
+ }
+}
--- /dev/null
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 4.6 |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2014 |
+ +--------------------------------------------------------------------+
+ | This file is a part of CiviCRM. |
+ | |
+ | CiviCRM is free software; you can copy, modify, and distribute it |
+ | under the terms of the GNU Affero General Public License |
+ | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
+ | |
+ | CiviCRM is distributed in the hope that it will be useful, but |
+ | WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
+ | See the GNU Affero General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Affero General Public |
+ | License and the CiviCRM Licensing Exception along |
+ | with this program; if not, contact CiviCRM LLC |
+ | at info[AT]civicrm[DOT]org. If you have questions about the |
+ | GNU Affero General Public License or the licensing of CiviCRM, |
+ | see the CiviCRM license FAQ at http://civicrm.org/licensing |
+ +--------------------------------------------------------------------+
+ */
+
+require_once '../civicrm.config.php';
+$config = CRM_Core_Config::singleton();
+
+CRM_Utils_System::loadBootStrap(array(), FALSE);
+
+$apiServer = new \Civi\Cxn\Rpc\ApiServer(new CRM_Cxn_CiviCxnStore());
+$apiServer->setLog(new CRM_Utils_SystemLogger());
+$apiServer->setRouter(function ($cxn, $entity, $action, $params) {
+ require_once 'api/v3/utils.php';
+
+ // Note: cxnId is authenticated before router is called.
+ $dao = new CRM_Cxn_DAO_Cxn();
+ $dao->cxn_id = $cxn['cxnId'];
+ if (empty($cxn['cxnId']) || !$dao->find(TRUE) || !$dao->cxn_id) {
+ return civicrm_api3_create_error('Failed to lookup connection authorizations.');
+ }
+ if (!$dao->is_active) {
+ return civicrm_api3_create_error('Connection is inactive');
+ }
+
+ // FIXME: apply $dao->perm
+
+ return civicrm_api($entity, $action, $params);
+
+});
+$apiServer->handleAndRespond(file_get_contents('php://input'));