From bcba1347f84d3dfd206ded7ca1d3f91362995c93 Mon Sep 17 00:00:00 2001 From: Peter Dias Date: Thu, 24 Sep 2020 14:13:23 +0800 Subject: [PATCH] MDL-65959 badges: Allow cross domain/protocol functionality - obv2 --- badges/backpack-add.php | 153 ++++++++++++++++++++++------------------ badges/mybackpack.php | 48 +++++++------ 2 files changed, 109 insertions(+), 92 deletions(-) diff --git a/badges/backpack-add.php b/badges/backpack-add.php index 0e1adc58d29..2e2478be825 100644 --- a/badges/backpack-add.php +++ b/badges/backpack-add.php @@ -25,12 +25,13 @@ require_once(__DIR__ . '/../config.php'); require_once($CFG->libdir . '/badgeslib.php'); -if (badges_open_badges_backpack_api() != OPEN_BADGES_V2) { +require_login(); + +$userbackpack = badges_get_user_backpack(); +if (badges_open_badges_backpack_api($userbackpack->id) != OPEN_BADGES_V2) { throw new coding_exception('No backpacks support Open Badges V2.'); } -require_login(); - $id = required_param('hash', PARAM_ALPHANUM); $PAGE->set_url('/badges/backpack-add.php', array('hash' => $id)); @@ -44,82 +45,97 @@ if (!empty($issuedbadge->recipient->id)) { // * Create badge // * Create assertion (Award the badge!) + // With the introduction OBv2.1 and MDL-65959 to allow cross region Badgr imports the above (old) procedure will + // only be completely performed if both the site and user backpacks conform to the same apiversion. + // Else we will attempt at pushing the assertion to the user's backpack. In this case, the id set against the assertion + // has to be a publicly accessible resource. + // Get the backpack. $badgeid = $issuedbadge->badgeid; $badge = new badge($badgeid); $backpack = $DB->get_record('badge_backpack', array('userid' => $USER->id)); - $sitebackpack = badges_get_site_primary_backpack(); $userbackpack = badges_get_site_backpack($backpack->externalbackpackid, $USER->id); - $assertion = new core_badges_assertion($id, $sitebackpack->apiversion); - $api = new \core_badges\backpack_api($sitebackpack); - $api->authenticate(); - - // Create issuer. - $issuer = $assertion->get_issuer(); - if (!($issuerentityid = badges_external_get_mapping($sitebackpack->id, OPEN_BADGES_V2_TYPE_ISSUER, $issuer['email']))) { - $response = $api->put_issuer($issuer); - if (!$response) { - throw new moodle_exception('invalidrequest', 'error'); - } - $issuerentityid = $response->id; - badges_external_create_mapping($sitebackpack->id, OPEN_BADGES_V2_TYPE_ISSUER, $issuer['email'], - $issuerentityid, $response->openBadgeId); - } - // Create badge. - $badge = $assertion->get_badge_class(false); - $badgeid = $assertion->get_badge_id(); - if (!($badgeentityid = badges_external_get_mapping($sitebackpack->id, OPEN_BADGES_V2_TYPE_BADGE, $badgeid))) { - $response = $api->put_badgeclass($issuerentityid, $badge); - if (!$response) { - throw new moodle_exception('invalidrequest', 'error'); - } - $badgeentityid = $response->id; - badges_external_create_mapping($sitebackpack->id, OPEN_BADGES_V2_TYPE_BADGE, $badgeid, - $badgeentityid, $response->hostedUrl); - } - - // Create assertion (Award the badge!). + $assertion = new core_badges_assertion($id, OPEN_BADGES_V2); $assertiondata = $assertion->get_badge_assertion(false, false); - $assertionid = $assertion->get_assertion_hash(); - $assertionentityid = badges_external_get_mapping( - $sitebackpack->id, - OPEN_BADGES_V2_TYPE_ASSERTION, - $assertionid - ); + $assertionentityid = $assertiondata['id']; + $badgeadded = false; + if (badges_open_badges_backpack_api() == OPEN_BADGES_V2) { + $sitebackpack = badges_get_site_primary_backpack(); + $api = new \core_badges\backpack_api($sitebackpack); + $response = $api->authenticate(); - if (!$assertionentityid && strpos($sitebackpack->backpackapiurl, 'badgr')) { - $assertionentityid = badges_generate_badgr_open_url( - $sitebackpack, - OPEN_BADGES_V2_TYPE_ASSERTION, - $assertionentityid - ); - } + // A numeric response indicates a valid successful authentication. Else an error object will be returned. + if (is_numeric($response)) { + // Create issuer. + $issuer = $assertion->get_issuer(); + if (!($issuerentityid = badges_external_get_mapping($sitebackpack->id, OPEN_BADGES_V2_TYPE_ISSUER, $issuer['email']))) { + $response = $api->put_issuer($issuer); + if (!$response) { + throw new moodle_exception('invalidrequest', 'error'); + } + $issuerentityid = $response->id; + badges_external_create_mapping($sitebackpack->id, OPEN_BADGES_V2_TYPE_ISSUER, $issuer['email'], + $issuerentityid); + } + // Create badge. + $badge = $assertion->get_badge_class(false); + $badgeid = $assertion->get_badge_id(); + if (!($badgeentityid = badges_external_get_mapping($sitebackpack->id, OPEN_BADGES_V2_TYPE_BADGE, $badgeid))) { + $response = $api->put_badgeclass($issuerentityid, $badge); + if (!$response) { + throw new moodle_exception('invalidrequest', 'error'); + } + $badgeentityid = $response->id; + badges_external_create_mapping($sitebackpack->id, OPEN_BADGES_V2_TYPE_BADGE, $badgeid, + $badgeentityid); + } - // Create an assertion for the recipient in the issuer's account. - if (!$assertionentityid) { - $response = $api->put_badgeclass_assertion($badgeentityid, $assertiondata); - if (!$response) { - throw new moodle_exception('invalidrequest', 'error'); - } - $assertionentityid = badges_generate_badgr_open_url($sitebackpack, OPEN_BADGES_V2_TYPE_ASSERTION, $response->id); - badges_external_create_mapping($sitebackpack->id, OPEN_BADGES_V2_TYPE_ASSERTION, $assertionid, - $response->id); - } else { - // An assertion already exists. Make sure it's up to date. - $internalid = badges_external_get_mapping( - $sitebackpack->id, - OPEN_BADGES_V2_TYPE_ASSERTION, - $assertionid, - 'externalid' - ); - $response = $api->update_assertion($internalid, $assertiondata); - if (!$response) { - throw new moodle_exception('invalidrequest', 'error'); + // Create assertion (Award the badge!). + $assertionentityid = badges_external_get_mapping( + $sitebackpack->id, + OPEN_BADGES_V2_TYPE_ASSERTION, + $assertionid + ); + + if (!$assertionentityid && strpos($sitebackpack->backpackapiurl, 'badgr')) { + $assertionentityid = badges_generate_badgr_open_url( + $sitebackpack, + OPEN_BADGES_V2_TYPE_ASSERTION, + $assertionentityid + ); + } + + // Create an assertion for the recipient in the issuer's account. + if (!$assertionentityid) { + $response = $api->put_badgeclass_assertion($badgeentityid, $assertiondata); + if (!$response) { + throw new moodle_exception('invalidrequest', 'error'); + } + $assertionentityid = badges_generate_badgr_open_url($sitebackpack, OPEN_BADGES_V2_TYPE_ASSERTION, $response->id); + $badgeadded = true; + badges_external_create_mapping($sitebackpack->id, OPEN_BADGES_V2_TYPE_ASSERTION, $assertionid, + $response->id); + } else { + // An assertion already exists. Make sure it's up to date. + $internalid = badges_external_get_mapping( + $sitebackpack->id, + OPEN_BADGES_V2_TYPE_ASSERTION, + $assertionid, + 'externalid' + ); + $response = $api->update_assertion($internalid, $assertiondata); + if (!$response) { + throw new moodle_exception('invalidrequest', 'error'); + } + } } } // Now award/upload the badge to the user's account. + // - If a user and site backpack have the same provider we can skip this as Badgr automatically maps recipients + // based on email address. + // - This is only needed when the backpacks are from different regions. if ($assertionentityid && !badges_external_get_mapping($userbackpack->id, OPEN_BADGES_V2_TYPE_ASSERTION, $assertionid)) { $userapi = new \core_badges\backpack_api($userbackpack, $backpack); $userapi->authenticate(); @@ -128,13 +144,12 @@ if (!empty($issuedbadge->recipient->id)) { throw new moodle_exception('invalidrequest', 'error'); } $assertionentityid = $response->id; + $badgeadded = true; badges_external_create_mapping($userbackpack->id, OPEN_BADGES_V2_TYPE_ASSERTION, $assertionid, $assertionentityid); - $response = ['success' => 'addedtobackpack']; - } else { - $response = ['warning' => 'existsinbackpack']; } + $response = $badgeadded ? ['success' => 'addedtobackpack'] : ['warning' => 'existsinbackpack']; redirect(new moodle_url('/badges/mybadges.php', $response)); } else { redirect(new moodle_url('/badges/mybadges.php')); diff --git a/badges/mybackpack.php b/badges/mybackpack.php index 05454c203df..89c3ffdba4d 100644 --- a/badges/mybackpack.php +++ b/badges/mybackpack.php @@ -55,7 +55,7 @@ $badgescache = cache::make('core', 'externalbadges'); if ($disconnect && $backpack) { require_sesskey(); - $sitebackpack = badges_get_site_backpack($backpack->externalbackpackid); + $sitebackpack = badges_get_user_backpack(); if ($sitebackpack->apiversion == OPEN_BADGES_V2P1) { $bp = new \core_badges\backpack_api2p1($sitebackpack); $bp->disconnect_backpack($backpack); @@ -71,7 +71,7 @@ if ($disconnect && $backpack) { $warning = ''; if ($backpack) { - $sitebackpack = badges_get_site_backpack($backpack->externalbackpackid); + $sitebackpack = badges_get_user_backpack(); // If backpack is connected, need to select collections. $bp = new \core_badges\backpack_api($sitebackpack, $backpack); @@ -123,28 +123,30 @@ if ($backpack) { $data = $form->get_submitted_data(); if ($form->is_cancelled()) { redirect(new moodle_url('/badges/mybadges.php')); - } else if (badges_open_badges_backpack_api($data->externalbackpackid) == OPEN_BADGES_V2P1) { - // If backpack is version 2.1 to redirect on the backpack site to login. - // User input username/email/password on the backpack site - // After confirm the scopes. - redirect(new moodle_url('/badges/backpack-connect.php', ['backpackid' => $data->externalbackpackid])); - } else if ($data = $form->get_data()) { - // The form may have been submitted under one of the following circumstances: - // 1. After clicking 'Connect to backpack'. We'll have $data->email. - // 2. After clicking 'Resend verification email'. We'll have $data->email. - // 3. After clicking 'Connect using a different email' to cancel the verification process. We'll have $data->revertbutton. + } else if ($form->is_submitted()) { + if (badges_open_badges_backpack_api($data->externalbackpackid) == OPEN_BADGES_V2P1) { + // If backpack is version 2.1 to redirect on the backpack site to login. + // User input username/email/password on the backpack site + // After confirm the scopes. + redirect(new moodle_url('/badges/backpack-connect.php', ['backpackid' => $data->externalbackpackid])); + } else if ($data = $form->get_data()) { + // The form may have been submitted under one of the following circumstances: + // 1. After clicking 'Connect to backpack'. We'll have $data->email. + // 2. After clicking 'Resend verification email'. We'll have $data->email. + // 3. After clicking 'Connect using a different email' to cancel the verification process. We'll have $data->revertbutton. - if (isset($data->revertbutton)) { - badges_disconnect_user_backpack($USER->id); - redirect(new moodle_url('/badges/mybackpack.php')); - } else if (isset($data->backpackemail)) { - if (badges_send_verification_email($data->backpackemail, $data->externalbackpackid, $data->password)) { - $a = get_user_preferences('badges_email_verify_backpackid'); - redirect(new moodle_url('/badges/mybackpack.php'), - get_string('backpackemailverifypending', 'badges', $data->backpackemail), - null, \core\output\notification::NOTIFY_INFO); - } else { - print_error ('backpackcannotsendverification', 'badges'); + if (isset($data->revertbutton)) { + badges_disconnect_user_backpack($USER->id); + redirect(new moodle_url('/badges/mybackpack.php')); + } else if (isset($data->backpackemail)) { + if (badges_send_verification_email($data->backpackemail, $data->externalbackpackid, $data->password)) { + $a = get_user_preferences('badges_email_verify_backpackid'); + redirect(new moodle_url('/badges/mybackpack.php'), + get_string('backpackemailverifypending', 'badges', $data->backpackemail), + null, \core\output\notification::NOTIFY_INFO); + } else { + print_error ('backpackcannotsendverification', 'badges'); + } } } }