UNPKG

gpii-universal

Version:

Cross platform, core components of the GPII personalization infrastructure.

208 lines (183 loc) 8.31 kB
/*! * User Logon Request * * Copyright 2018 OCAD University * * Licensed under the New BSD license. You may not use this file except in * compliance with this License. * * You may obtain a copy of the License at * https://github.com/GPII/universal/blob/master/LICENSE.txt */ "use strict"; var fluid = fluid || require("infusion"), gpii = fluid.registerNamespace("gpii"); // One dynamic component of this type is constructed for each user logon request on the LifecycleManager. fluid.defaults("gpii.lifecycleManager.userLogonRequest", { gradeNames: ["fluid.component"], logonState: null, // "login" or "logout". Supplied at defining inherited request handler grades gpiiKey: null, // A GPII key. Supplied at creating dynamic request instances requestPromise: null, // A promise. Supplied at creating dynamic request instances events: { onSuccess: null, onError: null }, invokers: { handleRequest: { funcName: "gpii.lifecycleManager.userLogonRequest.handleRequest", args: ["{that}", "{lifecycleManager}", "{arguments}.0"] // logonState } }, listeners: { "onCreate.handleRequest": { listener: "{that}.handleRequest", args: ["{that}.options.logonState"] }, "onSuccess.handleSuccessRequest": { listener: "gpii.lifecycleManager.userLogonRequest.handleSuccessRequest", args: ["{that}", "{arguments}.0"] }, "onError.handleFailedRequest": { listener: "gpii.lifecycleManager.userLogonRequest.handleFailedRequest", args: ["{that}", "{lifecycleManager}.userErrors.events.userError", "{arguments}.0"], priority: "after:handleErrors" } } }); gpii.lifecycleManager.userLogonRequest.handleRequest = function (that, lifecycleManager, logonState) { var gpiiKey = that.options.gpiiKey; var activeGpiiKey = lifecycleManager.getActiveSessionGpiiKey(); // find currently logged in user: // keep track of the last non-noUser key for /proximityTriggered endpoint to verify its debounce rule // even when the the current active key is "noUser". if (gpiiKey && gpiiKey !== "noUser") { gpii.lifecycleManager.userLogonHandling.updateCurrentUserLogon(lifecycleManager, gpiiKey, logonState); } // handle reset requests if (gpiiKey === "reset") { that.handleResetGpiiKey(); return; } // handle keyin requests if (logonState === "login") { that.loginUser(gpiiKey); } // handle keyout requests if (logonState === "logout") { if (activeGpiiKey !== gpiiKey) { var ignoreUserErrors = activeGpiiKey === "noUser" ? true : false; lifecycleManager.errorResponse(that, "Got logout request from user " + gpiiKey + ", but the user " + activeGpiiKey + " is logged in. So ignoring the request.", 409, ignoreUserErrors); } else { that.logoutUser(gpiiKey); } } }; gpii.lifecycleManager.userLogonRequest.handleSuccessRequest = function (that, payload) { fluid.log("UserLogonRequest completes successfully with the payload: ", payload); that.options.requestPromise.resolve(payload); that.destroy(); }; gpii.lifecycleManager.userLogonRequest.handleFailedRequest = function (that, userErrorEvent, err) { fluid.log("UserLogonRequest fails with the error: ", err); if (gpii.userErrors.isConnectionError(err.code)) { userErrorEvent.fire({ isError: true, messageKey: "NoConnection", originalError: err }); } else if (!err.ignoreUserErrors) { userErrorEvent.fire({ isError: true, messageKey: "KeyInFail", originalError: err.message }); } that.options.requestPromise.reject(err); that.destroy(); }; // Define the grade to be used for key-in and key-out gpii.lifecycleManager.userLogonRequest.handlerGrades = { login: "gpii.lifecycleManager.loginRequest", logout: "gpii.lifecycleManager.logoutRequest" }; // A variant of user logon request to handle key-in requests. // Note: The gradename that handles the logon state change will be distributed down: // 1. When GPII runs in the all-in-local config, the handler grade // "gpii.lifecycleManager.userLogonHandling.matchMakingStateChangeHandler" is distributed by "gpii.flowManager.local"; // 2. When GPII runs in the untrusted config, the handler grade // "gpii.lifecycleManager.untrusted.stateChangeHandler" is distributed by "gpii.flowManager.untrusted". fluid.defaults("gpii.lifecycleManager.loginRequest", { gradeNames: [ "gpii.lifecycleManager.userLogonRequest" ], logonState: "login" }); // A variant of user logon request to handle key-out requests. fluid.defaults("gpii.lifecycleManager.logoutRequest", { gradeNames: [ "gpii.lifecycleManager.userLogonRequest", "gpii.lifecycleManager.userLogonHandling.stateChangeHandler" ], logonState: "logout" }); /* * The lifecycleManager logon request queue is used to hold the key-in and key-out requests. * The entries in the action queue are of the format: * { * gpiiKey: {String}, * logonState: {String} // enum: ["login", "logout"] * } * The action queue is run sequentially, and an item is considered "done" once the promise returned by the request * is resolved. */ gpii.lifecycleManager.addToUserLogonRequestQueue = function (that, queue, item) { var newItem = fluid.copy(item); newItem.requestPromise = fluid.promise(); queue.push(newItem); if (queue.length === 1) { that.processUserLogonRequestQueue(); } return newItem.requestPromise; }; gpii.lifecycleManager.processUserLogonRequestQueue = function (that, queue) { // Pick the first item and process. This item will be removed from the queue once the processing completes. var item = queue[0]; var gradeName = gpii.lifecycleManager.userLogonRequest.handlerGrades[item.logonState]; if (!gradeName) { fluid.fail("No handler grade found for user logon action - " + item.logonState); }; that.events.onUserLogonRequestReceived.fire(gradeName, item.gpiiKey, item.requestPromise); item.requestPromise.then(that.endProcessOneUserLogonRequest, that.endProcessOneUserLogonRequest); }; gpii.lifecycleManager.endProcessOneUserLogonRequest = function (lifecycleManager) { // TODO: fluid.invokeLater() is to work around an issue that kettle reports the error "Failing to resume callback for // request xxx which has already concluded". The request that fails to resume callback is the user logon request that // the current "endProcessOneUserLogonRequest" callback is attached with. It appears that starting the process of // "noUser" keyin before the current callback completes triggers this error. fluid.invokeLater() helps to pull the // "noUser" keyin into a separate process. The request failure needs to be further investigated. fluid.invokeLater(function () { var queue = lifecycleManager.userLogonRequestQueue; // The processing on the first item completes. Remove it from the queue. queue.shift(); if (queue.length > 0) { // process next item in the queue if it exists lifecycleManager.processUserLogonRequestQueue(queue); } else { // if no actual user is logged in, login with "noUser" var activeGpiiKey = lifecycleManager.getActiveSessionGpiiKey(); // find currently logged in user: // Checking lifecycleManager.model.logonChange.inProgress is to make sure during the period to finish // this request handling, there isn't another user logon request being added to the queue and in process. if (!activeGpiiKey) { fluid.log("No active keys in GPII. Key in noUser"); lifecycleManager.addToUserLogonRequestQueue({ gpiiKey: "noUser", logonState: "login" }); } else { lifecycleManager.events.onQueueEmpty.fire(activeGpiiKey); } } }); };