MDL-65959 badges: Allow cross domain/protocol functionality - obv2
authorPeter Dias <peter@moodle.com>
Thu, 24 Sep 2020 06:13:23 +0000 (14:13 +0800)
committerPeter Dias <peter@moodle.com>
Mon, 26 Oct 2020 10:36:26 +0000 (18:36 +0800)
badges/backpack-add.php
badges/mybackpack.php

index 0e1adc5..2e2478b 100644 (file)
 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'));
index 05454c2..89c3ffd 100644 (file)
@@ -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.
-
-        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');
+    } 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');
+                }
             }
         }
     }