MDL-75552 badges: move apiBase consumption to backpack

The apiBase in .well-known/badgeconnect.json was ignored and it was
causing some failures when connecting or sending badges to an
external backpack.
For OBv2.1, it has been changed to always use the apiBase defined
in the badgeconnect.json backpack provider.
This commit is contained in:
Andrew Nicols 2023-04-26 14:27:21 +08:00 committed by Sara Arjona
parent 176a323b4e
commit 50d1e69df6
3 changed files with 73 additions and 19 deletions

View File

@ -151,25 +151,25 @@ Feature: Basic OAuth2 functionality
| Service base URL | https://dc.imsglobal.org/ |
When I press "Save changes"
Then I should see "Changes saved"
And I should see "Open Badges"
And "Allow services" "icon" should exist in the "Open Badges" "table_row"
And "Do not allow login" "icon" should exist in the "Open Badges" "table_row"
And "Service discovery successful" "icon" should exist in the "Open Badges" "table_row"
And the "src" attribute of "table.admintable th img" "css_element" should contain "IMS-Global-Logo.png"
And I click on "Configure endpoints" "link" in the "Open Badges" "table_row"
And I should see "https://dc.imsglobal.org/.well-known/badgeconnect.json" in the "discovery_endpoint" "table_row"
And I should see "authorization_endpoint"
And I navigate to "Server > OAuth 2 services" in site administration
And I click on "Configure user field mappings" "link" in the "Open Badges" "table_row"
And I should not see "given_name"
And I should not see "middle_name"
And I navigate to "Server > OAuth 2 services" in site administration
And I click on "Edit" "link" in the "Open Badges" "table_row"
And I should see "IMS Global Reference Implementation"
And I click on "Edit" "link" in the "IMS Global Reference Implementation" "table_row"
And I set the following fields to these values:
| Name | IMS Global |
And I press "Save changes"
And I should see "Changes saved"
And I should see "IMS Global"
And "Allow services" "icon" should exist in the "IMS Global" "table_row"
And "Do not allow login" "icon" should exist in the "IMS Global" "table_row"
And "Service discovery successful" "icon" should exist in the "IMS Global" "table_row"
And the "src" attribute of "table.admintable th img" "css_element" should contain "IMS-Global-Logo.png"
And I click on "Configure endpoints" "link" in the "IMS Global" "table_row"
And I should see "https://dc.imsglobal.org/.well-known/badgeconnect.json" in the "discovery_endpoint" "table_row"
And I should see "authorization_endpoint"
And I navigate to "Server > OAuth 2 services" in site administration
And I click on "Configure user field mappings" "link" in the "IMS Global" "table_row"
And I should not see "given_name"
And I should not see "middle_name"
And I navigate to "Server > OAuth 2 services" in site administration
And I click on "Delete" "link" in the "IMS Global" "table_row"
And I should see "Are you sure you want to delete the identity issuer \"IMS Global\"?"
And I press "Continue"

View File

@ -36,6 +36,9 @@ use core_badges\backpack_api2p1_mapping;
use core_badges\oauth2\client;
use curl;
use stdClass;
use core\oauth2\issuer;
use core\oauth2\endpoint;
use core\oauth2\discovery\imsbadgeconnect;
/**
* To process badges with backpack and control api request and this class using for Open Badge API v2.1 methods.
@ -61,8 +64,11 @@ class backpack_api2p1 {
/** @var null version api of the backpack. */
protected $backpackapiversion;
/** @var null api URL of the backpack. */
protected $backpackapiurl = '';
/** @var issuer The OAuth2 Issuer for this backpack */
protected issuer $issuer;
/** @var endpoint The apiBase endpoint */
protected endpoint $apibase;
/**
* backpack_api2p1 constructor.
@ -75,7 +81,6 @@ class backpack_api2p1 {
if (!empty($externalbackpack)) {
$this->externalbackpack = $externalbackpack;
$this->backpackapiversion = $externalbackpack->apiversion;
$this->backpackapiurl = $externalbackpack->backpackapiurl;
$this->get_clientid = $this->get_clientid($externalbackpack->oauth2_issuerid);
if (!($this->tokendata = $this->get_stored_token($externalbackpack->id))
@ -87,6 +92,44 @@ class backpack_api2p1 {
$this->define_mappings();
}
/**
* Initialises or returns the OAuth2 issuer associated to this backpack.
*
* @return issuer
*/
protected function get_issuer(): issuer {
if (!isset($this->issuer)) {
$this->issuer = new \core\oauth2\issuer($this->externalbackpack->oauth2_issuerid);
}
return $this->issuer;
}
/**
* Gets the apiBase url associated to this backpack.
*
* @return string
*/
protected function get_api_base_url(): string {
if (!isset($this->apibase)) {
$apibase = endpoint::get_record([
'issuerid' => $this->externalbackpack->oauth2_issuerid,
'name' => 'apiBase',
]);
if (empty($apibase)) {
imsbadgeconnect::create_endpoints($this->get_issuer());
$apibase = endpoint::get_record([
'issuerid' => $this->externalbackpack->oauth2_issuerid,
'name' => 'apiBase',
]);
}
$this->apibase = $apibase;
}
return $this->apibase->get('url');
}
/**
* Define the mappings supported by this usage and api version.
@ -157,7 +200,7 @@ class backpack_api2p1 {
foreach ($this->mappings as $mapping) {
if ($mapping->is_match($action)) {
return $mapping->request(
$this->backpackapiurl,
$this->get_api_base_url(),
$tokenkey,
$postdata
);
@ -194,6 +237,7 @@ class backpack_api2p1 {
private function get_clientid($issuerid) {
$issuer = \core\oauth2\api::get_issuer($issuerid);
if (!empty($issuer)) {
$this->issuer = $issuer;
$this->clientid = $issuer->get('clientid');
}
}
@ -212,7 +256,7 @@ class backpack_api2p1 {
return false;
}
$issuer = new \core\oauth2\issuer($this->externalbackpack->oauth2_issuerid);
$issuer = $this->get_issuer();
$client = new client($issuer, new moodle_url('/badges/mybadges.php'), '', $this->externalbackpack);
if (!$client->is_logged_in()) {
$redirecturl = new moodle_url('/badges/mybadges.php', ['error' => 'backpackexporterror']);

View File

@ -82,6 +82,16 @@ class imsbadgeconnect extends base_definition {
$issuer->set('image', $url);
$issuer->update();
}
} else if ($key == 'apiBase') {
(new endpoint(0, (object) [
'issuerid' => $issuer->get('id'),
'name' => $key,
'url' => $value,
]))->create();
} else if ($key == 'name') {
// Get and update issuer name.
$issuer->set('name', $value);
$issuer->update();
}
}
}