Skip to content
Snippets Groups Projects
Commit 2c4c41a7 authored by Rasmus Fuhse's avatar Rasmus Fuhse
Browse files

Resolve "edu-sharing/auth-plugin umstellen auf composer"

Closes #4120

Merge request studip/studip!2964
parent 59c6b7f6
No related branches found
No related tags found
No related merge requests found
Showing
with 59 additions and 683 deletions
......@@ -2,7 +2,7 @@
namespace Studip\Cli\Commands\Twillo;
use Config;
use EduSharingHelper;
use \EduSharingApiClient\EduSharingHelper;
use Studip\Cli\Commands\AbstractCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
......@@ -32,13 +32,13 @@ final class PrivateKeys extends AbstractCommand
$key = EduSharingHelper::generateKeyPair();
$success = file_put_contents(
$properties,
EduSharingHelper::generateEduAppXMLData($appId, $key['publickey'])
EduSharingHelper::generateEduAppXMLData($appId, $key['publicKey'])
);
if ($success !== false) {
file_put_contents(
$privateKey,
$key['privatekey']
$key['privateKey']
);
Config::get()->store('OERCAMPUS_TWILLO_APPID', $appId);
......
......@@ -61,7 +61,8 @@
"phpoffice/phpspreadsheet": "^1.19",
"psy/psysh": "^0.12.2",
"okvpn/clock-lts": "^1.0",
"vlucas/phpdotenv": "^5.6"
"vlucas/phpdotenv": "^5.6",
"edu-sharing/auth-plugin": "8.0.x-dev"
},
"replace": {
"symfony/polyfill-php73": "*",
......
......@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "69b82b7aa6db216cb8afdb9da520b4e7",
"content-hash": "535218b1c9cca9acd1f2c554c59e5113",
"packages": [
{
"name": "algo26-matthias/idna-convert",
......@@ -295,6 +295,53 @@
},
"time": "2023-06-19T06:10:36+00:00"
},
{
"name": "edu-sharing/auth-plugin",
"version": "8.0.x-dev",
"source": {
"type": "git",
"url": "https://github.com/edu-sharing/php-auth-plugin.git",
"reference": "4dc40c400afea63bd75ddd5ad4cea8033e477e72"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/edu-sharing/php-auth-plugin/zipball/4dc40c400afea63bd75ddd5ad4cea8033e477e72",
"reference": "4dc40c400afea63bd75ddd5ad4cea8033e477e72",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-json": "*",
"ext-openssl": "*",
"php": ">= 8.0"
},
"require-dev": {
"phpunit/phpunit": "^9"
},
"default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
"EduSharingApiClient\\": "src/EduSharing"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-3.0-only"
],
"authors": [
{
"name": "Torsten Simon",
"email": "simon@edu-sharing.net"
}
],
"description": "Plugin to provide authentification via Auth By App with a edu-sharing repository",
"support": {
"issues": "https://github.com/edu-sharing/php-auth-plugin/issues",
"source": "https://github.com/edu-sharing/php-auth-plugin/tree/8.0"
},
"time": "2024-04-02T10:02:58+00:00"
},
{
"name": "ezyang/htmlpurifier",
"version": "v4.17.0",
......@@ -7829,7 +7876,8 @@
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"phpxmlrpc/extras": 10
"phpxmlrpc/extras": 10,
"edu-sharing/auth-plugin": 20
},
"prefer-stable": false,
"prefer-lowest": false,
......
......@@ -88,21 +88,3 @@ StudipAutoloader::addClassLookup(
['xmlrpc_server'],
'composer/phpxmlrpc/phpxmlrpc/lib/xmlrpcs.inc'
);
//Edu-Sharing helper classes for twillo connector
StudipAutoloader::addClassLookup(
'EduSharingHelper',
'vendor/edu-sharing-plugin/edu-sharing-helper.php'
);
StudipAutoloader::addClassLookup(
'EduSharingHelperBase',
'vendor/edu-sharing-plugin/edu-sharing-helper-base.php'
);
StudipAutoloader::addClassLookup(
'EduSharingAuthHelper',
'vendor/edu-sharing-plugin/edu-sharing-auth-helper.php'
);
StudipAutoloader::addClassLookup(
'EduSharingNodeHelper',
'vendor/edu-sharing-plugin/edu-sharing-node-helper.php'
);
......@@ -50,14 +50,14 @@ class TwilloConnector
public static function uploadMaterial(OERMaterial $material, $user_id = null)
{
$user_id || $user_id = User::findCurrent()->id;
$base = new EduSharingHelperBase(
$base = new \EduSharingApiClient\EduSharingHelperBase(
self::$twillo_base_url,
file_get_contents($GLOBALS['STUDIP_BASE_PATH']."/config/twillo-private.key"),
Config::get()->OERCAMPUS_TWILLO_APPID,
self::getHttpProxy()
// 'data-quest-Test'
);
$authHelper = new EduSharingAuthHelper($base);
$authHelper = new \EduSharingApiClient\EduSharingAuthHelper($base);
if (!static::$ticket) {
static::$ticket = $authHelper->getTicketForUser(TwilloConnector::getTwilloUserID($user_id));
}
......@@ -261,13 +261,13 @@ class TwilloConnector
{
$user_id || $user_id = User::findCurrent()->id;
$base = new EduSharingHelperBase(
$base = new \EduSharingApiClient\EduSharingHelperBase(
self::$twillo_base_url,
file_get_contents($GLOBALS['STUDIP_BASE_PATH']."/config/twillo-private.key"),
Config::get()->OERCAMPUS_TWILLO_APPID,
self::getHttpProxy()// 'data-quest-Test'
);
$authHelper = new EduSharingAuthHelper($base);
$authHelper = new \EduSharingApiClient\EduSharingAuthHelper($base);
if (!static::$ticket) {
static::$ticket = $authHelper->getTicketForUser(TwilloConnector::getTwilloUserID($user_id));
}
......
<?php
require_once "edu-sharing-helper-abstract.php";
class EduSharingAuthHelper extends EduSharingHelperAbstract {
/**
* Gets detailed information about a ticket
* Will throw an exception if the given ticket is not valid anymore
* @param string $ticket
* The ticket, obtained by @getTicketForUser
* @return array
* Detailed information about the current session
* @throws Exception
* Thrown if the ticket is not valid anymore
*/
public function getTicketAuthenticationInfo(string $ticket) {
$curl = curl_init($this->base->baseUrl . '/rest/authentication/v1/validateSession');
curl_setopt_array($curl, [
CURLOPT_HTTPHEADER => [
$this->getRESTAuthenticationHeader($ticket),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_TIMEOUT => 5
]);
if ($this->base->http_proxy) {
curl_setopt($curl, CURLOPT_PROXY, $this->base->http_proxy);
}
$data = json_decode(curl_exec($curl), true);
curl_close($curl);
if ( is_null( $data ) ) {
throw new Exception( 'No answer from repository. Possibly a timeout while trying to connect' );
}
if($data['statusCode'] !== 'OK') {
throw new Exception('The given ticket is not valid anymore');
}
return $data;
}
/**
* Fetches the edu-sharing ticket for a given username
* @param string $username
* The username you want to generate a ticket for
* @return string
* The ticket, which you can use as an authentication header, see @getRESTAuthenticationHeader
* @throws Exception
*/
public function getTicketForUser(string $username, $bodyparams = null) {
if ($bodyparams === null) {
$bodyparams = [
"primaryAffiliation" => "employee",
"skills" => [
"string"
],
"types" => [
"string"
],
"extendedAttributes" => [
'affiliation' => ["employee"]
],
"vcard" => "string",
"firstName" => User::findCurrent()->vorname,
"lastName" => User::findCurrent()->nachname,
"email" => User::findCurrent()->email,
"avatar" => "string",
"about" => "string"
];
}
$curl = curl_init($this->base->baseUrl . '/rest/authentication/v1/appauth/' . rawurlencode($username));
curl_setopt_array($curl, [
CURLOPT_POST => 1,
CURLOPT_FAILONERROR => false,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HTTPHEADER => $this->getSignatureHeaders($username),
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_TIMEOUT => 5
]);
curl_setopt(
$curl,
CURLOPT_POSTFIELDS,
is_array($bodyparams) ? json_encode($bodyparams) : (string) $bodyparams
);
if ($this->base->http_proxy) {
curl_setopt($curl, CURLOPT_PROXY, $this->base->http_proxy);
}
$output = curl_exec($curl);
$data = json_decode($output, true);
$err = curl_errno( $curl );
$info = curl_getinfo($curl);
curl_close($curl);
if ($err === 0 && $info["http_code"] === 200 && $data['userId'] === $username) {
return $data['ticket'];
} else {
if ( is_null( $data ) ) {
$data = ['error' => $output];
}
throw new Exception(
'edu-sharing ticket could not be retrieved: HTTP-Code ' .
$info["http_code"] . ': ' . $data['error']
);
}
}
}
<?php
abstract class EduSharingHelperAbstract {
protected $base;
public function __construct(
EduSharingHelperBase $base
) {
$this->base = $base;
}
/**
* Generates the header to use for a given ticket to authenticate with any edu-sharing api endpoint
* @param string $ticket
* The ticket, obtained by @getTicketForUser
* @return string
*/
public function getRESTAuthenticationHeader(string $ticket) {
return 'Authorization: EDU-TICKET ' . $ticket;
}
protected function getSignatureHeaders(
string $signString,
$accept = 'application/json',
$contentType = 'application/json'
) {
$ts = time() * 1000;
$toSign = $this->base->appId . $signString . $ts;
$signature = $this->sign($toSign);
return [
'Accept: ' . $accept,
'Content-Type: ' . $contentType,
'X-Edu-App-Id: ' . $this->base->appId,
'X-Edu-App-Signed: ' . $toSign,
'X-Edu-App-Sig: ' . $signature,
'X-Edu-App-Ts: ' . $ts,
];
}
protected function sign(string $toSign) {
return $this->base->sign($toSign);
}
}
\ No newline at end of file
<?php
class EduSharingHelperBase {
public $baseUrl;
public $privateKey;
public $appId;
public $language = 'de';
public $http_proxy = '';
/**
* @param string $baseUrl
* The base url to your repository in the format "http://<host>/edu-sharing"
* @param string $privateKey
* Your app's private key. This must match the public key registered in the repo
* @param string $appId
* Your app id name (as registered in the edu-sharing repository)
*/
public function __construct(
string $baseUrl,
string $privateKey,
string $appId,
string $http_proxy = ''
) {
if(!preg_match('/^([a-z]|[A-Z]|[0-9]|[-_])+$/', $appId)) {
throw new Exception('The given app id contains invalid characters or symbols');
}
$this->baseUrl=$baseUrl;
$this->privateKey=$privateKey;
$this->appId=$appId;
$this->http_proxy = $http_proxy;
}
public function setLanguage(string $language) {
$this->language = $language;
}
function sign(string $toSign) {
$pkeyid = openssl_get_privatekey($this->privateKey);
openssl_sign($toSign, $signature, $pkeyid);
$signature = base64_encode($signature);
openssl_free_key($pkeyid);
return $signature;
}
}
<?php
class EduSharingHelper {
/**
* generate a new key pair (private + public) to be registered in the edu-sharing repository
* Store the data somewhere in your application, e.g. database
* use the public key returned to register the application in edu-sharing
* NOTE: This function will fail on windows-based systems!
* @throws Exception
*/
public static function generateKeyPair(
)
{
$res = openssl_pkey_new();
if(!$res) {
throw new Exception("No result from openssl_pkey_new. Please check your php installation");
}
openssl_pkey_export($res, $privatekey);
$publickey = openssl_pkey_get_details($res);
$publickey = $publickey["key"];
return [
"privatekey" => $privatekey,
"publickey" => $publickey
];
}
/**
* Generates an edu-sharing compatible xml file for registering the application
* This is a very basic function and is only intended for demonstration or manual use. Data is not escaped!
*/
public static function generateEduAppXMLData(string $appId, string $publickey, string $type = 'LMS', string $publicIP = '*') {
return '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<entry key="appid">' . $appId . '</entry>
<entry key="public_key">' . $publickey . '</entry>
<entry key="type">' . $type . '</entry>
<entry key="domain"></entry>
<!-- in case of wildcard host: Replace this, if possible, with the public ip from your service -->
<entry key ="host">' . $publicIP . '</entry>
<!-- must be true -->
<entry key="trustedclient">true</entry>
</properties>
';
}
}
\ No newline at end of file
<?php
require_once "edu-sharing-helper-abstract.php";
class DisplayMode {
const Inline = 'inline';
const Embed = 'embed';
const Dynamic = 'dynamic';
}
class Usage {
public $nodeId;
public $nodeVersion;
public $containerId;
public $resourceId;
public $usageId;
public function __construct($nodeId, $nodeVersion, $containerId, $resourceId, $usageId)
{
$this->nodeId = $nodeId;
$this->nodeVersion = $nodeVersion;
$this->containerId = $containerId;
$this->resourceId = $resourceId;
$this->usageId = $usageId;
}
}
class EduSharingNodeHelper extends EduSharingHelperAbstract {
/**
* creates a usage for a given node
* The given usage can later be used to fetch this node REGARDLESS of the actual user
* The usage gives permanent access to this node and acts similar to a license
* In order to be able to create an usage for a node, the current user (provided via the ticket)
* MUST have CC_PUBLISH permissions on the given node id
* @param string $ticket
* A ticket with the user session who is creating this usage
* @param string $containerId
* A unique page / course id this usage refers to inside your system (e.g. a database id of the page you include the usage)
* @param string $resourceId
* The individual resource id on the current page or course this object refers to
* (you may enumerate or use unique UUID's)
* @param string $nodeId
* The edu-sharing node id the usage shall be created for
* @param string|null $nodeVersion
* Optional: The fixed version this usage should refer to
* If you leave it empty, the usage will always refer to the latest version of the node
* @return Usage
* An usage element you can use with @getNodeByUsage
* Keep all data of this object stored inside your system!
*/
public function createUsage(
string $ticket,
string $containerId,
string $resourceId,
string $nodeId,
string $nodeVersion = null
) {
$curl = curl_init($this->base->baseUrl . '/rest/usage/v1/usages/repository/-home-');
$headers = $this->getSignatureHeaders($ticket);
$headers[] = $this->getRESTAuthenticationHeader($ticket);
curl_setopt_array($curl, [
CURLOPT_FAILONERROR => false,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => json_encode([
'appId' => $this->base->appId,
'courseId' => $containerId,
'resourceId' => $resourceId,
'nodeId' => $nodeId,
'nodeVersion' => $nodeVersion,
]),
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HTTPHEADER => $headers
]);
if ($this->base->http_proxy) {
curl_setopt($curl, CURLOPT_PROXY, $this->base->http_proxy);
}
$data = json_decode(curl_exec($curl), true);
$err = curl_errno( $curl );
$info = curl_getinfo($curl);
curl_close($curl);
if ($err === 0 && $info["http_code"] === 200) {
return new Usage(
$data['parentNodeId'],
$nodeVersion,
$containerId,
$resourceId,
$data['nodeId']
);
} else {
throw new Exception('creating usage failed ' .
$info["http_code"] . ': ' . $data['error'] . ' ' . $data['message']);
}
}
/**
* Loads the edu-sharing node refered by a given usage
* @param Usage $usage
* The usage, as previously returned by @createUsage
* @param string $displayMode
* The displayMode
* This will ONLY change the content representation inside the "detailsSnippet" return value
* @param array $renderingParams
* @return mixed
* Returns an object containing a "detailsSnippet" repesentation
* as well as the full node as provided by the REST API
* Please refer to the edu-sharing REST documentation for more details
* @throws Exception
*/
public function getNodeByUsage(
Usage $usage,
$displayMode = DisplayMode::Inline,
array $renderingParams = null
)
{
$url = $this->base->baseUrl . '/rest/rendering/v1/details/-home-/' . rawurlencode($usage->nodeId);
$url .= '?displayMode=' . rawurlencode($displayMode);
if($usage->nodeVersion) {
$url .= '&version=' . rawurlencode($usage->nodeVersion);
}
$curl = curl_init($url);
$headers = $this->getSignatureHeaders($usage->usageId);
$headers[] = 'X-Edu-Usage-Node-Id: ' . $usage->nodeId;
$headers[] = 'X-Edu-Usage-Course-Id: ' . $usage->containerId;
$headers[] = 'X-Edu-Usage-Resource-Id: ' . $usage->resourceId;
curl_setopt_array($curl, [
CURLOPT_FAILONERROR => false,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => json_encode($renderingParams),
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HTTPHEADER => $headers
]);
if ($this->base->http_proxy) {
curl_setopt($curl, CURLOPT_PROXY, $this->base->http_proxy);
}
$data = json_decode(curl_exec($curl), true);
$err = curl_errno( $curl );
$info = curl_getinfo($curl);
if ($err === 0 && $info["http_code"] === 200) {
return $data;
} else {
throw new Exception('fetching node by usage failed ' .
$info["http_code"] . ': ' . $data['error'] . ' ' . $data['message']);
}
}
/**
* Deletes the given usage
* We trust that you've validated if the current user in your context is allowed to do so
* There is no restriction in deleting usages even from foreign users, as long as they were generated by your app
* Thus, this endpoint does not require any user ticket
* @param string $nodeId
* The edu-sharing node id this usage belongs to
* @param string $usageId
* The usage id
*/
public function deleteUsage(
string $nodeId,
string $usageId
) {
$curl = curl_init($this->base->baseUrl . '/rest/usage/v1/usages/node/' . rawurlencode($nodeId) . '/' . rawurlencode($usageId));
$headers = $this->getSignatureHeaders($nodeId.$usageId);
curl_setopt_array($curl, [
CURLOPT_FAILONERROR => false,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HTTPHEADER => $headers
]);
if ($this->base->http_proxy) {
curl_setopt($curl, CURLOPT_PROXY, $this->base->http_proxy);
}
$data = json_decode(curl_exec($curl), true);
$err = curl_errno( $curl );
$info = curl_getinfo($curl);
curl_close($curl);
if ($err === 0 && $info["http_code"] === 200) {
} else {
throw new Exception('deleting usage failed ' .
$info["http_code"] . ': ' . $data['error'] . ' ' . $data['message']);
}
}
}
<?php
define('APP_ID', 'data-quest Test');
define('BASE_URL', 'http://localhost:8080/edu-sharing');
define('USERNAME', 'root@studip');
header('Accept: application/json');
header('Content-Type: application/json');
require_once "../edu-sharing-helper.php";
require_once "../edu-sharing-helper-base.php";
require_once "../edu-sharing-auth-helper.php";
require_once "../edu-sharing-node-helper.php";
$privatekey = @file_get_contents('private.key');
if(!$privatekey) {
die('no private key');
} else {
$key["privatekey"] = $privatekey;
}
// init the base class instance we use for all helpers
$base = new EduSharingHelperBase(BASE_URL, $key["privatekey"], APP_ID);
$postData = json_decode(file_get_contents('php://input'));
$action = $postData->action;
$result = null;
if ($action === 'BASE_URL') {
$result = BASE_URL;
} else if ($action === 'GET_NODE') {
$nodeHelper = new EduSharingNodeHelper($base);
$result = $nodeHelper->getNodeByUsage(
new Usage(
$postData->nodeId,
$postData->nodeVersion,
$postData->containerId,
$postData->resourceId,
$postData->usageId
)
);
} else if ($action === 'CREATE_USAGE') {
$nodeHelper = new EduSharingNodeHelper($base);
$result = $nodeHelper->createUsage(
$postData->ticket,
$postData->containerId,
$postData->resourceId,
$postData->nodeId
);
} else if ($action === 'DELETE_USAGE') {
$nodeHelper = new EduSharingNodeHelper($base);
$nodeHelper->deleteUsage(
$postData->nodeId,
$postData->usageId
);
} else if ($action === 'TICKET') {
$authHelper = new EduSharingAuthHelper($base);
$ticket = $authHelper->getTicketForUser(USERNAME);
$result = $ticket;
}
echo json_encode($result);
<?php
/**
* This is a sample file on how to use the edu-sharing remote library
* Run this script for the first time to create a private/public keypair
* On first run, a properties.xml file will be created
* Upload this file to your target edu-sharing (Admin-Tools -> Remote Systems -> Choose XML-File)
*/
define('APP_ID', 'sample-app');
define('USERNAME', 'tester');
require_once "../edu-sharing-helper.php";
require_once "../edu-sharing-helper-base.php";
require_once "../edu-sharing-auth-helper.php";
require_once "../edu-sharing-node-helper.php";
$privatekey = @file_get_contents('private.key');
if(!$privatekey) {
$key = EduSharingHelper::generateKeyPair();
// store the $key data inside your application, e.g. your database or plugin config
file_put_contents(APP_ID . '.properties.xml', EduSharingHelper::generateEduAppXMLData(APP_ID, $key['publickey']));
file_put_contents('private.key', $key['privatekey']);
die('Wrote ' . APP_ID . '.properties.xml file. Upload it to edu-sharing, then run this script again');
} else {
$key["privatekey"] = $privatekey;
}
if(count($argv) < 2) {
die('This script should be called as follow: "example.php http://localhost:8080/edu-sharing [<node-id>]"');
}
// init the base class instance we use for all helpers
$base = new EduSharingHelperBase($argv[1], $key["privatekey"], APP_ID);
$base->setLanguage('de');
// authenticating (getting a ticket) and validating the given ticket
$authHelper = new EduSharingAuthHelper($base);
$ticket = $authHelper->getTicketForUser(USERNAME);
echo "Ticket validation result:\n";
print_r($authHelper->getTicketAuthenticationInfo($ticket));
if(count($argv) !== 3) {
die("No node id given. Add a 3rd parameter to test create + fetching of nodes by usage");
}
$nodeHelper = new EduSharingNodeHelper($base);
$usage = $nodeHelper->createUsage($ticket, '1', '1', $argv[2]);
echo "Usage create result:\n";
print_r($usage);
$node = $nodeHelper->getNodeByUsage($usage);
echo "Get node by usage:\n";
print_r($node["node"]["name"]);
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Edu Sharing Usage Example</title>
<style>
body > div {
padding: 20px 10px;
}
pre {
border: 1px solid #eee;
padding: 10px;
margin: 10px;
}
</style>
<script>
let ticket;
let baseUrl = null;
let esWindow = null;
function openEduSharing() {
esWindow = window.open(
baseUrl + '/components/search?ticket=' + encodeURIComponent(ticket) +
'&reurl=IFRAME'
);
}
window.addEventListener('message', receiveMessage, false);
async function receiveMessage(event){
if(event.data.event === 'APPLY_NODE'){ // Event Name hier festlegen
esWindow.close();
console.log(event.data.data);
usage = await createUsage(event.data.data.nodeId);
// in a real application, the usage is stored in your backend system
localStorage.setItem('usage', JSON.stringify(usage));
await renderUsage();
}
}
async function renderUsage() {
if(localStorage.getItem('usage')) {
const usage = JSON.parse(localStorage.getItem('usage'));
document.querySelector('#usage').style.display = null;
document.querySelector('#delete-usage').style.display = null;
document.querySelector('#usage').innerHTML = JSON.stringify(usage, null, 4);
usage.action = 'GET_NODE';
const render = await fetchAPI(usage)
document.querySelector('#render').innerHTML = render.detailsSnippet;
}
}
async function createUsage(nodeId) {
return await fetchAPI({
action: 'CREATE_USAGE',
ticket,
nodeId,
containerId: 'my_sample_page_1',
resourceId: Math.random()
});
}
async function deleteUsage(nodeId) {
const usage = JSON.parse(localStorage.getItem('usage'));
await fetchAPI({
action: 'DELETE_USAGE',
nodeId: usage.nodeId,
usageId: usage.usageId
});
localStorage.removeItem('usage');
document.querySelector('#render').style.display = 'none';
document.querySelector('#usage').style.display = 'none';
document.querySelector('#delete-usage').style.display = 'none';
}
async function fetchAPI(data) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open("POST", "example-api.php", true);
xhr.onload = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(JSON.parse(xhr.response));
} else {
alert(xhr.statusText);
reject(xhr.statusText);
}
}
};
xhr.onerror = function (e) {
alert(xhr.statusText);
};
xhr.send(JSON.stringify(data));
});
}
async function getTicket() {
ticket = await fetchAPI({action: 'TICKET'});
document.querySelector('#ticket').innerText = ticket;
document.querySelector('#edu-select').style.display = null;
}
window.addEventListener('load', async () => {
baseUrl = await fetchAPI({action: 'BASE_URL'});
await renderUsage();
await getTicket();
});
</script>
</head>
<body>
<div>
<button onclick="getTicket()">Re-Fetch ticket</button>
<span id="ticket">No ticket</span>
</div>
<div id="edu-select" style="display:none;">
<button onclick="openEduSharing()">Open edu-sharing & select node</button>
</div>
<pre id="usage" style="display: none"></pre>
<div id="delete-usage" style="display: none">
<button onclick="deleteUsage()">Delete current Usage</button>
</div>
<div id="render"></div>
</body>
</html>
\ No newline at end of file
This library is a changed version of https://github.com/edu-sharing/php-auth-plugin
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment