예제 #1
0
/**
 * @param object $submitteddata
 *
 */
function vmoodle_bind_to_network($submitteddata, &$newmnet_host)
{
    global $USER, $CFG, $DB, $OUTPUT;
    // debug_trace("step 4.4 : binding to subnetwork");
    // Getting services schemes to apply
    // debug_trace("step 4.4.1 : getting services");
    vmoodle_get_service_strategy($submitteddata, $services, $peerservices, 'peer');
    // debug_trace("step 4.4.2 : getting possible peers");
    $idnewblock = $DB->get_field('local_vmoodle', 'id', array('vhostname' => $submitteddata->vhostname));
    // last mnet has been raised by one at step 3 so we add to network if less
    if ($submitteddata->mnet < vmoodle_get_last_subnetwork_number()) {
        // Retrieves the subnetwork member(s).
        $subnetwork_hosts = array();
        $select = 'id != ? AND mnet = ? AND enabled = 1';
        $subnetwork_members = $DB->get_records_select('local_vmoodle', $select, array($idnewblock, $submitteddata->mnet));
        if (!empty($subnetwork_members)) {
            // debug_trace("step 4.4.3 : preparing peers");
            foreach ($subnetwork_members as $subnetwork_member) {
                $temp_host = new stdClass();
                $temp_host->wwwroot = $subnetwork_member->vhostname;
                $temp_host->name = utf8_decode($subnetwork_member->name);
                $subnetwork_hosts[] = $temp_host;
            }
        }
        // Member(s) of the subnetwork add the new host.
        if (!empty($subnetwork_hosts)) {
            // debug_trace("step 4.4.4 : bind peers");
            $rpc_client = new \local_vmoodle\XmlRpc_Client();
            $rpc_client->reset_method();
            $rpc_client->set_method('local/vmoodle/rpclib.php/mnetadmin_rpc_bind_peer');
            // Authentication params.
            $rpc_client->add_param($USER->username, 'string');
            $userhostroot = $DB->get_field('mnet_host', 'wwwroot', array('id' => $USER->mnethostid));
            $rpc_client->add_param($userhostroot, 'string');
            $rpc_client->add_param($CFG->wwwroot, 'string');
            // Peer to bind to.
            $rpc_client->add_param((array) $newmnet_host, 'array');
            $rpc_client->add_param($peerservices, 'array');
            foreach ($subnetwork_hosts as $subnetwork_host) {
                // debug_trace("step 4.4.4.1 : bind to -> $subnetwork_host->wwwroot");
                $temp_member = new \local_vmoodle\Mnet_Peer();
                $temp_member->set_wwwroot($subnetwork_host->wwwroot);
                if (!$rpc_client->send($temp_member)) {
                    echo $OUTPUT->notification(implode('<br />', $rpc_client->getErrors($temp_member)));
                    if (debugging()) {
                        echo '<pre>';
                        // var_dump($rpc_client);
                        echo '</pre>';
                    }
                }
                // debug_trace("step 4.4.4.1 : bind from <- $subnetwork_host->wwwroot");
                $rpc_client_2 = new \local_vmoodle\XmlRpc_Client();
                $rpc_client_2->reset_method();
                $rpc_client_2->set_method('local/vmoodle/rpclib.php/mnetadmin_rpc_bind_peer');
                // Authentication params.
                $rpc_client_2->add_param($USER->username, 'string');
                $userhostroot = $DB->get_field('mnet_host', 'wwwroot', array('id' => $USER->mnethostid));
                $rpc_client_2->add_param($userhostroot, 'string');
                $rpc_client_2->add_param($CFG->wwwroot, 'string');
                // Peer to bind to.
                $rpc_client_2->add_param((array) $temp_member, 'array');
                $rpc_client_2->add_param($services, 'array');
                if (!$rpc_client_2->send($newmnet_host)) {
                    echo $OUTPUT->notification(implode('<br />', $rpc_client_2->getErrors($newmnet_host)));
                    if (debugging()) {
                        echo '<pre>';
                        // var_dump($rpc_client_2);
                        echo '</pre>';
                    }
                }
                unset($rpc_client_2);
                // free some resource
            }
        }
    }
    // Getting services schemes to apply to main
    // debug_trace("step 4.4.5 : getting services");
    vmoodle_get_service_strategy($submitteddata, $services, $peerservices, 'main');
    // debug_trace("step 4.4.5.1 : bind to -> $CFG->wwwroot");
    $mainhost = new \local_vmoodle\Mnet_Peer();
    // this is us
    $mainhost->set_wwwroot($CFG->wwwroot);
    // debug_trace('step 4.4.5.2 : Binding our main service strategy to remote');
    // bind the local service strategy to new host
    if (!empty($peerservices)) {
        $DB->delete_records('mnet_host2service', array('hostid' => $newmnet_host->id));
        // eventually deletes something on the way
        foreach ($peerservices as $servicename => $servicestate) {
            $service = $DB->get_record('mnet_service', array('name' => $servicename));
            $host2service = new stdclass();
            $host2service->hostid = $newmnet_host->id;
            $host2service->serviceid = $service->id;
            $host2service->publish = 0 + @$servicestate->publish;
            $host2service->subscribe = 0 + @$servicestate->subscribe;
            $DB->insert_record('mnet_host2service', $host2service);
            // debug_trace("step 4.4.5.2 : adding ".serialize($host2service));
        }
    }
    // debug_trace('step 4.4.5.4 : Binding remote service strategy to main');
    $rpc_client = new \local_vmoodle\XmlRpc_Client();
    $rpc_client->reset_method();
    $rpc_client->set_method('local/vmoodle/rpclib.php/mnetadmin_rpc_bind_peer');
    $rpc_client->add_param($USER->username, 'string');
    $userhostroot = $DB->get_field('mnet_host', 'wwwroot', array('id' => $USER->mnethostid));
    $rpc_client->add_param($userhostroot, 'string');
    $rpc_client->add_param($CFG->wwwroot, 'string');
    // Peer to bind to : this is us.
    $rpc_client->add_param((array) $mainhost, 'array');
    $rpc_client->add_param($services, 'array');
    // debug_trace('step 4.4.5.4 : Sending');
    if (!$rpc_client->send($newmnet_host)) {
        // echo $OUTPUT->notification(implode('<br />', $rpc_client->getErrors($newmnet_host)));
        if (debugging()) {
            echo '<pre>';
            // var_dump($rpc_client);
            echo '</pre>';
        }
    }
}
예제 #2
0
/**
 * force user account creation.
 * @param object $callinguser The calling user.
 * @param string $targetuser The username of the user to be created.
 * @param array $userparams an array containing all data for user.
 * @param string $userhostname the user's origin account.
 * @param array $bounceto an array of or a string containing hostnames to propagate users to.
 * @param boolean $onlybounce if true, do not try to create the user locally, just bounce.
 *
 * if userhostname is empty, the user is created with an account bound to the localhost mnethost id (local account) and
 * reset to manual auth if the auth is 'mnet' (note the auth will remain unchanged if other than mnet, so it is possible to preset
 * an SAML or LDAP bound account.
 * If userhostname is not empty, the call forces auth being mnet, whatever the auth field was set to, and the hostname is searched
 * for a local matching host in mnet_hosts.
 *
 * If bounceto is not empty, the account will be propagated to matching mnet_hosts in the MNET proximity.
 * The onlybounce feature is provided for using this rpc function using a local direct call to propagate a user programatically
 * a user to some bounce locations
 */
function mnetadmin_rpc_create_user($callinguser, $targetuser, $userparams, $userhostname = '', $bounceto = null, $onlybounce = false, $json_response = true, $overridecapability = false)
{
    global $CFG, $USER, $DB;
    $response = new StdClass();
    $response->status = RPC_SUCCESS;
    $response->errors = array();
    $response->error = '';
    $userparamsarr = (array) $userparams;
    $capability = '';
    if (!$overridecapability) {
        $capability = 'local/vmoodle:execute';
    }
    if ($auth_response = invoke_local_user((array) $callinguser, $capability)) {
        if ($json_response) {
            return $auth_response;
        } else {
            return json_decode($auth_response);
        }
    }
    // be sure of our structure type.
    $callinguser = (object) $callinguser;
    if (!$onlybounce) {
        if (function_exists('debug_trace')) {
            debug_trace("Up to create {$targetuser} ");
        }
        if (!($user = $DB->get_record('user', array('username' => $targetuser)))) {
            // Collect eventual profilefields and cleanup user record from them.
            foreach ($userparamsarr as $key => $value) {
                if (preg_match('/^profile_field_/', $key)) {
                    $profilefields[$key] = $value;
                    unset($userparams[$key]);
                }
            }
            if (function_exists('debug_trace')) {
                debug_trace("Making new user record");
            }
            $newuser = (object) $userparams;
            $newuser->username = $targetuser;
            // Remap local mnethostid and auth method if needed.
            if (!empty($userhostname)) {
                if (!($originuserhost = $DB->get_record('mnet_host', array('wwwroot' => $userhostname)))) {
                    // If we fail to find real origin host for the user, take request host as failover.
                    if (function_exists('debug_trace')) {
                        debug_trace("REMOTE CALL ERROR : Bad origin host. Trying {$callinguser->remotehostroot} as failover");
                    }
                    if (!($originuserhost = $DB->get_record('mnet_host', array('wwwroot' => $callinguser->remotehostroot)))) {
                        if (function_exists('debug_trace')) {
                            debug_trace("REMOTE CALL ERROR : Bad origin host " . json_encode($userhostname));
                        }
                        $response = new StdClass();
                        $response->status = 510;
                        $response->errors[] = "Bad origin host " . json_encode($userhostname) . ", or origin host of the user is not known by this host.";
                        $response->error = "Bad origin host " . json_encode($userhostname) . ", or origin host of the user is not known by this host.";
                        if ($json_response) {
                            return json_encode($response);
                        } else {
                            return $response;
                        }
                    }
                }
                $newuser->mnethostid = $originuserhost->id;
                if ($originuserhost->id != $CFG->mnet_localhost_id && (empty($newuser->auth) || $newuser->auth == 'manual')) {
                    $newuser->auth = 'mnet';
                } else {
                    if (empty($newuser->auth) || $newuser->auth == 'mnet') {
                        $newuser->auth = 'manual';
                    }
                }
            } else {
                $newuser->mnethostid = $CFG->mnet_localhost_id;
                if (empty($newuser->auth) || $newuser->auth == 'mnet') {
                    $newuser->auth = 'manual';
                }
            }
            $newuser->confirmed = 1;
            $newuser->timemodified = time();
            if (function_exists('debug_trace')) {
                debug_trace("REMOTE CALL : recording user");
            }
            if (!($userid = $DB->insert_record('user', $newuser))) {
                if (function_exists('debug_trace')) {
                    debug_trace("REMOTE CALL ERROR : User creation failure");
                }
                $response->status = RPC_FAILURE_RECORD;
                $response->errors[] = "Could not create the user.";
                $response->error = "Could not create the user.";
                if ($json_response) {
                    return json_encode($response);
                } else {
                    return $response;
                }
            }
            $response->userid = $userid;
            // add profilefields
            if (function_exists('debug_trace')) {
                debug_trace("REMOTE CALL : Adding profile fields");
            }
            if (!empty($profilefields)) {
                foreach ($profilefields as $key => $value) {
                    $key = str_replace('profile_field_', '', $key);
                    // extract real shortname
                    if ($field = $DB->get_record('user_info_field', array('shortname' => $key))) {
                        // Do insert only if known field. Ignore others.
                        $valuerec->userid = $userid;
                        $valuerec->fieldid = $field->id;
                        $valuerec->data = $value;
                        $DB->insert_record('user_info_data', $valuerec);
                    }
                }
            }
        } else {
            if (function_exists('debug_trace')) {
                debug_trace("REMOTE CALL : Reviving user");
            }
            if ($user->deleted == 1) {
                $user->deleted = 0;
                foreach ($userparams as $key => $value) {
                    $user->{$key} = $value;
                }
                $user->username = $targetuser;
                if (!($userid = $DB->update_record('user', $user))) {
                    if (function_exists('debug_trace')) {
                        debug_trace("REMOTE CALL ERROR : User revival failure");
                    }
                    $response->status = RPC_FAILURE_RECORD;
                    $response->errors[] = "Create user REMOTE CALL : Could not revive the user.";
                    $response->error = "Create user REMOTE CALL : Could not revive the user.";
                    if ($json_response) {
                        return json_encode($response);
                    } else {
                        return $response;
                    }
                }
                $response->userid = $userid;
            } else {
                if (function_exists('debug_trace')) {
                    debug_trace("Create user REMOTE CALL : User exists");
                }
                /*
                // usually create user matching user should be happy with that
                $response->status = RPC_SUCCESS;
                $response->errors[] = "User already exists.";
                $response->error = "User already exists.";
                if ($json_response) {
                    return json_encode($response);
                } else {
                    return $response;
                }
                */
            }
        }
    } else {
        if (!($userparams = $DB->get_record('user', array('username' => $targetuser)))) {
            $response->status = RPC_FAILURE_RECORD;
            $response->errors[] = "Create user REMOTE CALL : No such user to propagate.";
            $response->error = "Create user REMOTE CALL : No such user to propagate.";
            if ($json_response) {
                return json_encode($response);
            } else {
                return $response;
            }
        }
        if (function_exists('debug_trace')) {
            debug_trace('Create user REMOTE CALL : got user data as ' . json_encode($userparams));
        }
    }
    // Now proceed to bounces if any.
    if (!empty($bounceto)) {
        if (is_string($bounceto)) {
            $bounceto = explode(';', $bounceto);
        }
        foreach ($bounceto as $bouncehost) {
            // Check if known as mnet_hosts and possible to send admin requests.
            $sql = "\n                SELECT\n                    COUNT(*)\n                FROM \n                    {mnet_host} as mh,\n                    {mnet_service} as ms,\n                    {mnet_host2service} as h2s\n                WHERE\n                    mh.wwwroot = '{$bouncehost}' AND\n                    mh.id = h2s.hostid AND\n                    mh.deleted = 0 AND\n                    h2s.serviceid = ms.id AND\n                    ms.name = 'mnetadmin' AND\n                    h2s.subscribe = 1\n            ";
            $ok = $DB->count_records_sql($sql);
            if ($ok) {
                // We can do it.
                $userhostroot = $DB->get_field('mnet_host', 'wwwroot', array('id' => $USER->mnethostid));
                $rpc_client = new \local_vmoodle\XmlRpc_Client();
                $rpc_client->reset_method();
                $rpc_client->set_method('local/vmoodle/plugins/roles/rpclib.php/mnetadmin_rpc_create_user');
                $caller = new StdClass();
                $caller->username = $USER->username;
                $caller->remoteuserhostroot = $userhostroot;
                $caller->remotehostroot = $CFG->wwwroot;
                $rpc_client->add_param($caller, 'struct');
                // username
                $rpc_client->add_param($targetuser, 'string');
                $rpc_client->add_param($userparams, 'struct');
                if ($userhostname == '') {
                    $rpc_client->add_param($CFG->wwwroot, 'string');
                } else {
                    $rpc_client->add_param($userhostname, 'string');
                }
                if (function_exists('debug_trace')) {
                    debug_trace("REMOTE CALL : Bouncing to {$bouncehost} ");
                }
                $mnet_host = new mnet_peer();
                if ($mnet_host->set_wwwroot($bouncehost)) {
                    $result = $rpc_client->send($mnet_host);
                    if (empty($result)) {
                        // if (preg_match('/dev/', $CFG->wwwroot)) print_object($rpc_client);
                        $response->errors[] = 'Create user : bounce failed rpc transaction to ' . $bouncehost;
                        $response->errors[] = $rpc_client->getErrors();
                        $response->error = 'Create user : bounce failed rpc transaction to ' . $bouncehost;
                    } else {
                        // whatever we have, aggregate eventual remote errors to error stack.
                        $res = json_decode($rpc_client->response);
                        if (!empty($res->errors)) {
                            foreach ($res->errors as $remoteerror) {
                                $response->errors[] = 'REMOTE: ' . implode(' ', (array) $remoteerror);
                                $response->error = 'REMOTE : bounce failed rpc some of transactions to ' . $bouncehost;
                            }
                        }
                    }
                } else {
                    // silently ignore unless debugging
                    if (function_exists('debug_trace')) {
                        debug_trace("Bounce ignored  : No service capability for {$bouncehost} ");
                    }
                    $response->errors[] = 'Create user : ignoring bounce to ' . $bouncehost . ' because host communication failed.';
                    $response->error = 'Create user : (last error) ignoring bounce to ' . $bouncehost . ' because host communication failed.';
                }
            } else {
                $response->errors[] = 'Create user : ignoring bounce to ' . $bouncehost . ' because host unregistered.';
                $response->error = 'Create user : (last error) ignoring bounce to ' . $bouncehost . ' because host unregistered.';
            }
        }
    }
    if ($json_response) {
        return json_encode($response);
    } else {
        return $response;
    }
}