Commit 596255f5 authored by Geoffroy ARNOUD's avatar Geoffroy ARNOUD
Browse files

Managed optgroups #K7

parent c0dc356d
......@@ -80,3 +80,14 @@ if ($useSAML2Metadata) {
// from metadata instead of being manualy managed
sortIdentityProviders($IDProviders);
}
/*------------------------------------------------*/
// Retrieve previously selected IDPs
/*------------------------------------------------*/
// Get previously accessed IdPs
if (isset($_COOKIE[$SAMLDomainCookieName])) {
$IDPArray = getIdPArrayFromValue($_COOKIE[$SAMLDomainCookieName]);
} else {
$IDPArray = array();
}
......@@ -15,6 +15,7 @@
if ($useSelect2) {
echo '<link rel="stylesheet" href="'. $_SERVER['SCRIPT_NAME'] .'/select2.css" type="text/css" >'.PHP_EOL;
echo '<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>'.PHP_EOL;
// echo '<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.js"></script>'.PHP_EOL;
echo '<script type="text/javascript" src="'.$javascriptURL .'/select2Functions.js"></script>'.PHP_EOL;
} elseif ($useImprovedDropDownList) {
echo '<link rel="stylesheet" href="'. $_SERVER['SCRIPT_NAME'] .'/ImprovedDropDown.css" type="text/css">'.PHP_EOL;
......@@ -56,6 +57,7 @@
// Perform input validation on WAYF form
function checkForm(){
//console.log("checkForm ", document.IdPList.user_idp, "/", document.IdPList.user_idp.selectedIndex);
if(
document.IdPList.user_idp &&
document.IdPList.user_idp.selectedIndex == 0
......@@ -67,6 +69,23 @@
}
}
// Perform input validation on WAYF form for select2
function select2CheckForm() {
// FIXME : to be reviewed for select2 !!!
console.log("checkForm ", $('.userIdPSelection option:selected').text());
if (
document.IdPList.user_idp && (
$('.userIdPSelection option:selected').text() == null ||
$('.userIdPSelection option:selected').text() == ''
)
) {
alert(unescape('<?php echo getLocalString('make_selection', 'js') ?>'));
return false;
} else {
return true;
}
}
// Init WAYF
function init(){
preventIframeEmbedding();
......@@ -76,8 +95,8 @@
if (<?php echo ($useSelect2) ? 'true' : 'false' ?>){
$('.userIdPSelection').select2({
ajax: {
url: <?php echo "'".$_SERVER['REQUEST_URI']."api/idps'" ?>,
delay: 1000,
url: <?php echo "'".$apiURL."/idps'" ?>,
delay: 250,
dataType: 'json',
data: function (params) {
var query = {
......
......@@ -2,7 +2,13 @@
<!-- Identity Provider Selection: Start -->
<h1><?php echo getLocalString('permanent_select_header'); ?></h1>
<form id="IdPList" name="IdPList" method="post" onSubmit="return checkForm()" action="<?php echo $actionURL ?>">
<form id="IdPList" name="IdPList" method="post" onSubmit="<?php
if ($useSelect2) {
echo "return select2CheckForm()";
} else {
echo "return checkForm()";
}
?>" action="<?php echo $actionURL ?>">
<div id="userInputArea">
<p class="promptMessage"><?php echo getLocalString('permanent_cookie'); ?></p>
<p><?php echo getLocalString('select_idp'); ?></p>
......
......@@ -5,12 +5,7 @@
// The API is compliant with select2 (https://select2.org/)
/*------------------------------------------------*/
// TODO : gérer la pré-sélection
// TODO : gérer le groupes
// TODO : gérer les icones
$topLevelDir = dirname(__DIR__);
require('common.php');
......@@ -18,7 +13,7 @@ require('idpApiObjects.php');
header('Content-Type: application/json');
$repo = new IdpRepository($IDProviders);
$repo = new IdpRepository($IDProviders, $IDPArray);
global $select2PageSize;
......
......@@ -26,10 +26,11 @@ final class IdpObject
public $names = array();
public $protocols;
public $logo;
/* group */
public $type;
public function __construct($entId, $idp)
{
// FIXME groups are missing
$this->entityId = $entId;
$this->id = $entId;
......@@ -59,8 +60,33 @@ final class IdpObject
// Assume it's a language
$this->names{$key} = $value{"Name"};
}
// Group
if ($key == "Type") {
$this->type = $value;
}
}
}
}
/*
{
"text": "Group 1",
"children" : [
{
"id": 1,
"text": "Option 1.1"
},
{
"id": 2,
"text": "Option 1.2"
}
]
}
*/
final class IdpGroup
{
public $text;
public $children = array();
}
/*
......@@ -73,14 +99,57 @@ final class IdpRepository
// The idps in the form of IdpObject
public $idpObjects = array();
public function __construct(array $IDProviders = array())
public function __construct(array $IDProviders = array(), array $previouslySelectedIdps = null)
{
if ($previouslySelectedIdps != null) {
foreach ($previouslySelectedIdps as $selIdp) {
$idp = new IdpObject($selIdp, $IDProviders[$selIdp]);
$idp->type = getLocalString('last_used');
$this->idpObjects[] = $idp;
}
}
foreach ($IDProviders as $key => $value) {
$tmp = new IdpObject($key, $value);
$this->idpObjects[] = $tmp;
// Skip categories
if ($value['Type'] == 'category') {
continue;
}
// Skip incomplete descriptions
if (!is_array($value) || !isset($value['Name'])) {
continue;
}
$idp = new IdpObject($key, $value);
$this->idpObjects[] = $idp;
}
}
/*
* Groups a given array
*/
private function toGroups($array)
{
$result = array();
$tmp = array();
foreach ($array as $key => $idpObject) {
$type = $idpObject->type;
if (!isset($tmp[$type])) {
$group = new IdpGroup();
$group->text = $type;
$tmp[$type] = $group;
}
$tmp[$type]->children[] = $idpObject;
}
foreach ($tmp as $key => $idpGroup) {
$result[] = $idpGroup;
}
return $result;
}
public function countIdps()
{
return sizeof($this->idpObjects);
......@@ -91,7 +160,7 @@ final class IdpRepository
*/
public function toJson()
{
return json_encode($this->idpObjects);
return json_encode($this->toGroups($this->idpObjects), JSON_UNESCAPED_SLASHES);
}
/*
......@@ -108,8 +177,11 @@ final class IdpRepository
$idpPage = array_slice($array, $from, $pageSize);
$result{"results"} = $idpPage;
$result{"pagination"}{"more"} = (($pageNumber + 1)*$pageSize <= $this->countIdps());
$result{"results"} = $this->toGroups($idpPage);
// When using select2 optgroups, the pagination must be named "paginate"
// $result{"pagination"}{"more"} = (($pageNumber + 1)*$pageSize <= sizeof($array));
$result{"pagination"}{"more"} = (($pageNumber + 1)*$pageSize <= sizeof($array));
return json_encode($result, JSON_UNESCAPED_SLASHES);
}
......
......@@ -20,7 +20,7 @@ function printHeader()
global $useImprovedDropDownList, $disableRemoteLogos, $organizationLogoURL;
global $federationURL, $organizationURL, $faqURL, $helpURL, $privacyURL;
global $customStrings;
global $developmentMode, $useSelect2;
global $developmentMode, $useSelect2, $apiURL;
include(get_template('header.php'));
}
......
......@@ -27,7 +27,7 @@ final class IdpApiTest extends TestCase
require("test.IDProvider.metadata.php");
$repo = new IdpRepository($metadataIDProviders);
$this->assertEquals(
'{"results":[{"id":"https://rigal.enpc.fr/idp/shibboleth","text":"\u00c9cole des Ponts ParisTech","entityId":"https://rigal.enpc.fr/idp/shibboleth","SSO":"https://rigal.enpc.fr/idp/profile/Shibboleth/SSO","name":"\u00c9cole des Ponts ParisTech","names":{"en":"\u00c9cole des Ponts ParisTech","fr":"\u00c9cole des Ponts ParisTech"},"protocols":"urn:oasis:names:tc:SAML:1.1:protocol urn:mace:shibboleth:1.0 urn:oasis:names:tc:SAML:2.0:protocol","logo":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAABIAAAASABGyWs+AAAACXZwQWcAAAAQAAAAEABcxq3DAAAB7ElEQVQoz42Rz2/SYBjHX/rSvmW0sK6WhLLLPIhwdX+C2YWYGdDIMJpF/Z+W6XHxJgtTTCZb0xX5ddOMpWNhbiCQFHugykvXtQIeZjAq030vT57n+X6e7+EB40tUq9WmzgkwTUo+n9l6Xa+f/L2aAti2fXhY43m+WHx/JeBdLufz+Z49fWJZ5/l84T+A1taOjuosy8qywnFctboPgP0vICdLPpYV5vhIJMzz3HA4yr7duRSoVqvn1tnq6mNsDnRdh5CMx++22x1dNyYe13g8njRra+sQQp6f6/f7hvFVEK55PDOtdksQhNRK8s+EQqHQM3qI9tA0EoRAOHzDP+tHCHloz+dmS1XVC5v7ohiGcXCgLt5a7HTasVhsckXX9Wy2G4ncLJUr0Wj0V8LurkTTaGnpNgFhJrM1Aba3cxzHLS/fGY9GiqL8BJrN5snpKULoVXqTdLuPjz9pmgYAUFW12/3iOE46vQkh/PBxH9g2AQDIF4pBURTF4L1EPBAQQvPi3p4CACiXK6IYDIXmE4n4wsJ1lmHe5HaIUqmCv/UfPUwBACRJpih6JZnEeLCx8ZKiUCqVNM2BJMkkCRMP7jcaDdf68xcYY5Zhvg+Hpml6Z7wQuswzC2M86/eTFOU4jmVZjJdxES7D6P32h6voB98GBPZakOIQAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE1LTA3LTIwVDEwOjUwOjIwKzAyOjAwq4YxQQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNy0yMFQxMDo1MDoyMCswMjowMNrbif0AAAAASUVORK5CYII="}],"pagination":{"more":true}}',
'{"results":[{"text":"Ecole avec accents","children":[{"id":"https://rigal.enpc.fr/idp/shibboleth","text":"\u00c9cole des Ponts ParisTech","entityId":"https://rigal.enpc.fr/idp/shibboleth","SSO":"https://rigal.enpc.fr/idp/profile/Shibboleth/SSO","name":"\u00c9cole des Ponts ParisTech","names":{"en":"\u00c9cole des Ponts ParisTech","fr":"\u00c9cole des Ponts ParisTech"},"protocols":"urn:oasis:names:tc:SAML:1.1:protocol urn:mace:shibboleth:1.0 urn:oasis:names:tc:SAML:2.0:protocol","logo":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAABIAAAASABGyWs+AAAACXZwQWcAAAAQAAAAEABcxq3DAAAB7ElEQVQoz42Rz2/SYBjHX/rSvmW0sK6WhLLLPIhwdX+C2YWYGdDIMJpF/Z+W6XHxJgtTTCZb0xX5ddOMpWNhbiCQFHugykvXtQIeZjAq030vT57n+X6e7+EB40tUq9WmzgkwTUo+n9l6Xa+f/L2aAti2fXhY43m+WHx/JeBdLufz+Z49fWJZ5/l84T+A1taOjuosy8qywnFctboPgP0vICdLPpYV5vhIJMzz3HA4yr7duRSoVqvn1tnq6mNsDnRdh5CMx++22x1dNyYe13g8njRra+sQQp6f6/f7hvFVEK55PDOtdksQhNRK8s+EQqHQM3qI9tA0EoRAOHzDP+tHCHloz+dmS1XVC5v7ohiGcXCgLt5a7HTasVhsckXX9Wy2G4ncLJUr0Wj0V8LurkTTaGnpNgFhJrM1Aba3cxzHLS/fGY9GiqL8BJrN5snpKULoVXqTdLuPjz9pmgYAUFW12/3iOE46vQkh/PBxH9g2AQDIF4pBURTF4L1EPBAQQvPi3p4CACiXK6IYDIXmE4n4wsJ1lmHe5HaIUqmCv/UfPUwBACRJpih6JZnEeLCx8ZKiUCqVNM2BJMkkCRMP7jcaDdf68xcYY5Zhvg+Hpml6Z7wQuswzC2M86/eTFOU4jmVZjJdxES7D6P32h6voB98GBPZakOIQAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE1LTA3LTIwVDEwOjUwOjIwKzAyOjAwq4YxQQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNy0yMFQxMDo1MDoyMCswMjowMNrbif0AAAAASUVORK5CYII=","type":"Ecole avec accents"}]}],"paginate":{"more":false}}',
$repo->toJsonByQuery($query, 1)
);
}
......
......@@ -5061,6 +5061,7 @@ $metadataIDProviders = array (
'Name' => 'École des Ponts ParisTech',
),
'Protocols' => 'urn:oasis:names:tc:SAML:1.1:protocol urn:mace:shibboleth:1.0 urn:oasis:names:tc:SAML:2.0:protocol',
'Type' => 'Ecole avec accents',
'Logo' =>
array (
'URL' => 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAABIAAAASABGyWs+AAAACXZwQWcAAAAQAAAAEABcxq3DAAAB7ElEQVQoz42Rz2/SYBjHX/rSvmW0sK6WhLLLPIhwdX+C2YWYGdDIMJpF/Z+W6XHxJgtTTCZb0xX5ddOMpWNhbiCQFHugykvXtQIeZjAq030vT57n+X6e7+EB40tUq9WmzgkwTUo+n9l6Xa+f/L2aAti2fXhY43m+WHx/JeBdLufz+Z49fWJZ5/l84T+A1taOjuosy8qywnFctboPgP0vICdLPpYV5vhIJMzz3HA4yr7duRSoVqvn1tnq6mNsDnRdh5CMx++22x1dNyYe13g8njRra+sQQp6f6/f7hvFVEK55PDOtdksQhNRK8s+EQqHQM3qI9tA0EoRAOHzDP+tHCHloz+dmS1XVC5v7ohiGcXCgLt5a7HTasVhsckXX9Wy2G4ncLJUr0Wj0V8LurkTTaGnpNgFhJrM1Aba3cxzHLS/fGY9GiqL8BJrN5snpKULoVXqTdLuPjz9pmgYAUFW12/3iOE46vQkh/PBxH9g2AQDIF4pBURTF4L1EPBAQQvPi3p4CACiXK6IYDIXmE4n4wsJ1lmHe5HaIUqmCv/UfPUwBACRJpih6JZnEeLCx8ZKiUCqVNM2BJMkkCRMP7jcaDdf68xcYY5Zhvg+Hpml6Z7wQuswzC2M86/eTFOU4jmVZjJdxES7D6P32h6voB98GBPZakOIQAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE1LTA3LTIwVDEwOjUwOjIwKzAyOjAwq4YxQQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNy0yMFQxMDo1MDoyMCswMjowMNrbif0AAAAASUVORK5CYII=',
......
......@@ -90,12 +90,12 @@ if (isset($_POST['clear_user_idp'])) {
exit;
}
// Get previously accessed IdPs
if (isset($_COOKIE[$SAMLDomainCookieName])) {
$IDPArray = getIdPArrayFromValue($_COOKIE[$SAMLDomainCookieName]);
} else {
$IDPArray = array();
}
// // Get previously accessed IdPs
// if (isset($_COOKIE[$SAMLDomainCookieName])) {
// $IDPArray = getIdPArrayFromValue($_COOKIE[$SAMLDomainCookieName]);
// } else {
// $IDPArray = array();
// }
// Get previously accessed SPs
if (isset($_COOKIE[$SPCookieName])) {
......
......@@ -12,26 +12,35 @@ function formatList(idp) {
return idp.text;
}
var img = "";
if (idp.logo !== null) {
// Logo present
if (idp.logo.toLowerCase().indexOf('data:image') !== 0) {
// TODO : gérer le cas où on ne veut pas fetcher les logos distants
// remote logo
img = "<img src='" + idp.logo + "' />";
if (idp.children == null) {
// IDP
var img = "";
if (idp.logo !== null) {
// Logo present
if (idp.logo.toLowerCase().indexOf('data:image') !== 0) {
// TODO : gérer le cas où on ne veut pas fetcher les logos distants
// remote logo
img = "<img src='" + idp.logo + "' />";
} else {
// local logo
img = "<img src='" + idp.logo + "' />";
}
} else {
// local logo
img = "<img src='" + idp.logo + "' />";
img = "&nbsp;";
}
} else {
img = "&nbsp;";
}
var markup = "<div class='select2-result-repository clearfix'>" +
"<div class='select2-result-repository__logo'>" + img + "</div>" +
"<div class='select2-result-repository__title'>" + idp.text + "</div></div>";
var markup = "<div class='select2-result-repository clearfix'>" +
"<div class='select2-result-repository__logo'>" + img + "</div>" +
"<div class='select2-result-repository__title'>" + idp.text + "</div></div>";
return markup;
return markup;
} else {
// Group
var markup = "<div class='select2-result-repository clearfix'>" +
idp.text + "</div>";
return markup;
}
}
/*
......
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