All files / universal.klown/gpii/node_modules/flowManager/src CloudBasedFlowManager.js

78.57% Statements 22/28
75% Branches 3/4
80% Functions 4/5
78.57% Lines 22/28

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170                                      1x 1x 1x   1x             1x                         1x 20x 20x 20x 20x 19x 19x 19x       20x     1x                                     1x   37x 37x               37x 37x         1x                                                                                                                                 1x                      
/**
 * GPII Cloud-Based FlowManager
 *
 * Copyright 2013 OCAD University
 * Copyright 2017 OCAD University
 *
 * Licensed under the New BSD license. You may not use this file except in
 * compliance with this License.
 *
 * The research leading to these results has received funding from the European Union's
 * Seventh Framework Programme (FP7/2007-2013)
 * under grant agreement no. 289016.
 *
 * You may obtain a copy of the License at
 * https://github.com/GPII/universal/blob/master/LICENSE.txt
 */
 
"use strict";
 
var fluid = require("infusion"),
    kettle = require("kettle"),
    gpii = fluid.registerNamespace("gpii");
 
require("gpii-oauth2");
 
/** BASE, UNSECURED CLOUD-BASED FLOW MANAGER -
 * This will be maintained for a while in parallel with the OAuth2-secured API and eventually deprecated
 * This exposes an unsecured HTTP GET API of the form /:userToken/settings/:device
 */
 
fluid.defaults("gpii.flowManager.cloudBased", {
    requestHandlers: {
        settings: {
            route: "/:userToken/settings/:device",
            method: "get",
            type: "gpii.flowManager.cloudBased.settings.handler"
        },
        userLogin: null,
        userLogout: null,
        getUserToken: null
    }
});
 
gpii.flowManager.cloudBased.matchToSettings = function (flowManager, finalPayload, event) {
    var inferredConfiguration = fluid.get(finalPayload, [ "matchMakerOutput", "inferredConfiguration", "gpii-default"]) || {};
    var lifecycleInstructions = gpii.transformer.configurationToSettings(inferredConfiguration, finalPayload.solutionsRegistryEntries);
    var settings = {};
    fluid.each(lifecycleInstructions, function processSolution(solution, solutionId) {
        fluid.each(solution.settingsHandlers, function (settingsHandler) {
            Eif (settingsHandler.settings) {
                settings[solutionId] = settingsHandler.settings;
            }
        });
    });
    event.fire(settings);
};
 
fluid.defaults("gpii.flowManager.cloudBased.settings.handler", {
    gradeNames: ["kettle.request.http", "gpii.flowManager.matchMakingRequest"],
    invokers: {
        handleRequest: {
            funcName: "gpii.flowManager.cloudBased.settings.handleRequest",
            args: ["{request}.events.onError", "{request}.req.params.userToken", "{that}", "{request}.req.params.device"]
        },
        matchToSettings: {
            funcName: "gpii.flowManager.cloudBased.matchToSettings",
            args: ["{flowManager}", "{arguments}.0", "{request}.events.onSuccess"]
        }
    },
    listeners: {
        onMatchDone: "{that}.matchToSettings"
    }
});
 
// unsecured endpoint - will be removed in time
// TODO: However, this now receives direct dispatch from untrusted workflow gpii.request.flowManager.onUntrustedSettings below
gpii.flowManager.cloudBased.settings.handleRequest = function (onError, userToken, handler, deviceString) {
    var deviceContext;
    try {
        deviceContext = kettle.JSON.parse(deviceString);
    } catch (ex) {
        onError.fire({
            isError: true,
            message: "Cloud based flow manager requires device information - failed to parse " + ex.message
        });
        return;
    }
    handler.events.onUserToken.fire(userToken);
    handler.events.onDeviceContext.fire(deviceContext);
};
 
/** BEGIN OAUTH2-SECURED CLOUD-BASED FLOW MANAGER */
 
fluid.defaults("gpii.flowManager.cloudBased.oauth2", {
    gradeNames: ["fluid.component"],
    components: {
        oauth2DataStore: {
            type: "gpii.oauth2.dbDataStore"
        },
        authServer: {
            // note that this subcomponent directly attaches express routes to our underlying express app via its direct API -
            // e.g. at the paths /access_token
            type: "gpii.oauth2.authServer",
            options: {
                components: {
                    dataStore: "{gpii.oauth2.dataStore}"
                },
                members: {
                    expressApp: "{kettle.server}.expressApp"
                },
                events: {
                    onContributeMiddleware: "{kettle.server}.events.onContributeMiddleware",
                    onContributeRouteHandlers: "{kettle.server}.events.onContributeRouteHandlers"
                }
            }
        },
        authGrantFinder: {
            type: "gpii.oauth2.authGrantFinder"
        }
    },
    distributeOptions: {
        setDataStoreOnAuthGrantFinder: {
            record: "{gpii.oauth2.dataStore}",
            target: "{that gpii.oauth2.authorizationService}.options.components.dataStore"
        }
    },
    requestHandlers: {
        // The endpoint to request user settings
        untrustedSettingsGet: {
            route: "/:userToken/untrusted-settings/:device",
            method: "get",
            type: "gpii.flowManager.cloudBased.untrustedSettings.get.handler"
        },
        // The endpoint to update user settings
        untrustedSettingsPut: {
            route: "/:userToken/untrusted-settings",
            method: "put",
            type: "gpii.flowManager.cloudBased.untrustedSettings.put.handler"
        },
        userLogin: null,
        userLogout: null,
        getUserToken: null
    }
});
 
/**
 * This should be used as the last step of the matchmaking process in a cloudbased/Untrusted flowmanager setup.
 * It modifies the final payload by filtering out the irrelevant data before passing it on to the
 * given event.
 *
 * Note that we modify (filter) the users preferences set before passing it on in the payload. This is done because
 * this function is meant for a configuration of the GPII where the local flowmanager is untrusted - therefore we do not
 * want to pass the full preferences set back to it. On the other hand, the PSP need access to the users preferences to show and
 * modify them. Therefore the preferences set is filtered to only contain the preferences and settings that are
 * relevant to the configuration of the device (i.e. in the inferredConfiguration), any preferences not present there
 * are removed. This means a compromised local flowmanager would not gain any further information from looking at
 * the preferences set than it could have got by looking at the inferred configuration.
 */
gpii.flowManager.cloudBased.matchToUntrustedSettings = function (finalPayload, event) {
    // Note that we send the filtered preferences to assist a PSP - we may do more filtering here at some point
    var settings = fluid.filterKeys(finalPayload, [
        "userToken", "activeContextName", "preferences",
        "activeConfiguration", "solutionsRegistryEntries", "matchMakerOutput"
    ]);
    settings.preferences = gpii.matchMakerFramework.utils.filterPreferencesFromInferredConfig(settings.preferences, settings.matchMakerOutput.inferredConfiguration);
    fluid.log("cloudBased flowManager sending settings ", settings);
    event.fire(settings);
};