Commit 75f4a7ce authored by Geoffroy ARNOUD's avatar Geoffroy ARNOUD

Changes following Guillaume ROUSSE review #K11:

* Don't rely on CDN for JS
* Consistent defaults
* Refactor a bit logging function
* Removed useless test
* Fixed typo
* Bug fix on embedded
* Added param for Access-Control-Allow-Origin header
* Use legacy 'data' field for searches
parent b63211b3
......@@ -82,6 +82,11 @@
// Config to change the number of IdP fetched when using Select2 dropdown
//$select2PageSize = 100;
// For Select2 to work in embedded WAYF, CORS must be enabled.
// This settings allows to limit origins
// default: *
//$allowedCORSDomain = "*";
// Number of previously used Identity Providers to show at top of drop-down list
// Default is 3, set to 0 to disable
//$showNumOfPreviouslyUsedIdPs = 3;
......
......@@ -149,11 +149,11 @@ var wayf_return_url = "https://my-app.switch.ch/aai/index.php?page=show_welcome"
// Whether or not use Select2 drop down
// Attention: setting this to true, overrides $useImprovedDropDownList param
// For this to fully work, one must also add useSelect2 query Param to the
// embedded-wayf.js script loading URL.
// Page size is contrrolled by WAYF server directly.
// var wayf_use_select2 = false;
// Config to change the number of IdP fetched when using Select2 dropdown
// var wayf_select2_page_size = 100;
// If true the improved drop-down-list will not display IdP logos that
// have to be loaded from remote URLs. That way the web browser
// does not have to make requests to third party hosts.
......@@ -336,7 +336,8 @@ var wayf_return_url = "https://my-app.switch.ch/aai/index.php?page=show_welcome"
//-->
</script>
<!-- To fully enable select2, one have to add useSelect2 query param: -->
<!-- <script type="text/javascript" src="https://<?php echo $host ?><?php echo $path ?>/embedded-wayf.js?useSelect2=true"></script> -->
<script type="text/javascript" src="https://<?php echo $host ?><?php echo $path ?>/embedded-wayf.js"></script>
<noscript>
......
......@@ -14,9 +14,11 @@
if (isUseSelect2()) {
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;
// Load translations
echo '<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/i18n/'.$language.'.js"></script>'.PHP_EOL;
// Version of select2 : 4.0.6-rc.0
// Availability https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js
// Languages available at https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/i18n/<2letterCode>.js
echo '<script type="text/javascript" src="'.$javascriptURL .'/select2.min.js"></script>'.PHP_EOL;
echo '<script type="text/javascript" src="'.$javascriptURL .'/i18n/'.$language.'.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;
......
......@@ -58,6 +58,9 @@ function initConfigOptions()
global $instanceIdentifier;
global $developmentMode;
global $topLevelDir;
global $useSelect2;
global $select2PageSize;
global $allowedCORSDomain;
// Set independet default configuration options
......@@ -71,7 +74,8 @@ function initConfigOptions()
$defaults['showPermanentSetting'] = false;
$defaults['useImprovedDropDownList'] = true;
$defaults['useSelect2'] = false;
$defaults['select2PageSize'] = 50;
$defaults['select2PageSize'] = 100;
$defaults['allowedCORSDomain'] = '*';
$defaults['disableRemoteLogos'] = false;
$defaults['useSAML2Metadata'] = false;
$defaults['SAML2MetaOverLocalConf'] = false;
......@@ -820,54 +824,30 @@ function initLogger()
}
/******************************************************************************/
// Logs a debug message
function logDebug($infoMsg)
{
wayfLog("DEBUG", $infoMsg);
}
// Logs an info message
function logInfo($infoMsg)
{
global $developmentMode;
initLogger();
syslog(LOG_INFO, $infoMsg);
wayfLog("INFO", $infoMsg);
if ($developmentMode && isRunViaCLI()) {
echo $infoMsg;
}
}
/******************************************************************************/
// Logs an warnimg message
function logWarning($warnMsg)
{
global $developmentMode;
initLogger();
syslog(LOG_WARNING, $warnMsg);
wayfLog("WARN", $warnMsg);
if ($developmentMode && isRunViaCLI()) {
echo $warnMsg;
}
}
/******************************************************************************/
// Logs an error message
function logError($errorMsg)
{
global $developmentMode;
initLogger();
syslog(LOG_ERR, $errorMsg);
wayfLog("ERROR", $errorMsg);
if ($developmentMode) {
echo $errorMsg;
}
}
/******************************************************************************/
......@@ -884,8 +864,26 @@ function wayfLog($level, $errorMsg)
{
global $developmentMode;
// If developmentMode => Log to errorLog
if ($developmentMode) {
error_log(sprintf("[%s] %s", $level, $errorMsg));
// Legacy logging
//echo $errorMsg;
}
$syslogPriority = LOG_INFO;
if ($level == "ERROR") {
$syslogPriority = LOG_ERR;
}
if ($level == "WARN") {
$syslogPriority = LOG_WARNING;
}
if ($level != "DEBUG") {
// Syslog Logging
initLogger();
syslog($syslogPriority, $errorMsg);
}
}
......@@ -1157,3 +1155,21 @@ function isUseSelect2()
return $_GET["useSelect2"];
}
function getSelect2PageSize()
{
global $select2PageSize;
if (!isset($_GET["select2PageSize"])) {
return $select2PageSize;
}
return $_GET["select2PageSize"];
}
function buildIdpData($IDProvider, $key)
{
$data = getDomainNameFromURI($key);
$data .= composeOptionData($IDProvider);
return $data;
}
......@@ -11,27 +11,20 @@ require('common.php');
require('idpApiObjects.php');
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
$repo = new IdpRepository($IDProviders, $IDPArray);
global $allowedCORSDomain;
header('Access-Control-Allow-Origin: '.$allowedCORSDomain);
global $select2PageSize;
$repo = new IdpRepository($IDProviders, $IDPArray);
if (array_key_exists("page", $_GET)) {
if (array_key_exists("search", $_GET)) {
//error_log("Search with request ".$_GET["search"]);
if (isset($select2PageSize)) {
echo $repo->toJsonByQuery($_GET["search"], $_GET["page"], $select2PageSize);
} else {
echo $repo->toJsonByQuery($_GET["search"], $_GET["page"]);
}
echo $repo->toJsonByQuery($_GET["search"], $_GET["page"], getSelect2PageSize());
} else {
//error_log("Search page ".$_GET["page"]);
if (isset($select2PageSize)) {
echo $repo->toJsonByPage($_GET["page"], $select2PageSize);
} else {
echo $repo->toJsonByPage($_GET["page"]);
}
echo $repo->toJsonByPage($_GET["page"], getSelect2PageSize());
}
} else {
echo $repo->toJson();
......
......@@ -2,7 +2,7 @@
/*------------------------------------------------*/
/*------------------------------------------------*/
// Classes ued to ease API management
// Classes used to ease API management
/*------------------------------------------------*/
/*------------------------------------------------*/
......@@ -45,6 +45,7 @@ final class IdpObject
/* group */
public $type;
public function __construct($entId, $idp)
{
// $this->entityId = $entId;
......@@ -71,6 +72,16 @@ final class IdpObject
}
}
}
/*
* Legacy data select field construction
* to enable serach as usual
*/
public function getDataForSearch()
{
global $IDProviders;
return buildIdpData($IDProviders[$this->id], $this->id);
}
}
/*
......@@ -165,12 +176,6 @@ final class IdpRepository
$group = new IdpGroup();
$group->text = $type;
$tmp[$type] = $group;
// logInfo(sprintf(
// "hideFirstGroup = %s, type = %s, firstGroupName = %s",
// $hideFirstGroup?"true":"false",
// $type,
// $firstGroupName
// ));
$group->hide = $hideFirstGroup && ($type == $firstGroupName);
}
$tmp[$type]->children[] = $idpObject;
......@@ -227,7 +232,11 @@ final class IdpRepository
}
/*
* Return a pge of IDPs matching the $query
* Return a page of IDPs matching the $query.
* Search is done in:
* - name/text
* - getDomainNameFromURI(entityId)
* - composeOptionData(IDProviders[entityId])
*/
public function toJsonByQuery($query, $pageNumber, $pageSize=10)
{
......@@ -236,9 +245,11 @@ final class IdpRepository
array_filter(
$this->idpObjects,
function ($value) use ($query) {
// logDebug(sprintf("Data(%s) = %s", $value->id, $value->getDataForSearch()));
return (
fnmatch("*".removeAccents($query)."*", removeAccents($value->name), FNM_CASEFOLD)
|| fnmatch("*".removeAccents($query)."*", removeAccents($value->text), FNM_CASEFOLD)
|| fnmatch("*".removeAccents($query)."*", removeAccents($value->getDataForSearch()), FNM_CASEFOLD)
);
}
),
......
......@@ -219,8 +219,7 @@ function printOptionElement($IDProviders, $key, $selectedIDP)
$selected = ($selectedIDP == $key) ? ' selected="selected"' : $selected = '';
// Add additional information as data attribute to the entry
$data = getDomainNameFromURI($key);
$data .= composeOptionData($values);
$data = buildIdpData($values, $key);
// Add logo (which is assumed to be 16x16px) to extension string
$logo = (isset($values['Logo'])) ? 'logo="'.$values['Logo']['URL']. '"' : '' ;
......@@ -352,8 +351,9 @@ function printEmbeddedWAYFScript()
}
// Add other information to find IdP
$IdPData = getDomainNameFromURI($key);
$IdPData .= composeOptionData($IDProvider);
// $IdPData = getDomainNameFromURI($key);
// $IdPData .= composeOptionData($IDProvider);
$IdPData= buildIdpData($IDProvider, $key);
$IdPData = addslashes($IdPData);
// Skip non-IdP entries
......
......@@ -688,6 +688,7 @@
if (typeof jQuery === "function") {
$ = jQuery;
}
console.log("Loading Select2 !");
loadSelect2();
select2Loaded = true;
};
......@@ -710,62 +711,72 @@
var head = document.getElementsByTagName('head')[0];
var select2Script = document.createElement('script');
select2Script.src = "https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js";
select2Script.src = "<?php echo($javascriptURL .'/select2.min.js') ?>";
select2Script.type = 'text/javascript';
var select2Translation = document.createElement('script');
select2Translation.src = "<?php echo('https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/i18n/'.$language.'.js') ?>";
select2Translation.type = 'text/javascript';
select2Script.onload = function() {
console.log("Select2 JS loaded !");
// Load transalation
select2Translation.onload = function() {
console.log("Select2 JS loaded !");
$('.userIdPSelection').select2({
ajax: {
url: <?php echo "'".$apiURL."/idps'" ?>,
delay: 250,
dataType: 'json',
data: function(params) {
var query = {
search: params.term,
page: params.page || 1
}
// Query parameters will be ?search=[term]&page=[page]
return query;
},
error: function(jqxhr, status, exception) {
console.error('Exception:', exception);
<?php
if ($developmentMode) {
echo("alert('Exception:', exception);");
}
?>
// typeof jQuery.fn.select2 === "function" && jQuery.fn.select2.amd ? require(["S2"], runSelect2) : runSelect2();
runSelect2();
};
head.appendChild(select2Script);
}
function runSelect2() {
var head = document.getElementsByTagName('head')[0];
var select2Translation = document.createElement('script');
select2Translation.src = "<?php echo($javascriptURL .'/i18n/'.$language.'.js') ?>";
select2Translation.type = 'text/javascript';
select2Translation.onload = function() {
console.log("Select2 Translation loaded !");
$('.userIdPSelection').select2({
ajax: {
url: <?php echo "'".$apiURL."/idps'" ?>,
delay: 250,
dataType: 'json',
data: function(params) {
var query = {
search: params.term,
page: params.page || 1
}
// Query parameters will be ?search=[term]&page=[page]
return query;
},
placeholder: "<?php echo getLocalString('select_idp') ?>",
allowClear: true,
language: "<?php echo $language ?>",
templateResult: formatIdp,
templateSelection: formatIdp,
escapeMarkup: function(text) {
return text;
error: function(jqxhr, status, exception) {
console.error('Exception:', exception);
<?php
if ($developmentMode) {
echo("alert('Exception:', exception);");
}
});
// Auto-submit when an idp is selected
$('.userIdPSelection').on('select2:select', function(e) {
document.getElementById("IdPList").submit();
});
}
};
?>
}
},
placeholder: "<?php echo getLocalString('select_idp') ?>",
allowClear: true,
language: "<?php echo $language ?>",
templateResult: formatIdp,
templateSelection: formatIdp,
escapeMarkup: function(text) {
return text;
}
});
// Auto-submit when an idp is selected
$('.userIdPSelection').on('select2:select', function(e) {
document.getElementById("IdPList").submit();
});
head.appendChild(select2Script);
};
head.appendChild(select2Translation);
}
<?php } ?>
(function() {
......@@ -802,7 +813,7 @@
typeof wayf_select2_page_size === "undefined" ||
typeof wayf_select2_page_size !== "number"
) {
wayf_select2_page_size = 50;
wayf_select2_page_size = 100;
}
if (
......
/*! Select2 4.0.6-rc.0 | https://github.com/select2/select2/blob/master/LICENSE.md */
(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/en",[],function(){return{errorLoading:function(){return"The results could not be loaded."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Please delete "+t+" character";return t!=1&&(n+="s"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Please enter "+t+" or more characters";return n},loadingMore:function(){return"Loading more results…"},maximumSelected:function(e){var t="You can only select "+e.maximum+" item";return e.maximum!=1&&(t+="s"),t},noResults:function(){return"No results found"},searching:function(){return"Searching…"}}}),{define:e.define,require:e.require}})();
\ No newline at end of file
/*! Select2 4.0.6-rc.0 | https://github.com/select2/select2/blob/master/LICENSE.md */
(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/fr",[],function(){return{errorLoading:function(){return"Les résultats ne peuvent pas être chargés."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Supprimez "+t+" caractère"+(t>1)?"s":""},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Saisissez au moins "+t+" caractère"+(t>1)?"s":""},loadingMore:function(){return"Chargement de résultats supplémentaires…"},maximumSelected:function(e){return"Vous pouvez seulement sélectionner "+e.maximum+" élément"+(e.maximum>1)?"s":""},noResults:function(){return"Aucun résultat trouvé"},searching:function(){return"Recherche en cours…"}}}),{define:e.define,require:e.require}})();
\ No newline at end of file
/*! Select2 4.0.6-rc.0 | https://github.com/select2/select2/blob/master/LICENSE.md */
(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/it",[],function(){return{errorLoading:function(){return"I risultati non possono essere caricati."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Per favore cancella "+t+" caratter";return t!==1?n+="i":n+="e",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Per favore inserisci "+t+" o più caratteri";return n},loadingMore:function(){return"Caricando più risultati…"},maximumSelected:function(e){var t="Puoi selezionare solo "+e.maximum+" element";return e.maximum!==1?t+="i":t+="o",t},noResults:function(){return"Nessun risultato trovato"},searching:function(){return"Sto cercando…"}}}),{define:e.define,require:e.require}})();
\ No newline at end of file
/*! Select2 4.0.6-rc.0 | https://github.com/select2/select2/blob/master/LICENSE.md */
(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ja",[],function(){return{errorLoading:function(){return"結果が読み込まれませんでした"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+" 文字を削除してください";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="少なくとも "+t+" 文字を入力してください";return n},loadingMore:function(){return"読み込み中…"},maximumSelected:function(e){var t=e.maximum+" 件しか選択できません";return t},noResults:function(){return"対象が見つかりません"},searching:function(){return"検索しています…"}}}),{define:e.define,require:e.require}})();
\ No newline at end of file
/*! Select2 4.0.6-rc.0 | https://github.com/select2/select2/blob/master/LICENSE.md */
(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/pt",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Por favor apague "+t+" ";return n+=t!=1?"caracteres":"caractere",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Introduza "+t+" ou mais caracteres";return n},loadingMore:function(){return"A carregar mais resultados…"},maximumSelected:function(e){var t="Apenas pode seleccionar "+e.maximum+" ";return t+=e.maximum!=1?"itens":"item",t},noResults:function(){return"Sem resultados"},searching:function(){return"A procurar…"}}}),{define:e.define,require:e.require}})();
\ No newline at end of file
/*! Select2 4.0.6-rc.0 | https://github.com/select2/select2/blob/master/LICENSE.md */
(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/tr",[],function(){return{errorLoading:function(){return"Sonuç yüklenemedi"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+" karakter daha girmelisiniz";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="En az "+t+" karakter daha girmelisiniz";return n},loadingMore:function(){return"Daha fazla…"},maximumSelected:function(e){var t="Sadece "+e.maximum+" seçim yapabilirsiniz";return t},noResults:function(){return"Sonuç bulunamadı"},searching:function(){return"Aranıyor…"}}}),{define:e.define,require:e.require}})();
\ No newline at end of file
This diff is collapsed.
......@@ -21,10 +21,6 @@ function doFormatIdp(idp, logo) {
return idp.text;
}
if (idp.id === '') { // adjust for custom placeholder values
console.log("null Id => ", idp);
}
if (idp.children == null) {
// IDP
var img = "";
......
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