MDL-65959 badge: Enable OB2.1 *connection* with cross domain ability
authorPeter Dias <peter@moodle.com>
Thu, 24 Sep 2020 03:03:55 +0000 (11:03 +0800)
committerPeter Dias <peter@moodle.com>
Mon, 26 Oct 2020 16:27:20 +0000 (00:27 +0800)
badges/backpack-connect.php
badges/backpack-export.php
badges/mybackpack.php
badges/renderer.php
lib/badgeslib.php

index cece808..ff77f49 100644 (file)
 require_once(__DIR__ . '/../config.php');
 require_once($CFG->libdir . '/badgeslib.php');
 
+$backpackid = required_param('backpackid', PARAM_INT);
 $scope = optional_param('scope', '', PARAM_RAW);
 $action = optional_param('action', null, PARAM_RAW);
 
-if (badges_open_badges_backpack_api() != OPEN_BADGES_V2P1) {
+if (badges_open_badges_backpack_api($backpackid) != OPEN_BADGES_V2P1) {
     throw new coding_exception('backpacks only support Open Badges V2.1');
 }
 
 require_login();
 
-$externalbackpack = badges_get_site_backpack($CFG->badges_site_backpack);
+$externalbackpack = badges_get_site_backpack($backpackid);
 $persistedissuer = \core\oauth2\issuer::get_record(['id' => $externalbackpack->oauth2_issuerid]);
 if ($persistedissuer) {
     $issuer = new \core\oauth2\issuer($externalbackpack->oauth2_issuerid);
     $returnurl = new moodle_url('/badges/backpack-connect.php',
-        ['action' => 'authorization', 'sesskey' => sesskey()]);
+        ['action' => 'authorization', 'sesskey' => sesskey(), 'backpackid' => $backpackid]);
 
     $client = new core_badges\oauth2\client($issuer, $returnurl, $scope, $externalbackpack);
     if ($client) {
index e1015b7..60a0ace 100644 (file)
@@ -25,9 +25,6 @@
 require_once(__DIR__ . '/../config.php');
 require_once($CFG->libdir . '/badgeslib.php');
 
-if (badges_open_badges_backpack_api() != OPEN_BADGES_V2P1) {
-    throw new coding_exception('backpacks only support Open Badges V2.1');
-}
 $hash = optional_param('hash', null, PARAM_RAW);
 
 $PAGE->set_pagelayout('admin');
@@ -37,7 +34,12 @@ require_login();
 if (empty($CFG->badges_allowexternalbackpack) || empty($CFG->enablebadges)) {
     redirect($CFG->wwwroot);
 }
-$backpack = badges_get_site_backpack($CFG->badges_site_backpack);
+
+$backpack = badges_get_user_backpack();
+if (badges_open_badges_backpack_api($backpack->id) != OPEN_BADGES_V2P1) {
+    throw new coding_exception('backpacks only support Open Badges V2.1');
+}
+
 $userbadges = badges_get_user_badges($USER->id);
 $context = context_user::instance($USER->id);
 
@@ -50,7 +52,6 @@ $PAGE->set_pagelayout('standard');
 
 $redirecturl = new moodle_url('/badges/mybadges.php');
 if ($hash) {
-    $backpack = badges_get_site_backpack($CFG->badges_site_backpack);
     $api = new core_badges\backpack_api2p1($backpack);
     $notify = $api->put_assertions($hash);
     if (!empty($notify['status']) && $notify['status'] == \core\output\notification::NOTIFY_SUCCESS) {
index e759727..05454c2 100644 (file)
@@ -103,16 +103,6 @@ if ($backpack) {
         $bp->set_backpack_collections($backpack->id, $groups);
         redirect(new moodle_url('/badges/mybadges.php'));
     }
-} else if (badges_open_badges_backpack_api() == 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.
-    $form = new \core_badges\form\backpack(new moodle_url('/badges/mybackpack.php'));
-    if ($form->is_cancelled()) {
-        redirect(new moodle_url('/badges/mybadges.php'));
-    } else if ($data = $form->get_submitted_data()) {
-        redirect(new moodle_url('/badges/backpack-connect.php'));
-    }
 } else {
     // If backpack is not connected, need to connect first.
     // To create a new connection to the backpack, first we need to verify the user's email address:
@@ -130,8 +120,14 @@ if ($backpack) {
     $params['backpackid'] = get_user_preferences('badges_email_verify_backpackid');
 
     $form = new \core_badges\form\backpack(new moodle_url('/badges/mybackpack.php'), $params);
+    $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.
index 2d0d3f9..b561bfe 100644 (file)
@@ -80,14 +80,14 @@ class core_badges_renderer extends plugin_renderer_base {
                     $params
                 );
                 $notexpiredbadge = (empty($badge->dateexpire) || $badge->dateexpire > time());
-                $backpackexists = badges_user_has_backpack($USER->id);
-                if (!empty($CFG->badges_allowexternalbackpack) && $notexpiredbadge && $backpackexists) {
+                $userbackpack = badges_get_user_backpack();
+                if (!empty($CFG->badges_allowexternalbackpack) && $notexpiredbadge && $userbackpack) {
                     $assertion = new moodle_url('/badges/assertion.php', array('b' => $badge->uniquehash));
                     $action = null;
-                    if (badges_open_badges_backpack_api() == OPEN_BADGES_V1) {
+                    if (badges_open_badges_backpack_api($userbackpack->id) == OPEN_BADGES_V1) {
                         $action = new component_action('click', 'addtobackpack', array('assertion' => $assertion->out(false)));
                         $addurl = new moodle_url('#');
-                    } else if (badges_open_badges_backpack_api() == OPEN_BADGES_V2P1) {
+                    } else if (badges_open_badges_backpack_api($userbackpack->id) == OPEN_BADGES_V2P1) {
                         $addurl = new moodle_url('/badges/backpack-export.php', array('hash' => $badge->uniquehash));
                     } else {
                         $addurl = new moodle_url('/badges/backpack-add.php', array('hash' => $badge->uniquehash));
@@ -342,9 +342,10 @@ class core_badges_renderer extends plugin_renderer_base {
                         new moodle_url('/badges/badge.php', array('hash' => $ibadge->hash, 'bake' => true)),
                         get_string('download'),
                         'POST');
-            if (!empty($CFG->badges_allowexternalbackpack) && ($expiration > $now) && badges_user_has_backpack($USER->id)) {
+            if (!empty($CFG->badges_allowexternalbackpack) && ($expiration > $now)
+                && $userbackpack = badges_get_user_backpack($USER->id)) {
 
-                if (badges_open_badges_backpack_api() == OPEN_BADGES_V1) {
+                if (badges_open_badges_backpack_api($userbackpack->id) == OPEN_BADGES_V1) {
                     $assertion = new moodle_url('/badges/assertion.php', array('b' => $ibadge->hash));
                     $action = new component_action('click', 'addtobackpack', array('assertion' => $assertion->out(false)));
                     $attributes = array(
@@ -356,7 +357,7 @@ class core_badges_renderer extends plugin_renderer_base {
                     $this->output->add_action_handler($action, 'addbutton');
                     $output .= $tobackpack;
                 } else {
-                    if (badges_open_badges_backpack_api() == OPEN_BADGES_V2P1) {
+                    if (badges_open_badges_backpack_api($userbackpack->id) == OPEN_BADGES_V2P1) {
                         $assertion = new moodle_url('/badges/backpack-export.php', array('hash' => $ibadge->hash));
                     } else {
                         $assertion = new moodle_url('/badges/backpack-add.php', array('hash' => $ibadge->hash));
index 35263ac..81bb7ef 100644 (file)
@@ -909,12 +909,16 @@ function badges_save_backpack_credentials(stdClass $data) {
 
 /**
  * Is any backpack enabled that supports open badges V1?
+ * @param int|null $backpackid Check the version of the given id OR if null the sitewide backpack
  * @return boolean
  */
-function badges_open_badges_backpack_api() {
-    global $CFG;
+function badges_open_badges_backpack_api(?int $backpackid = null) {
+    if (!$backpackid) {
+        global $CFG;
+        $backpackid = $CFG->badges_site_backpack;
+    }
 
-    $backpack = badges_get_site_backpack($CFG->badges_site_backpack);
+    $backpack = badges_get_site_backpack($backpackid);
     if (empty($backpack->apiversion)) {
         return OPEN_BADGES_V2;
     }
@@ -939,6 +943,28 @@ function badges_get_site_backpack($id, int $userid = 0) {
     return $DB->get_record_sql($sql, ['id' => $id, 'userid' => $userid]);
 }
 
+/**
+ * Get the user backpack for the currently logged in user OR the provided user
+ *
+ * @param int|null $userid The user whose backpack you're requesting for. If null, get the logged in user's backpack
+ * @return mixed The user's backpack or none.
+ * @throws dml_exception
+ */
+function badges_get_user_backpack(?int $userid = 0) {
+    global $DB;
+
+    if (!$userid) {
+        global $USER;
+        $userid = $USER->id;
+    }
+
+    $sql = "SELECT beb.*, bb.id AS badgebackpack, bb.password, bb.email AS backpackemail
+              FROM {badge_external_backpack} beb
+              JOIN {badge_backpack} bb ON bb.externalbackpackid = beb.id AND bb.userid=:userid";
+
+    return $DB->get_record_sql($sql, ['userid' => $userid]);
+}
+
 /**
  * Get the primary backpack for the site
  *