Verified Commit 785ffa71 authored by Andrei Mondoc's avatar Andrei Mondoc Committed by Kevin Cristiano

log in and sync wp user before dispatching rest response

Signed-off-by: Kevin Cristiano's avatarKevin Cristiano <kcristiano@kcristiano.com>
parent 834326b3
......@@ -451,7 +451,7 @@ class Rest extends Base {
* @param string $param
* @return bool
*/
protected function is_valid_json( $param ) {
public function is_valid_json( $param ) {
$param = json_decode( $param, true );
......@@ -467,7 +467,7 @@ class Rest extends Base {
* @since 0.1
* @return bool $is_valid_site_key
*/
private function is_valid_site_key() {
public function is_valid_site_key() {
return \CRM_Utils_System::authenticateKey( false );
......@@ -480,7 +480,7 @@ class Rest extends Base {
* @param WP_REST_Resquest $request
* @return bool $is_valid_api_key
*/
private function is_valid_api_key( $request ) {
public function is_valid_api_key( $request ) {
$api_key = $request->get_param( 'api_key' );
......@@ -488,73 +488,9 @@ class Rest extends Base {
$contact_id = \CRM_Core_DAO::getFieldValue( 'CRM_Contact_DAO_Contact', $api_key, 'id', 'api_key' );
// validate contact and login
if ( $contact_id ) {
if ( ! $contact_id ) return false;
$wp_user = $this->get_wp_user( $contact_id );
$this->do_user_login( $wp_user );
return true;
}
return false;
}
/**
* Get WordPress user data.
*
* @since 0.1
* @param int $contact_id The contact id
* @return bool|WP_User $user The WordPress user data
*/
protected function get_wp_user( int $contact_id ) {
try {
// Get CiviCRM domain group ID from constant, if set.
$domain_id = defined( 'CIVICRM_DOMAIN_ID' ) ? CIVICRM_DOMAIN_ID : 0;
// If this fails, get it from config.
if ( $domain_id === 0 ) {
$domain_id = \CRM_Core_Config::domainID();
}
// Call API.
$uf_match = civicrm_api3( 'UFMatch', 'getsingle', [
'contact_id' => $contact_id,
'domain_id' => $domain_id,
] );
} catch ( \CiviCRM_API3_Exception $e ) {
return $this->civi_rest_error( $e->getMessage() );
}
$wp_user = get_userdata( $uf_match['uf_id'] );
return $wp_user;
}
/**
* Logs in the WordPress user, needed to respect CiviCRM ACL and permissions.
*
* @since 0.1
* @param WP_User $user
*/
protected function do_user_login( \WP_User $user ) {
if ( is_user_logged_in() ) return;
wp_set_current_user( $user->ID, $user->user_login );
wp_set_auth_cookie( $user->ID );
do_action( 'wp_login', $user->user_login, $user );
return true;
}
......
......@@ -56,6 +56,17 @@ class Plugin {
civi_wp()->initialize();
// rest calls need a wp user, do login
if ( false !== strpos( $request->get_route(), 'rest' ) ) {
$logged_in_wp_user = $this->do_user_login( $request );
// return error
if ( is_wp_error( $logged_in_wp_user ) ) {
return $logged_in_wp_user;
}
}
}
return $result;
......@@ -201,4 +212,168 @@ class Plugin {
}
/**
* Performs the necessary checks and
* data retrieval to login a WordPress user.
*
* @since 0.1
* @param \WP_REST_Request $request The request
* @return \WP_User|\WP_Error|void $logged_in_wp_user The logged in WordPress user object, \Wp_Error, or nothing
*/
public function do_user_login( $request ) {
/**
* Filter and opportunity to bypass
* the default user login.
*
* @since 0.1
* @param bool $login
*/
$logged_in = apply_filters( 'civi_wp_rest/plugin/do_user_login', false, $request );
if ( $logged_in ) return;
// default login based on contact's api_key
if ( ! ( new Controller\Rest )->is_valid_api_key( $request ) ) {
return new \WP_Error(
'civicrm_rest_api_error',
__( 'Missing or invalid param "api_key".', 'civicrm' )
);
}
$contact_id = \CRM_Core_DAO::getFieldValue(
'CRM_Contact_DAO_Contact',
$request->get_param( 'api_key' ),
'id',
'api_key'
);
$wp_user = $this->get_wp_user( $contact_id );
if ( is_wp_error( $wp_user ) ) {
return $wp_user;
}
return $this->login_wp_user( $wp_user, $request );
}
/**
* Get WordPress user data.
*
* @since 0.1
* @param int $contact_id The contact id
* @return WP_User|WP_Error $user The WordPress user data or WP_Error object
*/
public function get_wp_user( int $contact_id ) {
try {
// Call API.
$uf_match = civicrm_api3( 'UFMatch', 'getsingle', [
'contact_id' => $contact_id,
'domain_id' => $this->get_civi_domain_id(),
] );
} catch ( \CiviCRM_API3_Exception $e ) {
return new \WP_Error(
'civicrm_rest_api_error',
__( 'A WordPress user must be associated with the contact for the provided API key.', 'civicrm' )
);
}
// filter uf_match
add_filter( 'civi_wp_rest/plugin/uf_match', function() use ( $uf_match ) {
return ! empty( $uf_match ) ? $uf_match : null;
} );
return get_userdata( $uf_match['uf_id'] );
}
/**
* Logs in the WordPress user, and
* syncs it with it's CiviCRM contact.
*
* @since 0.1
* @param \WP_User $user The WordPress user object
* @param \WP_REST_Request|null $request The request object or null
* @return \WP_User|void $wp_user The logged in WordPress user object or nothing
*/
public function login_wp_user( \WP_User $wp_user, $request = null ) {
/**
* Filter the user about to be logged in.
*
* @since 0.1
* @param \WP_User $user The WordPress user object
* @param \WP_REST_Request|null $request The request object or null
*/
$wp_user = apply_filters( 'civi_wp_rest/plugin/wp_user_login', $wp_user, $request );
wp_set_current_user( $wp_user->ID, $wp_user->user_login );
wp_set_auth_cookie( $wp_user->ID );
do_action( 'wp_login', $wp_user->user_login, $wp_user );
$this->set_civi_user_session( $wp_user );
return $wp_user;
}
/**
* Sets the necessary user
* session variables for CiviCRM.
*
* @since 0.1
* @param \WP_User $wp_user The WordPress user
* @return void
*/
public function set_civi_user_session( $wp_user ): void {
$uf_match = apply_filters( 'civi_wp_rest/plugin/uf_match', null );
if ( ! $uf_match ) {
// Call API.
$uf_match = civicrm_api3( 'UFMatch', 'getsingle', [
'uf_id' => $wp_user->ID,
'domain_id' => $this->get_civi_domain_id(),
] );
}
// Set necessary session variables.
$session = \CRM_Core_Session::singleton();
$session->set( 'ufID', $wp_user->ID );
$session->set( 'userID', $uf_match['contact_id'] );
$session->set( 'ufUniqID', $uf_match['uf_name'] );
}
/**
* Retrieves the CiviCRM domain_id.
*
* @since 0.1
* @return int $domain_id The domain id
*/
public function get_civi_domain_id(): int {
// Get CiviCRM domain group ID from constant, if set.
$domain_id = defined( 'CIVICRM_DOMAIN_ID' ) ? CIVICRM_DOMAIN_ID : 0;
// If this fails, get it from config.
if ( $domain_id === 0 ) {
$domain_id = \CRM_Core_Config::domainID();
}
return $domain_id;
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment