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 df89cc0e authored by Francois Gannaz's avatar Francois Gannaz
Browse files

php code style

parent e2273280
......@@ -2,7 +2,6 @@
/**
* @license http://www.gnu.org/licenses/gpl-3.0.html GNU GPL v3
* @package mod_labnbook
* @copyright 2019 Université Grenoble Alpes
*/
......
......@@ -2,7 +2,6 @@
/**
* @license http://www.gnu.org/licenses/gpl-3.0.html GNU GPL v3
* @package mod_labnbook
* @copyright 2019 Université Grenoble Alpes
*/
......@@ -33,7 +32,8 @@ class environment
*/
public $token_exp;
public function createPayload() : array {
public function createPayload(): array
{
$payload = [
'iss' => (int) $this->iss,
'sub' => (int) $this->sub,
......
......@@ -2,15 +2,14 @@
/**
* @license http://www.gnu.org/licenses/gpl-3.0.html GNU GPL v3
* @package mod_labnbook
* @copyright 2019 Université Grenoble Alpes
*/
namespace mod_labnbook\fetch;
require_once dirname(dirname(__DIR__)) . '/vendor/firebase/php-jwt/src/JWT.php';
require_once \dirname(__DIR__, 2) . '/vendor/firebase/php-jwt/src/JWT.php';
use \Firebase\JWT\JWT;
use Firebase\JWT\JWT;
/**
* Fetch info from the LabNbook API.
......@@ -41,11 +40,12 @@ class fetcher
*/
private $lastError;
public function __construct(string $baseUrl, string $secret, environment $environment) {
public function __construct(string $baseUrl, string $secret, environment $environment)
{
if (!$secret) {
throw new \Exception("The JWT secret key is empty.");
}
$this->baseUrl = rtrim($baseUrl, '/');
$this->baseUrl = \rtrim($baseUrl, '/');
$this->secret = $secret;
$this->environment = $environment;
}
......@@ -53,7 +53,8 @@ class fetcher
/**
* @return \Stdclass {code, message}
*/
public function getLastError() : ?\Stdclass {
public function getLastError(): ?\Stdclass
{
return (object) $this->lastError;
}
......@@ -65,9 +66,10 @@ class fetcher
* @param array $payload Default is empty. Else any assoc array.
* @return mixed
*/
public function fetch(string $verb, string $urlPath, array $payload = []) {
$curl = curl_init();
curl_setopt_array($curl, [
public function fetch(string $verb, string $urlPath, array $payload = [])
{
$curl = \curl_init();
\curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $verb,
CURLOPT_URL => $this->createUrl($urlPath),
......@@ -78,32 +80,32 @@ class fetcher
],
CURLOPT_CONNECTTIMEOUT => self::TIMEOUT,
]);
$response = curl_exec($curl);
if (curl_errno($curl) !== 0) {
$response = \curl_exec($curl);
if (\curl_errno($curl) !== 0) {
$this->lastError = (object) [
'code' => 0,
'message' => curl_error($curl),
'message' => \curl_error($curl),
];
}
$error = $this->validateResponse($curl, $response);
if ($error) {
curl_close($curl);
error_log("Query $verb $urlPath to labnbook API failed. $error");
\curl_close($curl);
\error_log("Query $verb $urlPath to labnbook API failed. $error");
throw new \Exception("HTTP request failed.");
}
// send decoded response?
$contentType = curl_getinfo($curl, CURLINFO_CONTENT_TYPE);
curl_close($curl);
$contentType = \curl_getinfo($curl, CURLINFO_CONTENT_TYPE);
\curl_close($curl);
if ($contentType === 'application/json') {
return json_decode($response);
} else {
return $response;
return \json_decode($response);
}
return $response;
}
public function createUrl(string $urlPath) : string {
return $this->baseUrl . '/' . ltrim($urlPath, '/');
public function createUrl(string $urlPath): string
{
return $this->baseUrl . '/' . \ltrim($urlPath, '/');
}
/**
......@@ -114,7 +116,8 @@ class fetcher
* @param array $payload Default is empty. Else any assoc array.
* @return string JS source code
*/
public function getJsFetch(string $verb, string $urlPath, array $payload = []) {
public function getJsFetch(string $verb, string $urlPath, array $payload = [])
{
$url = \json_encode($this->createUrl($urlPath));
$verb = \json_encode($verb);
$token = $this->encodeJwtToken($urlPath, $payload);
......@@ -134,13 +137,14 @@ fetch($url, {
EOJS;
}
public function encodeJwtToken(string $urlPath, array $payload) : string {
public function encodeJwtToken(string $urlPath, array $payload): string
{
$jwtPayload = $this->environment->createPayload();
if ($payload) {
$jwtPayload['data'] = $payload;
}
$jwtPayload['dest'] = '/' . trim($urlPath, '/');;
$jwtPayload['iat'] = time(); // UTC timestamp
$jwtPayload['dest'] = '/' . \trim($urlPath, '/');
$jwtPayload['iat'] = \time(); // UTC timestamp
return JWT::encode($jwtPayload, $this->secret, 'HS256');
}
......@@ -149,15 +153,16 @@ EOJS;
* @param resource $response
* @return string if OK "", else error message
*/
protected function validateResponse($curl, $response) {
protected function validateResponse($curl, $response)
{
if ($response === false) {
$this->lastError = (object) ['message' => "Network error? " . curl_error($curl)];
return "Network error? " . curl_error($curl);
$this->lastError = (object) ['message' => "Network error? " . \curl_error($curl)];
return "Network error? " . \curl_error($curl);
}
$responseCode = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
$responseCode = \curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
if ($responseCode != 200) {
$this->lastError = json_decode($response); // Do not verify signature?
if (json_last_error() !== JSON_ERROR_NONE) {
$this->lastError = \json_decode($response); // Do not verify signature?
if (\json_last_error() !== JSON_ERROR_NONE) {
$this->lastError = (object) ['message' => $response];
}
$this->lastError->code = $responseCode;
......
......@@ -2,7 +2,6 @@
/**
* @license http://www.gnu.org/licenses/gpl-3.0.html GNU GPL v3
* @package mod_labnbook
* @copyright 2019 Université Grenoble Alpes
*/
......@@ -19,15 +18,11 @@ class institution extends moodlefetcher
const ERROR_LOGIN_UNKNOWN = 403;
const ERROR_CREATION_FAILED = 500;
protected function getSigningKey() : string {
global $CFG;
return $CFG->labnbook_api_key;
}
/**
* @return int Cf constants: OK, ERROR_*
*/
public function loginUser() : int {
public function loginUser(): int
{
try {
$this->fetch("POST", "/v1/auth/login");
} catch (\Exception $e) {
......@@ -37,9 +32,10 @@ class institution extends moodlefetcher
return self::OK;
}
public function createUser($user) {
public function createUser($user)
{
try {
$this->fetch("PUT", "/v1/user/create", (array)$user);
$this->fetch("PUT", "/v1/user/create", (array) $user);
} catch (\Exception $e) {
$error = $this->fetcher->getLastError();
return (isset($error->code) ? (int) $error->code : 0);
......@@ -51,12 +47,13 @@ class institution extends moodlefetcher
/**
* Return a JWT token for the redirection page of LnB, so that the user ends on the user-binding page.
*
* @param string $returnUrl Full URL, including protocol.
* @param string $returnUrl full URL, including protocol
* @param string $role "learner" | "teacher"
* @return string JWT
* @throws \moodle_exception
*/
public function getBindingTokenForRedirect(string $returnUrl, string $role) : string {
public function getBindingTokenForRedirect(string $returnUrl, string $role): string
{
if ($role !== 'learner' && $role !== 'teacher') {
throw new \moodle_exception("Invalid role value in fetch.institution.getBindingToken()");
}
......@@ -69,4 +66,10 @@ class institution extends moodlefetcher
];
return $this->fetcher->encodeJwtToken('/v1/redirect', $payload);
}
protected function getSigningKey(): string
{
global $CFG;
return $CFG->labnbook_api_key;
}
}
......@@ -2,7 +2,6 @@
/**
* @license http://www.gnu.org/licenses/gpl-3.0.html GNU GPL v3
* @package mod_labnbook
* @copyright 2019 Université Grenoble Alpes
*/
......@@ -20,7 +19,8 @@ abstract class moodlefetcher
*/
protected $fetcher;
public function __construct() {
public function __construct()
{
global $CFG;
$this->fetcher = new fetcher(
$CFG->labnbook_api_url,
......@@ -29,7 +29,14 @@ abstract class moodlefetcher
);
}
protected function getEnvironment() : environment {
public function getRedirectUrl(): string
{
global $CFG;
return \rtrim($CFG->labnbook_api_url, '/') . '/v1/redirect';
}
protected function getEnvironment(): environment
{
global $CFG, $USER;
$env = new environment();
$env->orig = "inst"; // default value
......@@ -38,22 +45,18 @@ abstract class moodlefetcher
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 = new \Stdclass;
$SESSION->labnbook = new \Stdclass();
}
$SESSION->labnbook->auth = $response->auth;
}
return isset($response->data) ? $response->data : $response;
}
abstract protected function getSigningKey() : string;
public function getRedirectUrl() : string {
global $CFG;
return rtrim($CFG->labnbook_api_url, '/') . '/v1/redirect';
}
abstract protected function getSigningKey(): string;
}
......@@ -2,7 +2,6 @@
/**
* @license http://www.gnu.org/licenses/gpl-3.0.html GNU GPL v3
* @package mod_labnbook
* @copyright 2019 Université Grenoble Alpes
*/
......@@ -20,35 +19,18 @@ class user extends moodlefetcher
/**
* Check that the current user has a Labnbook authentication, valid for the next 30 s.
*/
public static function isAuthenticated() {
public static function isAuthenticated()
{
global $SESSION;
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)) {
throw new \Exception("User token for the Labnbook API does not exist.");
}
$env = parent::getEnvironment();
$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)) {
throw new \Exception("User token for the Labnbook API does not exist.");
}
return $SESSION->labnbook->auth->token;
&& $SESSION->labnbook->auth->token_exp > \time() + 30;
}
/**
* @return array mission[]
*/
public function getMissions() {
public function getMissions()
{
return $this->fetch('GET', '/v1/mission')->data;
}
......@@ -62,7 +44,8 @@ class user extends moodlefetcher
* @param array $teamconfig
* @return object teamconfig
*/
public function useMission(int $missionId, int $courseId, string $coursename, ?int $groupId = null, array $teamconfig) {
public function useMission(int $missionId, int $courseId, string $coursename, ?int $groupId = null, array $teamconfig)
{
return $this
->fetch(
'POST',
......@@ -87,7 +70,8 @@ class user extends moodlefetcher
* @param array $teamconfig
* @return object teamconfig
*/
public function updateMissionUse(int $missionId, int $courseId, string $coursename, ?int $groupId = null, array $teamconfig) {
public function updateMissionUse(int $missionId, int $courseId, string $coursename, ?int $groupId = null, array $teamconfig)
{
return $this
->fetch(
'POST',
......@@ -109,7 +93,8 @@ class user extends moodlefetcher
*
* @return string JavaScript Promise
*/
public function getJsMissions() {
public function getJsMissions()
{
return $this->fetcher->getJsFetch('GET', '/v1/mission')
. '.then(function(r) {
if (r.ok) {
......@@ -128,7 +113,8 @@ class user extends moodlefetcher
* @return string JWT
* @throws \moodle_exception
*/
public function getReportTokenForRedirect(int $teamconfigId) : string {
public function getReportTokenForRedirect(int $teamconfigId): string
{
$payload = [
'path' => "/report/enter/$teamconfigId",
];
......@@ -142,7 +128,8 @@ class user extends moodlefetcher
* @return string JWT
* @throws \moodle_exception
*/
public function getReportsTokenForRedirect(int $teamconfigId) : string {
public function getReportsTokenForRedirect(int $teamconfigId): string
{
$payload = [
'path' => "/authoring_tools/lb_reports.php#teamconfig=$teamconfigId",
];
......@@ -156,7 +143,8 @@ class user extends moodlefetcher
* @return string JWT
* @throws \moodle_exception
*/
public function getTeamingTokenForRedirect(int $teamconfigId) : string {
public function getTeamingTokenForRedirect(int $teamconfigId): string
{
$payload = [
'path' => "/authoring_tools/lb_students.php#teamconfig=$teamconfigId",
];
......@@ -170,10 +158,32 @@ class user extends moodlefetcher
* @return string JWT
* @throws \moodle_exception
*/
public function getMissionTokenForRedirect() : string {
public function getMissionTokenForRedirect(): string
{
$payload = [
'path' => "/authoring_tools/lb_missions.php",
];
return $this->fetcher->encodeJwtToken('/v1/redirect', $payload);
}
protected function getEnvironment(): environment
{
global $SESSION;
if (empty($SESSION->labnbook->auth->token_exp)) {
throw new \Exception("User token for the Labnbook API does not exist.");
}
$env = parent::getEnvironment();
$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)) {
throw new \Exception("User token for the Labnbook API does not exist.");
}
return $SESSION->labnbook->auth->token;
}
}
<?php
/**
* @package mod_labnbook
* @copyright 2019 Université Grenoble Alpes
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
......@@ -18,28 +17,27 @@ require_once $CFG->libdir . '/form/select.php';
*/
class select_dynamic extends \MoodleQuickForm_select
{
/**
* Overrides the filtering method.
*
* @param array $submitValues submitted values
* @param bool $assoc if true the returned value is an assoc array
* @return string|array
*/
function exportValue(&$submitValues, $assoc = false)
/**
* Overrides the filtering method.
*
* @param array $submitValues submitted values
* @param bool $assoc if true the returned value is an assoc array
* @return string|array
*/
public function exportValue(&$submitValues, $assoc = false)
{
if (empty($this->_options)) {
return $this->_prepareValue(null, $assoc);
}
$value = $this->_findValue($submitValues);
if (is_null($value)) {
if (\is_null($value)) {
$value = $this->getValue();
}
if ($this->getMultiple()) {
return $this->_prepareValue((array) $value, $assoc);
} else {
return $this->_prepareValue(is_array($value) ? $value[0] : $value, $assoc);
}
return $this->_prepareValue(\is_array($value) ? $value[0] : $value, $assoc);
}
}
<?php
/**
* @package mod_labnbook
* @copyright 2019 Université Grenoble Alpes
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
......@@ -17,22 +16,22 @@ class helper
* Redirects on an account binding|creation if necessary.
*
* @global \Stdclass $COURSE
* @return null
* @throws \moodle_exception
*/
public static function requireLabnbookAuthentication() {
public static function requireLabnbookAuthentication()
{
global $COURSE;
if (fetch\user::isAuthenticated()) {
return;
}
$institutionFetcher = new fetch\institution;
$institutionFetcher = new fetch\institution();
switch ($institutionFetcher->loginUser()) {
case fetch\institution::OK:
return;
case fetch\institution::ERROR_LOGIN_UNKNOWN:
redirect(
"/mod/labnbook/user-binding.php?courseid={$COURSE->id}&return="
. base64_encode($_SERVER['REQUEST_URI'])
. \base64_encode($_SERVER['REQUEST_URI'])
);
break;
case fetch\institution::ERROR_TOKEN_NOTVALID:
......
......@@ -3,7 +3,6 @@
/**
* Defines {@link \mod_labnbook\privacy\provider} class.
*
* @package mod_labnbook
* @category privacy
* @copyright 2019 Université Grenoble Alpes
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
......@@ -11,19 +10,20 @@
namespace mod_labnbook\privacy;
defined('MOODLE_INTERNAL') || die();
\defined('MOODLE_INTERNAL') || die();
/**
* Privacy API implementation for the LabNbook plugin.
*/
class provider implements \core_privacy\local\metadata\null_provider {
class provider implements \core_privacy\local\metadata\null_provider
{
/**
* Returns stringid of a text explaining that this plugin stores no personal data.
*
* @return string
*/
public static function get_reason() : string {
public static function get_reason(): string
{
return 'privacy:metadata';
}
}
......@@ -3,13 +3,11 @@
/**
* Plugin capabilities are defined here.
*
* @package mod_labnbook
* @category access
* @copyright 2019 Université Grenoble Alpes
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
\defined('MOODLE_INTERNAL') || die();
$capabilities = [
'mod/labnbook:view' => [
......
......@@ -3,13 +3,11 @@
/**
* Plugin upgrade steps are defined here.
*
* @package mod_labnbook
* @category upgrade
* @copyright 2019 Université Grenoble Alpes
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
\defined('MOODLE_INTERNAL') || die();
/**
* Execute mod_labnbook upgrade from the given old version.
......@@ -17,7 +15,8 @@ defined('MOODLE_INTERNAL') || die();
* @param int $oldversion
* @return bool
*/
function xmldb_labnbook_upgrade($oldversion) {
function xmldb_labnbook_upgrade($oldversion)
{
/*
global $DB;
......
......@@ -3,13 +3,11 @@
/**
* Redirect the user to the appropriate submission related page.
*
* @package mod_labnbook
* @category grade
* @copyright 2019 Université Grenoble Alpes
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require(__DIR__.'/../../config.php');
require(__DIR__ . '/../../config.php');
// Course module ID.
$id = required_param('id', PARAM_INT);
......@@ -21,4 +19,4 @@ $itemnumber = optional_param('itemnumber', 0, PARAM_INT);
$userid = optional_param('userid', 0, PARAM_INT);
// In the simplest case just redirect to the view page.
redirect('view.php?id='.$id);
redirect('view.php?id=' . $id);
......@@ -3,13 +3,11 @@
/**
* Display information about all the mod_labnbook modules in the requested course.
*
* @package mod_labnbook
* @copyright 2019 Université Grenoble Alpes
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require(__DIR__.'/../../config.php');
require_once(__DIR__.'/lib.php');