/*
* Copyright 2023 Anyware Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Tool to display the result of all relevant AccessController for the context
*/
Ext.define('Ametys.plugins.coreui.rights.ExplainUserRightTool', {
extend: "Ametys.plugins.coreui.rights.RightContextSelectionTool",
/**
* @cfg {String} showUnknowResultIconCls The separated CSS classes to apply to button to show unknown results
*/
showUnknowResultIconCls: 'ametysicon-sign-add',
/**
* @cfg {String} showUnknowResultIconCls Tooltip of the button to show unknown results
*/
showUnknowResultTooltip: "{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_SHOW_UNKNOWN_RESULTS}}",
/**
* @cfg {String} hideUnknowResultIconCls The separated CSS classes to apply to button to hide unknown results
*/
hideUnknowResultIconCls: 'ametysicon-sign-minus',
/**
* @cfg {String} hideUnknowResultIconCls Tooltip of the button to hide unknown results
*/
hideUnknowResultTooltip: "{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_HIDE_UNKNOWN_RESULTS}}",
constructor: function(config)
{
this.callParent(arguments);
// Create the result template
this._resultTpl = new Ext.XTemplate(
'{[this.setAnyUserMode(values.mode)]}',
'<p><i class="icon {[this.computeGlyph(values.result)]}"></i>{[this.computeSummaryLabel(values.result)]}</p>',
'<h2>{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_RESULT_DETAILS_LABEL}}</h2>',
'<tpl if="values.explanations.length != 0">',
'<ul>',
'<tpl for="explanations">',
'<li data-type="{accessResult}"><i class="icon {[this.computeGlyph(values.accessResult)]}"></i><span data-qtip="{accessControllerId}">{explanation}</span></li>',
'</tpl>',
'</ul>',
'<tpl else>',
'<p>-</p>',
'</tpl>',
{
setAnyUserMode(mode)
{
this._anyUser = mode == "anyUser";
},
computeGlyph: function(result)
{
switch (result)
{
case Ametys.plugins.coreui.rights.AccessResult.ANONYMOUS_ALLOWED:
case Ametys.plugins.coreui.rights.AccessResult.ANY_CONNECTED_ALLOWED:
case Ametys.plugins.coreui.rights.AccessResult.GROUP_ALLOWED:
case Ametys.plugins.coreui.rights.AccessResult.USER_ALLOWED:
return "ametysicon-check-1 allowed";
case Ametys.plugins.coreui.rights.AccessResult.ANONYMOUS_DENIED:
case Ametys.plugins.coreui.rights.AccessResult.ANY_CONNECTED_DENIED:
case Ametys.plugins.coreui.rights.AccessResult.GROUP_DENIED:
case Ametys.plugins.coreui.rights.AccessResult.USER_DENIED:
return "ametysicon-cross-1 denied";
case Ametys.plugins.coreui.rights.AccessResult.UNKNOWN:
default:
return "ametysicon-sign-question unknown";
}
},
computeSummaryLabel: function(result)
{
switch (result)
{
case Ametys.plugins.coreui.rights.AccessResult.ANONYMOUS_ALLOWED:
case Ametys.plugins.coreui.rights.AccessResult.ANY_CONNECTED_ALLOWED:
case Ametys.plugins.coreui.rights.AccessResult.GROUP_ALLOWED:
case Ametys.plugins.coreui.rights.AccessResult.USER_ALLOWED:
return this._anyUser ? "{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_RESULT_SUMMARY_ANY_USER_ALLOWED}}" : "{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_RESULT_SUMMARY_CURRENT_USER_ALLOWED}}";
case Ametys.plugins.coreui.rights.AccessResult.ANONYMOUS_DENIED:
case Ametys.plugins.coreui.rights.AccessResult.ANY_CONNECTED_DENIED:
case Ametys.plugins.coreui.rights.AccessResult.GROUP_DENIED:
case Ametys.plugins.coreui.rights.AccessResult.USER_DENIED:
case Ametys.plugins.coreui.rights.AccessResult.UNKNOWN:
default:
return this._anyUser ? "{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_RESULT_SUMMARY_ANY_USER_DENIED}}" : "{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_RESULT_SUMMARY_CURRENT_USER_DENIED}}";
}
}
}
);
this._contextTpl = new Ext.XTemplate("...");
},
createPanel: function()
{
var me = this;
// content will be filled with refresh
this._contextCmp = Ext.create('Ext.Component', {ui: 'tool-hintmessage', flex: 1});
// content will be filled with refresh
this._resultCmp = Ext.create('Ext.panel.Panel', {
anchor: "100%",
cls: 'results',
dockedItems: [{
layout: {
type: 'hbox',
align: 'middle'
},
defaultType: 'button',
margin: 0,
items: [
{
xtype: 'component',
html: '<h2>{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_RESULT_SUMMARY_LABEL}}</h2>',
flex: 1
},
{
// show/hide empty data
iconCls: this.showUnknowResultIconCls,
tooltip: this.showUnknowResultTooltip,
scope: this,
enableToggle: true,
toggleHandler: this.showUnknownResults,
cls: 'a-btn-light'
}
]
}],
tpl: this._resultTpl
});
return Ext.create('Ext.container.Container', {
layout: {
type: 'card'
},
cls: 'uitool-explain-user-right',
items: [
{
itemId: 'invalid-selection-card',
xtype: 'component',
cls: 'a-panel-text-empty',
border: false,
html: ''
}, {
itemId: 'result-card',
cls: 'result-card-panel',
layout: "anchor",
defaults: {
anchor: "100%",
minWidth: 300,
},
scrollable: true,
dockedItems: [
this._contextCmp
],
items: [
Ext.create("Ametys.form.field.RightByProfile", {
itemId: 'right',
fieldLabel: '{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_RIGHT_WIDGET_LABEL}}',
labelAlign: 'top',
labelSeparator: '',
showProfilesIncludingRight: true,
value: Ametys.form.widget.Right.READER_RIGHT,
ametysDescription: '{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_RIGHT_WIDGET_DESC}}',
cls: 'ametys',
padding: "5 5 0 5",
allowBlank: false,
listeners: {change: function() {me.showOutOfDate();}}
}), {
xtype: 'edition.user',
itemId: 'user',
fieldLabel: '{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_USER_WIDGET_LABEL}}',
labelAlign: 'top',
labelSeparator: '',
cls: 'ametys',
padding: "5 5 0 5",
value: "CURRENT",
multiple: false,
emptyText: `{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_USER_WIDGET_EMPTY}}`,
ametysDescription: `{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_USER_WIDGET_DESC}}`,
listeners: {change: function() {me.showOutOfDate();}}
},
this._resultCmp
]
}
]
});
},
setParams: function(params)
{
this._switchMode(params.mode || "anyUser")
this.callParent(arguments);
},
showUnknownResults: function(btn, pressed)
{
if (pressed)
{
btn.setIconCls(this.hideUnknowResultIconCls);
btn.setTooltip(this.hideUnknowResultTooltip);
this._resultCmp.addCls('show-unknown')
}
else
{
btn.setIconCls(this.showUnknowResultIconCls);
btn.setTooltip(this.showUnknowResultTooltip);
this._resultCmp.removeCls('show-unknown')
}
this._resultCmp.hide();
this._resultCmp.show();
},
_switchMode: function(mode)
{
if(this._mode != mode)
{
this._mode = mode;
var contextHint;
if (mode == 'anyUser')
{
this.getContentPanel().getComponent('result-card').getComponent('user').setVisible(true);
contextHint = `{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_CONTEXT_HEADER_ANY_USER}}`
}
else
{
this.getContentPanel().getComponent('result-card').getComponent('user').setVisible(false);
contextHint = `{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_CONTEXT_HEADER_CURRENT_USER}}`
}
contextHint += `</br><tpl if="contextType">({contextType})</tpl> <strong data-qtip="{contextId}">{[Ext.String.escapeHtml(values.contextLabel)]}</strong>`
this._contextTpl.set(contextHint, true);
}
},
setNoSelectionMatchState: function (message)
{
var mainPanel = this.getContentPanel()
mainPanel.setActiveItem('invalid-selection-card');
mainPanel.getComponent('invalid-selection-card').setHtml(message);
// call parent to ensure normal operation
this.callParent(arguments);
},
refresh: function(manual)
{
this.showRefreshing();
var targets = this.getCurrentSelectionTargets(); // [][0] == undefined
if (targets.length > 1
|| targets.length == 0 && Ametys.message.MessageBus.getCurrentSelectionMessage().getTargets().length != 0)
{
// if selection multiple or not empty, do nothing
this.showUpToDate(true);
return;
}
var target = targets[0];
this.getContentPanel().setActiveItem('result-card');
// Update context header
var contextId = this.getContextId(target);
var contextInfo = this.getContextInfo(target);
this._contextCmp.setHtml(this._contextTpl.apply({contextLabel: contextInfo.label, contextId: contextId, contextType: contextInfo.type}));
// Check if right is set. If so call server. Otherwise stop and hide the result component
var right = this.getContentPanel().getComponent('result-card').getComponent('right').getValue();
if (right != null)
{
this._resultCmp.setVisible(true);
this._updateResultCard(contextId, right);
}
else
{
this._resultCmp.setVisible(false);
this.showUpToDate();
}
},
_updateResultCard: function(context, right)
{
var serverId = this.getConvertorId();
var args = {
context: context
};
if (this._mode == "anyUser")
{
var user = this.getContentPanel().getComponent('result-card').getComponent('user').getValue();
args.user = user;
this.serverCall('explainRight', [right, user, context, serverId], this._explainRightCb, {arguments: args, cancelCode: this.getId() + "$explain"});
}
else
{
this.serverCall('explainCurrentUserRight',[right, context, serverId], this._explainRightCb, {arguments: args, cancelCode: this.getId() + "$explain"})
}
},
_explainRightCb: function(response, args)
{
var result = response.result != Ametys.plugins.coreui.rights.AccessResult.UNKNOWN ? response.result : Ametys.plugins.coreui.rights.AccessResult.USER_DENIED
this._resultCmp.update({
result : result,
explanations: response.explanations,
user: args.user,
mode: this._mode
});
this.showUpToDate();
}
});