Vous avez reçu un message "Your GitLab account has been locked ..." ? Pas d'inquiétude : lisez cet article https://docs.gricad-pages.univ-grenoble-alpes.fr/help/unlock/

Commit cc2c8001 authored by Francois Gannaz's avatar Francois Gannaz
Browse files

add instance: user binding and mission list

parent 933b7f32
......@@ -30,12 +30,12 @@ class environment
public function createPayload() : array {
$payload = [
'iss' => $this->iss,
'sub' => $this->sub,
'orig' => $this->orig,
'iss' => (int) $this->iss,
'sub' => (int) $this->sub,
'orig' => (string) $this->orig,
];
if ($this->token_exp) {
$payload['token_exp'] = $this->token_exp;
$payload['token_exp'] = (int) $this->token_exp;
}
return $payload;
}
......
......@@ -126,7 +126,7 @@ EOJS;
if ($payload) {
$jwtPayload['data'] = $payload;
}
$jwtPayload['dest'] = '/' . ltrim($urlPath, '/');;
$jwtPayload['dest'] = '/' . trim($urlPath, '/');;
$jwtPayload['iat'] = time(); // UTC timestamp
return JWT::encode($jwtPayload, $this->secret, 'HS256');
}
......
......@@ -24,7 +24,7 @@ class institution extends moodlefetcher
*/
public function loginUser() : int {
try {
$response = $this->fetcher->fetch("POST", "/v1/auth/login");
$response = $this->fetch("POST", "/v1/auth/login");
} catch (\Exception $e) {
$error = $this->fetcher->getLastError();
return (isset($error->code) ? (int) $error->code : 0);
......@@ -43,7 +43,7 @@ class institution extends moodlefetcher
public function createUser($user) {
try {
$response = $this->fetcher->fetch("PUT", "/v1/user/create", ['data' => $user]);
$response = $this->fetch("PUT", "/v1/user/create", ['data' => $user]);
} catch (\Exception $e) {
$error = $this->fetcher->getLastError();
if ($error->code === self::ERROR_CREATION_FAILED) {
......@@ -59,4 +59,13 @@ class institution extends moodlefetcher
// TODO
return self::OK;
}
public function getBindingToken($returnUrl) : string {
return $this->fetcher->encodeJwtToken('/v1/user/link', ['url' => $returnUrl]);
}
public function getLoginUrl() : string {
global $CFG;
return rtrim($CFG->labnbook_api_url, '/') . '/v1/user/link';
}
}
......@@ -25,20 +25,20 @@ abstract class moodlefetcher
protected function getEnvironment() : environment {
global $CFG, $USER;
$env = new environment();
$env->orig = "inst";
$env->orig = "inst"; // default value
$env->iss = (int) $CFG->labnbook_institution_id;
$env->sub = (int) $USER->id;
return $env;
}
protected function fetch($verb, $path, $payload) {
protected function fetch($verb, $path, $payload = []) {
global $SESSION;
$response = $this->fetcher->fetch($verb, $path, $payload);
if (!empty($response->auth)) {
if (empty($SESSION->labnbook)) {
$SESSION->labnbook = [];
$SESSION->labnbook = new \Stdclass;
}
$SESSION->labnbook['auth'] = $response->auth;
$SESSION->labnbook->auth = $response->auth;
}
return isset($response->data) ? $response->data : $response;
}
......
......@@ -12,34 +12,39 @@ class user extends moodlefetcher
const ERROR_LOGIN_UNKNOWN = 403;
const ERROR_CREATION_FAILED = 500;
/**
* Check that the current user has a Labnbook authentication, valid for the next 30 s.
*/
public static function isAuthenticated() {
global $SESSION;
return !empty($SESSION->labnbook['auth']['token_exp']);
return !empty($SESSION->labnbook->auth->token_exp)
&& $SESSION->labnbook->auth->token_exp > time() + 30;
}
protected function getEnvironment() : environment {
global $SESSION;
if (empty($SESSION->labnbook['auth']['token_exp'])) {
if (empty($SESSION->labnbook->auth->token_exp)) {
throw new \Exception("User token for the Labnbook API does not exist.");
}
$env = parent::getEnvironment();
$env->token_exp = $SESSION->labnbook['auth']['token_exp'];
$env->orig = "user";
$env->token_exp = $SESSION->labnbook->auth->token_exp;
return $env;
}
protected function getSigningKey() : string {
global $SESSION;
if (empty($SESSION->labnbook['auth']['token'])) {
if (empty($SESSION->labnbook->auth->token)) {
throw new \Exception("User token for the Labnbook API does not exist.");
}
return $SESSION->labnbook['auth']['token'];
return $SESSION->labnbook->auth->token;
}
/**
* @return array mission[]
*/
public function getMissions() {
return $this->fetch('GET', '/mission')->data;
return $this->fetch('GET', '/v1/mission')->data;
}
/**
......@@ -50,7 +55,14 @@ class user extends moodlefetcher
* @return string JavaScript Promise
*/
public function getJsMissions() {
return $this->fetcher->getJsFetch($verb, $path, $payload)
. '.then(x => x.data)';
return $this->fetcher->getJsFetch('GET', '/v1/mission')
. '.then(function(r) {
if (r.ok) {
return r.json();
} else {
console.error(r);
throw new Error(r);
}
}).then(x => x.data)';
}
}
......@@ -42,11 +42,11 @@ class mod_labnbook_mod_form extends moodleform_mod {
['' => "-"],
[
'onchange' => 'javascript: '
. 'document.querySelector("#id_name").value = labnbookMissions[this.value].name;'
. 'document.querySelector("#id_name").value = getMission(this.value).name;'
// update the Atto text, but Atto is undocumented stuff (wiki pages are all dead)
. 'document.querySelector("#id_introeditor").innerHTML = labnbookMissions[this.value].description;'
. 'document.querySelector("#id_introeditoreditable").innerHTML = labnbookMissions[this.value].description;'
// TODO update the TinyMCE text. Is there a way to detect the editor plugin? A common API?
. 'document.querySelector("#id_introeditoreditable").innerHTML = getMission(this.value).description;'
. 'document.querySelector("#id_introeditor").innerHTML = getMission(this.value).description;'
// TODO update the TinyMCE text. Is there a way to detect the editor plugin? A common API for pluggable editors?
]
);
$mform->addRule('labnbook_missionid', null, 'required', null, 'client');
......@@ -55,6 +55,10 @@ class mod_labnbook_mod_form extends moodleform_mod {
$mform->addElement('html', <<<"EOJS"
<script>
var labnbookMissions = new Map();
function getMission(id) {
return labnbookMissions.get(parseInt(id));
}
var refreshLock = 0;
function refreshMissions() {
if (refreshLock) {
......@@ -64,9 +68,9 @@ function refreshMissions() {
var container = document.querySelector('#id_labnbook_missionid');
var loading = document.createElement('span');
loading.setAttribute('class', 'fa-spinner fa-spin');
loading.setAttribute('class', 'fa fa-spinner fa-pulse fa-fw');
loading.setAttribute('id', 'labnbook-missions-loading');
container.parent.appendChild(loading);
document.querySelector('#refresh-missions').parentNode.appendChild(loading);
$fetchMissions.then(missions => {
refreshLock = 0;
......@@ -82,16 +86,22 @@ function refreshMissions() {
}
}).catch(() => {
refreshLock = 0;
document.querySelector('#labnbook-missions-loading').remove();
// TODO: error, what shall we do?
alert("Erreur...");
});
}
document.addEventListener("DOMContentLoaded", function(event) {
refreshMissions();
})
</script>
EOJS
);
$mform->addElement(
'static', '', '',
'<button type="button" onclick="refreshMissions()">'
'<button type="button" onclick="refreshMissions()" id="refresh-missions">'
. get_string('refresh', 'mod_labnbook')
. '</a>'
);
......@@ -138,6 +148,7 @@ EOJS
}
function requireLabnbookAuthentication() {
global $COURSE;
if (fetch\user::isAuthenticated()) {
return;
}
......@@ -145,8 +156,5 @@ function requireLabnbookAuthentication() {
if ($institutionFetcher->loginUser() === fetch\institution::OK) {
return;
}
// ask for account creation or authentication
require __DIR__ . '/user-binding.php';
// do not display the mod form
exit();
redirect("/mod/labnbook/user-binding.php?courseid={$COURSE->id}&return=" . base64_encode($_SERVER['REQUEST_URI']));
}
......@@ -9,20 +9,74 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
use \mod_labnbook\fetch;
require_once dirname(dirname(__DIR__)) . '/config.php';
$returnUrl = base64_decode(required_param('return', PARAM_ALPHANUM));
$courseid = required_param('courseid', PARAM_INT);
$create = optional_param('create', false, PARAM_BOOL);
$course = $DB->get_record('course', ['id' => $courseid], '*', MUST_EXIST);
require_login($course);
$fetchInstitution = new fetch\institution();
$context = context_course::instance($courseid);
if ($create && !fetch\user::isAuthenticated()) {
global $USER;
$isTeacher = has_capability('mod/labnbook:addinstance', $context);
if (createUser($USER, $isTeacher)) {
redirect($returnUrl);
}
}
/* @var $PAGE moodle_page */
global $PAGE;
$PAGE->set_url('/mod/labnbook/user-binding.php');
$PAGE->set_title("LabNbook");
$PAGE->set_heading("LabNbook");
$PAGE->set_context($context);
/* @var $OUTPUT moodle_core_output */
global $OUTPUT;
echo $OUTPUT->header();
?>
fromage ou dessert ?
<p>
Vous n'avez pas de compte dans LabNbook, ou ce compte n'est pas encore connu de Moodle.
</p>
<div class="container-fluid">
<div class="row">
<div class="col" style="text-align: center">
<form action="<?= $fetchInstitution->getLoginUrl() ?>" method="GET">
<input type="hidden" name="token" value="<?= $fetchInstitution->getBindingToken($CFG->wwwroot . $returnUrl) ?>" />
<button type="submit" class="btn btn-primary">Se connecter à LabNbook</button>
</form>
<div>Si vous possédez déjà un compte dans LabNbook, ce lien permettra de vous authentifier dans LabNbook et de mettre à jour votre compte Moodle.</div>
</div>
<div class="col" style="text-align: center">
<form action="" method="POST">
<input type="hidden" name="return" value="<?= base64_encode($returnUrl) ?>" />
<input type="hidden" name="courseid" value="<?= $COURSE->id ?>" />
<input type="hidden" name="create" value="1" />
<button type="submit" class="btn btn-primary">Créer un nouveau compte dans LabNbook</button>
</form>
<div>Un compte sera créé dans LabNbook et associé à ce compte Moodle.</div>
</div>
</div>
</div>
<?php
echo $OUTPUT->footer();
function createUser($user, $isTeacher) {
$success = $fetchInstitution->createUser([
'first_name' => $user->firstname,
'user_name' => $user->lastname,
'login' => $user->username,
'email' => $user->email,
'role' => ($isTeacher ? 'teacher' : 'learner'),
]);
return ($success === fetch\institution::OK);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment