Невозможно установить переменную из выражения ExpressJS res.locals.connection.query () - PullRequest
0 голосов
/ 10 сентября 2018

Я пытаюсь создать функцию единого входа, которая проверяет, был ли пользователь уже подготовлен, и либо создает пользователя, либо обновляет базу данных самой последней информацией.

Я установил обновление / вставку, но теперь не могу вернуть идентификатор пользователя (uid или UserID) из запроса.

Я оставил несколько замечаний, которые я пытался прокомментировать в разделе.

По сути, запрос, который выполняет вставку / обновление, вложен в другой, который находится внутри post_assert. Мне нужно значение iresults.insertId для только что подготовленных пользователей и результат результатов [0] .nid из запроса первого уровня, который будет сохранен в массиве cookieData.

Сейчас я получаю остальные файлы cookie (firstName, lastName, username, email, wwwid, country и geo, но из-за моей жизни не могу получить свойство cookieData.userid, которое будет добавлено до него отправляется обратно в браузер.

Это API-интерфейс expressJS REST, который отправляет данные обратно в приложение VueJS.

Я пробовал обратные вызовы, а также глобальные переменные, но, похоже, ничто не добавляет новое значение в массив.

sp.post_assert(idp, options, function (err, saml_response) {
        if (err)
            res.redirect('https://www.example.com/');
        var sessionID = saml_response.response_header.id;
        setCookie(res, req, sessionID);
        var refererLocation = req.cookies.referLocation;
        // Set User Data Variables
        const firstName = saml_response.user.attributes.givenName;
        const middleName = null;
        const lastName = saml_response.user.attributes.sn;
        const username = saml_response.user.attributes.uid;
        const email = saml_response.user.attributes.mail;
        const wwid = saml_response.user.attributes.employeeID;
        const country = saml_response.user.attributes.country;
        const geo = saml_response.user.attributes.geographicRegion;
        /*function setCookieData(val) {
          cookieData.userid = val;
        }*/
        // let userid;
        // Check if user exists in DB
        res.locals.connection.query('SELECT * FROM users WHERE username = ?', [username], function (error, results, fields) {
          if (error) throw error;
          // Get the Current Date-Time for insertion
          const accessDateTime = new Date();
          const adtYear = accessDateTime.getFullYear();
          const adtMonth = accessDateTime.getMonth() + 1;
          const adtDay = accessDateTime.getDate();
          const adtHour = accessDateTime.getHours();
          const adtMin = accessDateTime.getMinutes();
          const adtSec = accessDateTime.getSeconds();
          const dts = `${adtYear}-${adtMonth}-${adtDay} ${adtHour}:${adtMin}:${adtSec}`;
          // let userid;
          // If results is empty, then the user who just logged in does not currently have
          // an account provisioned, so set them up an account.
          if (!(results.hasOwnProperty(0))) {
            res.locals.connection.query('INSERT INTO users SET ?', {first_name: firstName, middle_name: middleName, last_name: lastName, username: username, email: email, status: 1, created: dts, access: dts, login: dts}, function (ierror, iresults, ifields){
              if (ierror) throw ierror;
              // Set the User Data Cookie
              // res.locals.userid = iresults.insertId;
              // setUserIdValue(iresults[0].insertId);
              // res.clearCookie('UserInfo');
              // res.cookie('UserInfo', cookieData);
              // cookieData.userid=iresults[0].insertId;
              // res.cookie('UserInfo', cookieData);
              app.locals.userid = iresults[0].insertId;
            });
          // Else, the result was NOT empty, then the user already exists in the DB,
          // so just update their Access and Login DATETIME fields.
          } else {
            res.locals.connection.query('UPDATE users SET login = ?, access = ? WHERE uid = ?', [dts, dts, results[0].uid], function (ierror, iresults, ifields){
              if (ierror) throw ierror;
              // userid = results[0].uid;
              // Set the User Data Cookie
              // res.locals.userid = results[0].uid;
              // setUserIdValue(results[0].uid);
              // res.clearCookie('UserInfo');
              // res.cookie('UserInfo', cookieData);
              // cookieData.userid=results[0].uid;
              // res.cookie('UserInfo', cookieData);
              app.locals.userid = results[0].uid;
            });
          }
        });
        const cookieData = {
          firstName: firstName,
          lastName: lastName,
          username: username,
          email: email,
          wwid: wwid,
          country: country,
          geo: geo,
          userid: app.locals.userid,
        };
        res.cookie('UserInfo', cookieData);
        //Add saml ID to database with expiration date
        if (refererLocation != undefined) {
            res.clearCookie("referLocation");
            res.redirect('https://www.example.com' + refererLocation);
        } else {
            res.redirect('https://www.example.com/uri');
        }
        // Save name_id and session_index for logout
        // Note:  In practice these should be saved in the user session, not globally.
        // name_id = saml_response.user.givenName + "," + saml_response.sn;
        // session_index = saml_response.user.session_index;
        //var first = saml_response.user.attributes.givenName;
        //var last = saml_response.user.attributes.sn;
        //res.send("Hello, " + first + " " + last);
    });

РЕДАКТИРОВАТЬ (9-11-2018)

Я разбил его на наиболее простую концепцию и до сих пор не могу заставить его вернуть значение 'userid' в cookie. Даже после установки всего на ASYNC и AWAIT.

app.post('/api/v1/saml/acs', function (req, res) {
    const options = {
        request_body: req.body,
        allow_unencrypted_assertion: true
    };
    sp.post_assert(idp, options, async function (err, saml_response) {
        if (err)
            res.redirect('https://www.example.com/');
        const sessionID = saml_response.response_header.id;
        const user = saml_response.user.attributes;
        // Set User Data Variables
        const firstName = user.givenName;
        const middleName = null;
        const lastName = user.sn;
        const username = user.uid;
        const email = user.mail;
        const wwid = user.employeeID;
        const country = user.country;
        const geo = user.geographicRegion;
        app.locals.UserData = {
          firstName: firstName,
          lastName: lastName,
          username: username,
          email: email,
          wwid: wwid,
          country: country,
          geo: geo,
          // userid: '',
        };
        // Check if user exists in DB
        await res.locals.connection.query('SELECT * FROM users WHERE username = ?', [app.locals.UserData.username], async function (error, results, fields) {
          if (error) throw error;
          // Get the Current Date-Time for insertion
          const accessDateTime = new Date();
          const adtYear = accessDateTime.getFullYear();
          const adtMonth = accessDateTime.getMonth() + 1;
          const adtDay = accessDateTime.getDate();
          const adtHour = accessDateTime.getHours();
          const adtMin = accessDateTime.getMinutes();
          const adtSec = accessDateTime.getSeconds();
          const dts = `${adtYear}-${adtMonth}-${adtDay} ${adtHour}:${adtMin}:${adtSec}`;
          // If results is empty, then the user who just logged in does not currently have
          // an account provisioned, so set them up an account.
          if (!(results.hasOwnProperty(0))) {
            await res.locals.connection.query('INSERT INTO users SET ?', {first_name: app.locals.UserData.firstName, middle_name: app.locals.UserData.middleName, last_name: app.locals.UserData.lastName, username: app.locals.UserData.username, email: app.locals.UserData.email, status: 1, created: dts, access: dts, login: dts}, async function (ierror, iresults, ifields){
              if (ierror) throw ierror;
              app.locals.UserData.userid = 22;
              // app.locals.UserData.userid = iresults.insertID;
            });
          } else {
            await res.locals.connection.query('UPDATE users SET login = ?, access = ? WHERE uid = ?', [dts, dts, results[0].uid], async function (ierror, iresults, ifields){
              if (ierror) throw ierror;
              app.locals.UserData.userid = 44;
              // app.locals.UserData.userid = results[0].uid;
            });
          }
        });
        // Set User Session Cookie
        res.cookie('UserData', app.locals.UserData);
        // Set SAML Session Cookie
        setCookie(res, req, sessionID);
        // Get the referrer location
        var refererLocation = req.cookies.referLocation;
        // If it is undefined, then send the user back to where they started the Sign On process.
        if (refererLocation != undefined) {
            res.clearCookie("referLocation");
            res.redirect('https://www.example.com' + refererLocation);
        } else {
            res.redirect('https://www.example.com/uri');
        }
    });
});

Ответ на dmfay

Я полагаю, что следовал вашему совету, но он по-прежнему не возвращает свойство 'userid'.

Я добавил параметр 'next' в

app.post('/api/va/saml/acs', function (){...});

и добавил вызов 'next ()' в конце

sp.post_assert(idp, options, async function(...){
    // logic here with nested calls trying to update app.locals.UserData
    next();
});

Я также пробовал вызов 'next ()' вне post_assert, и я получаю это сообщение:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

См. Ниже обновленный код.

app.post('/api/v1/saml/acs', function (req, res, next) {
    const options = {
        request_body: req.body,
        allow_unencrypted_assertion: true
    };
    sp.post_assert(idp, options, async function (err, saml_response) {
        if (err)
            res.redirect('https://www.example.com/');
        const sessionID = saml_response.response_header.id;
        const user = saml_response.user.attributes;
        // Set User Data Variables
        const firstName = user.givenName;
        const middleName = null;
        const lastName = user.sn;
        const username = user.uid;
        const email = user.mail;
        const wwid = user.employeeID;
        const country = user.country;
        const geo = user.geographicRegion;
        app.locals.UserData = {
          firstName: firstName,
          lastName: lastName,
          username: username,
          email: email,
          wwid: wwid,
          country: country,
          geo: geo,
          // userid: '',
        };
        // Check if user exists in DB
        await res.locals.connection.query('SELECT * FROM users WHERE username = ?', [app.locals.UserData.username], async function (error, results, fields) {
          if (error) throw error;
          // Get the Current Date-Time for insertion
          const accessDateTime = new Date();
          const adtYear = accessDateTime.getFullYear();
          const adtMonth = accessDateTime.getMonth() + 1;
          const adtDay = accessDateTime.getDate();
          const adtHour = accessDateTime.getHours();
          const adtMin = accessDateTime.getMinutes();
          const adtSec = accessDateTime.getSeconds();
          const dts = `${adtYear}-${adtMonth}-${adtDay} ${adtHour}:${adtMin}:${adtSec}`;
          // If results is empty, then the user who just logged in does not currently have
          // an account provisioned, so set them up an account.
          if (!(results.hasOwnProperty(0))) {
            await res.locals.connection.query('INSERT INTO users SET ?', {first_name: app.locals.UserData.firstName, middle_name: app.locals.UserData.middleName, last_name: app.locals.UserData.lastName, username: app.locals.UserData.username, email: app.locals.UserData.email, status: 1, created: dts, access: dts, login: dts}, async function (ierror, iresults, ifields){
              if (ierror) throw ierror;
              app.locals.UserData.userid = 22;
              // app.locals.UserData.userid = iresults.insertID;
            });
          } else {
            await res.locals.connection.query('UPDATE users SET login = ?, access = ? WHERE uid = ?', [dts, dts, results[0].uid], async function (ierror, iresults, ifields){
              if (ierror) throw ierror;
              app.locals.UserData.userid = 44;
              // app.locals.UserData.userid = results[0].uid;
            });
          }
        });
        // Set User Session Cookie
        res.cookie('UserData', app.locals.UserData);
        // Set SAML Session Cookie
        setCookie(res, req, sessionID);
        // Get the referrer location
        var refererLocation = req.cookies.referLocation;
        // If it is undefined, then send the user back to where they started the Sign On process.
        if (refererLocation != undefined) {
            res.clearCookie("referLocation");
            res.redirect('https://www.example.com' + refererLocation);
        } else {
            res.redirect('https://www.example.com/uri');
        }
        next();
    });
});

Рабочий код

Спасибо DMFAY и BennetQuigley. Эта проблема была решена.

Рабочий раствор прокомментирован ниже.

app.post('/api/v1/saml/acs', function (req, res, next) {
    const options = {
        request_body: req.body,
        allow_unencrypted_assertion: true
    };
    sp.post_assert(idp, options, function (err, saml_response) {
        if (err)
            res.redirect('https://www.example.com/');
        // Get the Sessions ID
        const sessionID = saml_response.response_header.id;
        // Set the returned User Info to a Variable
        const user = saml_response.user.attributes;
        // Set the app.locals.UserData variable
        app.locals.UserData = {
          firstName: user.givenName,
          middleName: null,
          lastName: user.sn,
          username: user.uid,
          email: user.mail,
          wwid: user.employeeID,
          country: user.country,
          geo: user.geographicRegion,
        };
        // Check if user exists in DB
        res.locals.connection.query('SELECT * FROM users WHERE username = ?', [app.locals.UserData.username], function (error, results, fields) {
          if (error) throw error;
          // Get the Current Date-Time for Insert/Update of user logon history
          const accessDateTime = new Date();
          const adtYear = accessDateTime.getFullYear();
          const adtMonth = accessDateTime.getMonth() + 1;
          const adtDay = accessDateTime.getDate();
          const adtHour = accessDateTime.getHours();
          const adtMin = accessDateTime.getMinutes();
          const adtSec = accessDateTime.getSeconds();
          const dts = `${adtYear}-${adtMonth}-${adtDay} ${adtHour}:${adtMin}:${adtSec}`;
          // If results is empty, then the user who just logged in does not currently have
          // an account provisioned, so set them up an account.
          if (!(results.hasOwnProperty(0))) {
            res.locals.connection.query('INSERT INTO users SET ?', {
              first_name: app.locals.UserData.firstName,
              middle_name: app.locals.UserData.middleName,
              last_name: app.locals.UserData.lastName,
              username: app.locals.UserData.username,
              email: app.locals.UserData.email,
              status: 1,
              created: dts,
              access: dts,
              login: dts
            }, function (ierror, iresults, ifields){
              if (ierror) throw ierror;
              // set the app.locals.UserData.userid value to the newly inserted ID
              app.locals.UserData.userid = `["${iresults.insertID}"]`;
              // From here to 'next()' has to be repeated in both cases
              // 'next()' must be used to return the values and actions to the parent
              // Call.
              // Set User Session Cookie
              res.cookie('UserData', app.locals.UserData);
              // Set SAML Session Cookie
              setCookie(res, req, sessionID);
              // Get the referrer location
              var refererLocation = req.cookies.referLocation;
              // If it is undefined, then send the user back to where they started the Sign On process.
              if (refererLocation != undefined) {
                  res.clearCookie("referLocation");
                  res.redirect('https://clpstaging.mcafee.com' + refererLocation);
              } else {
                  res.redirect('https://clpstaging.mcafee.com/clp');
              }
              // Tell the callback to move forward with the actions.
              next();
            });
          } else {
            res.locals.connection.query('UPDATE users SET login = ?, access = ? WHERE uid = ?', [dts, dts, results[0].uid], function (ierror, iresults, ifields){
              if (ierror) throw ierror;
              // Set the app.locals.UserData.userid to the Users PK
              app.locals.UserData.userid = results[0].uid;
              // From here to 'next()' has to be repeated in both cases
              // 'next()' must be used to return the values and actions to the parent
              // Call.
              // Set User Session Cookie
              res.cookie('UserData', app.locals.UserData);
              // Set SAML Session Cookie
              setCookie(res, req, sessionID);
              // Get the referrer location
              var refererLocation = req.cookies.referLocation;
              // If it is undefined, then send the user back to where they started the Sign On process.
              if (refererLocation != undefined) {
                  res.clearCookie("referLocation");
                  res.redirect('https://www.example.com' + refererLocation);
              } else {
                  res.redirect('https://www.example.com/uri');
              }
              // Tell the callback to move forward with the actions.
              next();
            });
          }
        });
    });
});

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Как сказал dmfay, post_assert завершает и устанавливает cookie, прежде чем запрос сможет завершиться, и устанавливает поле userid.

Лучший способ, который я нашел для решения подобных проблем, - это использовать Обещания .

Из документации Google по Обещаниям:

var promise = new Promise(function(resolve, reject) {
  // query the database to get the user id

  if (/* everything turned out fine */) {
    resolve("Stuff worked!"); //resolve (return) the user id here
  }
  else {
    reject(Error("It broke"));
  }
});

И тогда вы захотите использовать то, что возвращает Обещание.

promise.then(function(result) {
  console.log(result); // Set the cookie with the user id here
}, function(err) {
  console.log(err); // Error
});
0 голосов
/ 11 сентября 2018

Ваш обратный вызов post_assert является асинхронным, а обратный вызов маршрута - нет, поэтому логика маршрута завершается до завершения обратного вызова post_assert.Вероятно, вам проще всего использовать Express с использованием подписи app.post(url, function (req, res, next) {...}) и вызывать next() в качестве последнего шага в обратном вызове post_assert после того, как вы закончили писать cookie и настраивать перенаправление.

...