/*
* 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.
*/
/**
* The temporay users DAO
* @private
*/
Ext.define('Ametys.plugins.web.tempusers.TempUsersDAO', {
singleton: true,
constructor: function(config)
{
/**
* @callable
* @member Ametys.plugins.web.tempusers.TempUsersDAO
* @method getTempUsersProperties
* Gets temporary users information.
* This calls the method 'getTempUsersInformation' of the server component 'org.ametys.web.usermanagement.UserSignupManager'.
* @param {Object[]} parameters The parameters to transmit to the server method
* @param {String[]} parameters.emails The emails of the temporary users to retrieve.
* @param {String[]} parameters.siteName The site name of the temporary users to retrieve.
* @param {Function} callback The function to call when the java process is over. Use options.scope for the scope.
* @param {Object[]} callback.tempusers The temporary users' properties. Null on error (please note that when an error occured, the callback may not be called depending on the value of errorMessage).
* @param {String[]} callback.unknownTempusers The unknown temporay users
* @param {Object} callback.arguments Other arguments specified in option.arguments
* @param {Object} [options] Advanced options for the call.
* @param {Boolean/String/Object} [options.errorMessage] Display an error message. See Ametys.data.ServerComm#callMethod errorMessage.
* @param {Boolean/String/Object} [options.waitMessage] Display a waiting message. See Ametys.data.ServerComm#callMethod waitMessage.
* @param {Number} [options.scope] This parameter is the scope used to call the callback. Moreover is the given class is a mixin of Ametys.data.ServerCaller, its methods Ametys.data.ServerCaller#beforeServerCall and Ametys.data.ServerCaller#afterServerCall will be used so see their documentation to look for additional options (such a refreshing on Ametys.ribbon.element.ui.ButtonController#beforeServerCall).
* @param {Number} [options.priority] The message priority. See Ametys.data.ServerComm#callMethod for more information on the priority. PRIORITY_SYNCHRONOUS cannot be used here.
* @param {String} [options.cancelCode] Cancel similar unachieved read operations. See Ametys.data.ServerComm#callMethod cancelCode.
* @param {Object} [options.arguments] Additional arguments set in the callback.arguments parameter.
* @param {Boolean} [options.ignoreCallbackOnError] If the server throws an exception, should the callback beeing called with a null parameter. See Ametys.data.ServerComm#callMethod ignoreOnError.
*/
this.addCallables(
{
role: "org.ametys.web.usermanagement.UserSignupManager",
methodName: "getTempUsersProperties",
callback: {
handler: Ext.emptyFn
},
waitMessage: true,
errorMessage: {
msg: "{{i18n PLUGINS_WEB_DAO_TEMPUSERS_REQUEST_ERROR}}",
category: Ext.getClassName(this)
}
}
);
},
/**
* Get a temporary user by email (for current site) asynchronously
* @param {String} email The email of the temporary user to get. Cannot be null.
* @param {String} siteName The site name of the temporary user to get. Cannot be null.
* @param {Function} callback The method that will be called
* @param {Ametys.plugins.web.tempusers.TempUser} callback.tempuser The retrieved temporary user. Can be empty.
*/
getTempUser: function (email, callback)
{
if (Ext.isEmpty(id))
{
callback(null);
return;
}
this._getTempUsers ([email], Ext.bind(this._getTempUserCb, this, [callback], 1));
},
/**
* @private
* Called after #getTempUser to finally call the callback argument
* @param {Ametys.plugins.web.tempusers.TempUser[]} tempusers The retrieved temporary users. Can be empty.
* @param {Function} callback The function to call back
* @param {Ametys.plugins.web.tempusers.TempUser} callback.tempuser The temporary user. Can be empty.
*/
_getTempUserCb: function (tempusers, callback)
{
callback((tempusers.length == 0) ? null : tempusers[0]);
},
/**
* Get several temporay users by their emails (for current site) asynchronously
* @param {String[]} emails The emails of the temporary users to gets. Cannot be null or empty.
* @param {Function} callback The method that will be called
* @param {Ametys.plugins.web.tempusers.TempUser[]} callback.tempusers The retrieved tempusers. Can be empty.
*/
getTempUsers: function (emails, callback)
{
if (Ext.isEmpty(emails))
{
callback([]);
return;
}
this._getTempUsers (emails, Ext.bind(this._getTempUsersCb, this, [callback], 1));
},
/**
* @private
* Called after #getTempUsers to finally call the callback argument
* @param {Ametys.plugins.web.tempusers.TempUser[]} tempusers The retrieved tempusers. Can be empty.
* @param {Function} callback The function to call back
* @param {Ametys.plugins.web.tempusers.TempUser[]} callback.tempusers The retrieved tempusers. Can be empty.
*/
_getTempUsersCb: function (tempusers, callback)
{
callback(tempusers);
},
/**
* Retrieve temporary users from the cache, or by doing a server request.
* @param {String[]} emails The emails
* @param {Function} callback The callback function called after retrieving the temporary users. Has the following parameters:
* @param {Ametys.plugins.web.tempusers.TempUser[]} callback.tempusers An array of retrieved temporary users. Can be empty.
* @param {String[]} callback.unknownTempusers Array of unknown emails among the requested list.
* @param {Object} [scope=window] The callback scope, default to window. Can be null.
* @param {Boolean} [displayErrors=false] Set to true to display error dialog box if unknown temp users are reported.
* @private
*/
_getTempUsers: function(emails, callback, scope, displayErrors)
{
this._initCache();
emails = Ext.Array.from(emails);
var resolved = {}, unresolved = [], tempuser;
Ext.Array.each(emails, function(email) {
tempuser = this._getFromCache(email);
if (tempuser)
{
resolved[id] = tempuser;
}
else if (!Ext.Array.contains(this._resolving, email))
{
this._resolving.push(email);
unresolved.push(email);
}
}, this);
if (unresolved.length > 0)
{
this.getTempUsersProperties([emails, Ametys.getAppParameter('siteName')], this._sendGetTempUserRequestCb, {scope: this, arguments: [callback, scope, displayErrors || false]});
}
else
{
callback.call(scope || window, Ext.Object.getValues(resolved), []);
}
},
/**
* Callback function called after #getTempUsersProperties is processed
* @param {Object} response The response object.
* @param {Array} args The callback arguments.
* @param {Array} params The parameters.
* @private
*/
_sendGetTempUserRequestCb: function (response, args, params)
{
var callback = args[0] || Ext.emptyFn;
var scope = args[1] || window;
var displayErrors = args[3] || false;
var tempusers = [];
var unknownTempusers = response.unknownTempusers || [];
// Populate cache.
Ext.Array.forEach(response.tempusers, function(data) {
var tempuser = Ext.create ('Ametys.plugins.web.tempusers.TempUser', data);
tempusers.push(tempuser);
this._addToCache(data.email, tempuser);
}, this);
if (displayErrors && unknownTempusers.length > 0)
{
Ametys.log.ErrorDialog.display({
title: "{{i18n PLUGINS_WEB_DAO_TEMP_USER_NOT_FOUND_ERROR_TITLE}}",
text: "{{i18n PLUGINS_WEB_DAO_TEMP_USER_NOT_FOUND_ERROR_MSG}}",
details: unknownTempusers.join(", "),
category: this.self.getName()
});
}
if (typeof callback == 'function')
{
callback (tempusers, unknownTempusers);
}
},
/**
* @property {Object} _cache The DAO cache. Keys are temporary users' email, Values are an object representing the temporary user data.
* @private
*/
_cache: null,
/**
* @property {Object} _cacheExpirations The object holding the expiration times for each entry in the cache
* @private
*/
_cacheExpirations : null,
/**
* @property {String[]} _resolving Array of the requested temporay users that are currently being resolved on the server.
* Used to avoid making several requests for the same temporay user in a short period of time.
* @private
*/
_resolving: null,
/**
* Update a temporay user in the cache. Nothing will be done if the entry is not present in the cache.
* This must be done when some data of a temporary user are modified.
* @param {String} email the email
* @param {Object} updatedData The properties to update for this temporay user.
*/
localUpdate: function(email, updatedData)
{
this._initCache();
var tempuser = this._getFromCache(email);
if (tempuser)
{
tempuser.setProperties(updatedData);
this._addToCache(email, tempuser);
}
},
/**
* Remove a temporay user in the cache.
* This must be used to invalidate an entry in the cache.
* Typically it must be done when a temporary user have just been removed on the server.
* @param {String} email the email
*/
localRemove: function(email)
{
this._initCache();
delete this._cache[email];
delete this._cacheExpirations[email];
delete this._resolving[email];
},
/**
* Cache initialization
* @private
*/
_initCache: function()
{
if (this._cache == null)
{
this._cache = {};
this._cacheExpirations = {};
this._resolving = [];
}
},
/**
* Cache invalidation
*/
invalidateCache: function()
{
this._cache = null;
this._initCache();
},
/**
* Internal method to put an entry in the cache.
* @private
*/
_addToCache: function(email, tempuser)
{
this._cache[email] = tempuser;
this._cacheExpirations[email] = Ext.Date.add(new Date(), Ext.Date.MINUTE, 15);
Ext.Array.remove(this._resolving, email);
},
/**
* Internal method to retrieve an entry in the cache.
* @private
*/
_getFromCache: function(email)
{
if (this._cacheExpirations[email] && new Date() <= this._cacheExpirations[email])
{
return this._cache[email];
}
else
{
this.localRemove(email);
return null;
}
}
});