Как я должен передавать переменные из моих внешних маршрутов в контроллер javascript в Node.js асинхронно? - PullRequest
0 голосов
/ 05 марта 2019

Мои внешние маршруты настроены так, что форма POST отправляет данные на мой сервер, а мой файл сервера проверяет ввод.Затем он принимает эти данные и передает их в другой файл, который затем выполняет аутентификацию.У меня есть несколько вопросов по этому поводу:

1) Нужно ли передавать данные асинхронно?2) Способ, которым я в настоящее время передаю синхронный?Если это нужно изменить 3) Если я хочу передать свои переменные в этот файл, и он использует асинхронный водопад (я считаю, что я не могу передать переменные в первую функцию), я должен создать основную функцию, которая имеет две подфункции (однудля хранения переменных и одной для выполнения асинхронного водопада)?

Я новичок в Node.js, поэтому только начал изучать концепцию асинхронной функциональности.Любые советы, помощь или вопросы, пожалуйста, дайте мне знать.Если я что-то пропустил, пожалуйста, спросите

Функция моего сервера такова:

//Route for POST requests to Login
//First Sanitise input!
app.route('/login').post([
    //ACCOUNTTYPE CHECKS -------------------------------------------------------------------------------
    check('accountType').exists()
    .trim()
    .isAlpha()
    .isLength({
        min: 8,
        max: 10
    })
    .matches(/(Production|Internal)/).withMessage('Must be either \'Production\' or \'Internal\'\!')
    .escape(),

    //CUSTOMERID CHECKS --------------------------------------------------------------------------------
    check('customerID').exists()
    .trim()
    .isNumeric()
    .isInt()
    .isLength({
        max: 40
    })
    .escape(),

    //CLIENTID CHECKS ---------------------
    check('clientID').exists()
    .trim()
    .isAlphanumeric()
    .isLength({
        max: 40
    })
    .escape(),

    //CLIENTSECRET CHECKS ---------------------
    check('clientSecret').exists()
    .trim()
    .isAlphanumeric()
    .isLength({
        min: 0,
        max: 45
    })
    .escape(),

    //USERNAME CHECKS ---------------------
    check('username').exists()
    .trim()
    .isEmail()
    .isLength({
        min: 0,
        max: 100
    })
    .escape(),

    //PASSWORD CHECKS ---------------------
    check('password').exists()
    .trim()
    .isLength({
        min: 0,
        max: 100
    })
    .escape()
], urlencodedParser, (req, res) => {
    let now = new Date().toString(),
        log = `${now}: ${req.method} ${req.url}`,
        sess = req.session;

    console.log(req.body);
    fs.appendFile('server-requests.log', log + '\n', (err) => {
        if (err) {
            console.log('Unable to append to server-requests.log!');
        }
    });

    // Finds the validation errors in this request and wraps them in an object with handy functions
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
        //return a bad status and array of errors
        //if the validation fails
        // return res.status(422).json({
        //     errors: errors.array()
        // });
        //OR:
        return res.render('login.hbs', {
            currentYear: new Date().getFullYear(),
                //This does not work realtime - FIX TODO
                currentTime: moment().format('MMMM Do YYYY - h:mm:ss a'),
                data: {},
                errors: errors.mapped()
        });
    // If there aren't any errors, proceed to save variable data and use  2.0
    } else {
        //Handle with event emiitters and make asynchronous - TODO
        const data = matchedData(req);
        console.log('Data stored in session:')
        console.log('Sanitised:', data);

        //Store Form Data in session variables
        sess.accountType = data.accountType,
        sess.customerID = data.customerID,
        sess.clientID = data.clientID,
        sess.clientSecret = data.clientSecret,
        sess.username = data.username,
        sess.password = data.password;


        console.log('Sanitised POST Form! Now initialising request.');
        req.flash('success', 'Successful POST request, proceeding to authorisation...)');

        //Make asynchronous?
        //use each function and get variables
        auth.saveVariables(sess.accountType, sess.customerID, sess.clientID, sess.clientSecret, sess.username, sess.password);
        auth.asyncWaterfall(callback)

        res.redirect('/index');

        //Or alternatively should it redirect with a query string?
        // const url = require('url');
        // app.get('/index', function (req, res) {
        //     res.redirect(url.format({
        //         pathname: "/",
        //         query: {
        //             "acccountType": 1,
        //             "customerID": 2,
        //             "clientID": 3,
        //             "clientSecret": 4,
        //             "username": 5,
        //             "password": 6
        //         }
        //     }));
        // });
    }
})

Вот начало кода моего контроллера аутентификации:

    const saveVariables = (accountType, customerID, clientID, clientSecret, username, password, callback) => {
        //Test parameters
        if (accountType.type() !== String || customerID.type() !== String || clientID.type() !== String || clientSecret.type() !== String || username.type() !== String || password.type() !== String) {
            let fields = [accountType, customerID, clientID, clientSecret, username, password];
            test(fields);
        }
        accountType,
        customerID,
        clientID,
        clientSecret,
        username,
        password;
    }

    const test = (array) => {
        array.forEach((field) => {
            let errorString;
            if (field.type() !== String) {
                errorString += `The field ${field} is not a String. Type: ${field}.`
            }
            return errorString;
        })
    }

//This const creates the auth URL and auth code grant URL. It also assigns the host URL.
const createAuthURL = (callback) => {
    //If the paramter test passes then proceed
    if (accountType === "Production") {
        try {
            let authURL = `https://${prodURL}${url1}`,
                authCodeURL = `https://${prodURL}${url2}`,
                host = prodURL;
        } catch (e) {
            console.log(`Error occurred when assigning url variables (Production). Error: ${e}`);
            console.error('Error occurred when assigning url variables (Production). Error:', e);
        }
    } else if (accountType === "Internal") {
        try {
            let authURL = `https://${internURL}${url1}`,
                authCodeURL = `https://${internURL}${url2}`,
                host = internURL;
        } catch (e) {
            console.log(`Error occurred when assigning url variables (Internal). Error: ${e}`);
            console.error('Error occurred when assigning url variables (Internal). Error:', e);
        }

    } else {
        console.log(`Bad String Input into auth URL! Entry: ${accountType}`);
        console.error('Bad String Input into auth URL: ', accountType);
    }
}

const asyncWaterfall = (req, res) => {
    //Asynchronous Waterfall Call of 'Getting Access Tokens' (Stages 1-3)
    async.waterfall([
        getCookieData,
        getAuthCode,
        getAccessToken
    ], (err, result) => {
        if (err) {
            alert('Something is wrong!');
        }
        return alert('Done!');
    });

    //STAGE 1 - USE CUSTOMER DETAILS TO RETRIEVE COOKIE AND CSRF SESSION DATA
    getCookieData = async (callback) => {
            //For testing purposes - Remove after development
            console.log(`The type of account used is: ${accountType}`);
            console.log(`The customerID used is: ${customerID}`);
            console.log(`The clientID used is: ${clientID}`);
            console.log(`The client secret used is: ${clientSecret}`);
            console.log(`The username used is: ${username}`);
            console.log(`The password used is: ${password}`);
            console.log(`Making a URL request to: ${authURL}`);

            //If the paramter test passes then proceed
            var options = {
                //Type of HTTP request
                method: 'POST',
                //URI String
                uri: authURL,
                //HTTP Query Strings
                qs: {
                    'client_id': clientID
                },
                //HTTP Headers
                headers: {
                    'cache-control': 'no-cache',
                    'Accept': 'application/json',
                    'Host': host,
                    'Content-Type': 'application/json'
                },
                //HTTP Body
                body: {
                    'username': username,
                    'password': password
                },
                json: true // Automatically stringifies the body to JSON
                //resolveWithFullResponse: true // Get the full response instead of just the body
                //simple: false // Get a rejection only if the request failed for technical reasons
            };
            console.log(`Beginning HTTP POST Request to ${authURL}...`);

            //await literally makes JavaScript wait until the promise settles, and then go on with the result.
            await rp(options)
            .then((parsedBody) => {
                //POST Succeeded...
                Console.log('Successful HTTP POST!');
                try {
                    let csrf = response.body('csrftoken'),
                        ses = response.body('session'),
                        sesk = `session=${ses}`;
                } catch (e) {
                    console.log(`STAGE 1 - Error occurred when assigning url variables. Error: ${e}`);
                    console.error('STAGE 1 - Error occurred when assigning url variables. Error:', e);
                }
                console.log(`Successful grab of the cookie: ${ses} and csrf token: ${csrf}. Getting authorisation code now!`);
                //Asynchronous callback for the next function - return = defensive architecture 
                return callback(null, authCodeURL, customerID, clientID, csrf, sesk);
            })
            .catch((err) => {
                if (res.statusCode == 400) {
                    console.log(`Error Message: ${res.body.message}. Status: ${res.body.status}`);
                    console.error('Error Message:', res.body.message, 'Status:', res.body.status);
                } else if (res.statusCode == 401) {
                    console.log(`Error Message: ${res.body.message}. Status: ${res.body.status}`);
                    console.error('Error Message:', res.body.message, 'Status:', res.body.status);
                } else {
                    console.log(`Failed to retrieve the cookie data! Error: ${error}`);
                    console.error('Failed to retrieve the cookie data! Error:', error);
                }
            });
        },

        //STAGE 2 - USE COOKIES AND CSRF TOKEN TO GET AUTH CODE
        //Is the word async needed? it is not asyncchronous but sequential
        getAuthCode = async (authCodeURL, customerID, clientID, csrf, sesk, callback) => {
                //Make sure all the data is in string format - Run Time Tests
                if (authCodeURL !== String || cutomerID !== String || clientID !== String || csrf !== String || sesk !== String) {
                    let fields = [authCodeURL, cutomerID, clientID, csrf, sesk];
                    test(fields);
                }

                //If successful, proceed:
                var options = {
                    method: 'POST',
                    uri: authCodeURL,
                    qs: {
                        'client_id': clientID,
                        'response_type': 'code',
                        'scope': 'all'
                    },
                    headers: {
                        'X-CSRF-TOKEN': csrf,
                        'Accept': 'application/json',
                        'Cookie': sesk,
                        'Content-Type': 'application/json'
                    },
                    body: {
                        'customer_id': customerID
                    },
                    json: true // Automatically stringifies the body to JSON
                };
                console.log(`Beginning HTTP POST Request to ${authCodeURL}...`);

                //await literally makes JavaScript wait until the promise settles, and then go on with the result.
                await rp(options)
                    .then((parsedBody) => {
                        //POST Succeeded...
                        Console.log('Successful HTTP POST!');
                        try {
                            let authCode = response.body.JSON('auth_code'),
                                swapurl = `https://${host}${url3}`;
                        } catch (e) {
                            console.log(`STAGE 2 - Error occurred when assigning url variables. Error: ${e}`);
                            console.error('STAGE 2 - Error occurred when assigning url variables. Error:', e);
                        }
                        console.log(`The authorisation Code is ${authcode}. Getting Access Token now!`);
                        //Asynchronous callback for the next function - return = defensive architecture
                        return callback(null, swapURL, clientID, clientSecret, authCode);
                    })
                    .catch((err) => {
                        if (res.statusCode == 400) {
                            console.log(`Error Message: ${res.body.message}. Extra: ${res.body.extra}`);
                            console.error('Error Message:', res.body.message, 'Extra:', res.body.extra);
                        } else {
                            console.log(`Failed to retrieve the authorisation code! Error: ${error}`);
                            console.error('Failed to retrieve the authorisation code! Error: ', error);
                        }
                    });
            },

            //STAGE 3 - USE AUTH CODE TO GET ACCESS TOKEN
            //ASYNC NEEDED?
            getAccessToken = async (swapURL, clientID, clientSecret, authCode, callback) => {
                //Make sure all the data is in string format - Run Time Tests
                if (swapURL !== String || clientSecret !== String || clientID !== String || authCode !== String) {
                    let fields = [swapURL, clientSecret, clientID, authCode];
                    test(fields);
                }

                //If successful, proceed:
                var options = {
                    method: 'POST',
                    uri: swapURL,
                    qs: {
                        'client_id': clientID,
                        'grant_type': 'authorization_code',
                        'client_secret': clientSecret,
                        'code': authCode
                    },
                    json: true // Automatically stringifies the body to JSON
                };
                console.log(`Beginning HTTP POST Request to ${swapURL}...`);

                //await literally makes JavaScript wait until the promise settles, and then go on with the result.
                await rp(options)
                    .then((parsedBody) => {
                        //POST Succeeded...
                        Console.log('Successful HTTP POST!');
                        try {
                            let accessToken = response.body('access_token'),
                                refreshToken = response.body('refresh_token');
                        } catch (e) {
                            console.log(`STAGE 3 - Error occurred when assigning url variables. Error: ${e}`);
                            console.error('STAGE 3 - Error occurred when assigning url variables. Error:', e);
                        }
                        console.log(`The access Token is ${accessToken} and the refreshToken which is ${refreshToken}! These are only valid for 2 hours!`);
                        //Asynchronous callback for the waterfall - return = defensive architecture
                        return callback(null, 'done');
                    })
                    .catch((err) => {
                        console.log(`Failed to retrieve the access/refresh Token! Error: ${error}`);
                        console.error('Failed to retrieve the access/refresh Token! Error:', error);
                    });
            }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...