Catching dialog name before being routed - middleware - node.js

I have a bot built with MS bot framework, using a library structure.
I'm trying to catch the dialog name + library of a message, before it is being routed to the dialog. (for analytics purposes)
Is there a middleware that can help me do that?
I tried the routing middleware of the UniversalBot, but it seems be running just before a dialog was choosen.

One possible option here could be using the ISessionMiddleware.
botbuilder: function (session, next) {
console.log(session.message.text);
next();
}
This will allow you to have access to the session. This will execute once a message is bound to a particular session and gives the option of looking at a message and the state of the session (where user is in available dialogs, etc) then making a decision of how to proceed.

It seems like bot.onDisambiguateRoute is the solution.
The var route contains the route name/library in that case, and has also the dialog arguments besides that. see the docs for more info
example code:
bot.onDisambiguateRoute(function (session, routes) {
// Route message as normal
var route = builder.Library.bestRouteResult(routes, session.dialogStack(), bot.name);
// *** log route
if (route) {
bot.library(route.libraryName).selectRoute(session, route);
} else {
// Just let the active dialog process the message
session.routeToActiveDialog();
}
}
});

Related

In node.js with express, is there a way of changing the url of a link on the fly?

I have a link on a page:
Back
which of course takes the user to '/application-reference'. However, if the session has timed out, I want the user to taken to '/session-ended' instead. Session timed out is detected by the absence of request.session.
I've tried changing the href to send the user back to the same page (i.e. the link is in 'security-code' and takes the user to 'security-code') with the idea that the handling code can look for request.session and decide which page to redirect to, only I can find no way for the code to detect that the page has been called by itself via the back button.
I think the answer is to put something in my express module so that the router.get call that redirects to '/application-reference' will under the right circumstances redirect to '/session-ended'. But I have no idea how to go about this.
I suppose the ideal would be for the '/session-ended' screen to be invoked any time the user clicks on any screen once the session has timed out.
Any suggestions?
Inside your /application-reference-handler you could check if the session on the req-object is still valid. If not redirect the request to /session-ended:
app.get('/application-reference', (req, res) => {
if(!req.session) { // or a more detailed check for the session's validity
return res.redirect("/session-ended");
}
// rest of the handler-code ...
});
An better way to do this is to define a separate middleware to check the user's session - this allows you to reuse this middleware and not having to duplicate the check in your handlers:
function validateSession(req,res,next) {
if(!req.session) { // or a more detailed check for the session's validity
return res.redirect("/session-ended");
}
// all is good, go to the next middleware
next();
});
app.get('/application-reference', validateSession, (req, res) => { ... });

How to send data with redirect back in Express JS

Hello I am new to NodeJs. Currently I am working in node with Express framework.
I installed the express-back package in my project and now I want to send send back data to view from where post request fired.
Below is my code that I write:
routes.js
router.post('/register/user',Rules.UserRules.registerUser,UserController.registerUser)
UserController.js
const {check, validationResult} = require('express-validator');
registerUser = function (req, res, next) {
// Validate request parameters, queries using express-validator
const errors = validationResult(req)
console.log("==== errors ===")
console.log(errors.array())
if (!errors.isEmpty()) {
console.log("==== erorror founded ====")
return res.redirect('/signup',{errors:errors})
}else{
console.log('--- form body ----')
console.log(req.body)
}
}
module.exports = {registerUser}
When I submit my form to this route then control moves to UserController and I validations fails then I want to send it back to view without defining the redirect path I just want to send it back to view from where request received with errors. But I did not find any useful solution yet.
Is there any idea that how I can achieve this target. Suggest any useful link for nodejs beginner.
use res.send(errors) it send errors to client at this route. but if you want to redirect it to another route and then send it to client you have to create /signup route and use res.send(errors) it send errors to client. by default ``` res```` will redirect to redirected route.
router.post('/signup', (req, res)=>{
//send error or do somethings.
res.json(req.body.errors);
})
Use
app.locals.errors=errors
to make your error variable available to your template upon redirection as a general guide. Read more at http://expressjs.com/en/5x/api.html#app.locals. Remember, this will share the error variable across the application, so do not forget to apply logic that allows only the logged in user to view the error information relevant to that user.

How to access 'session.conversationData' while intercepting 'send' hook from middleware?

I have been following the official guidelines while trying to intercept user/bot messages.
bot.use({
botbuilder (session, next) {
logger.info("MESSAGE RECEIVED:" + session.message.text);
next();
},
send (event, next) {
logger.info("MESSAGE SENT:" + event.text);
next();
}
});
While botbuilder hook behaves as expected, send is never called.
At the moment when i will be able to solve this issue, my goal is to have
access to the session object, more precisely to the session.conversationData storage container from the send method middleware.
What have i done ?
i have been following the Logging middleware example and the readme states:
The botbuilder hook on the middleware is an example of ISessionMiddleware. The main advantage of using this hook instead of receive is the access we gain to the session.
and
send and receive hooks use IEventMiddleware. The first argument is the event itself. To see whether an event is a message, check to see if event.type is 'message'.
Currently i have wrapped the session.send in a custom function so i can log the messages which are send by the bot, and another function which logs the user response from inside the dialog. While this solution solves my problem it feels bad ( need to manually update each dialog ) and i am not able to create a generic middleware which could be loaded from a module.
What am i trying to achieve ?
The purpose of my middleware is to intercept user/bot messages and log them to SQL table with the following schema : conversation-id, message-text, timestamp.
conversation-id is stored in session.conversationData storage container, thus why i need to get access to session object from the send hook.
using "botbuilder": "^3.13.1"
You can load the session within the send by calling loadSessionWithoutDispatching:
send: function (message, next) {
bot.loadSessionWithoutDispatching(message.address,function (error,session){
console.log(session.userData);
});
next();
}

Express middleware and parameter handling ordering on route

So I am running some API tests and I noticed that one test is failing because it is running some parameter handling logic before middleware, now here is an example of the route definition:
app.post("/something/:some_param",
middlewareA, middlewareB, middlewareC,
function(req, res) {
// Do stuff
});
Now I assumed (wrongly I think) that middleware would be invoked first then it would handle the parameter handler for :some_param however it seems to be the other way around. (by parameter handler I mean app.param())
Problem I have here is that if the above is correct and parameter handlers are run first, some of the logic within the parameter handler assumes the user is logged in already and blows up if they are not, and middlewareA handles user authentication and if they are not logged in redirects them etc, so ideally I would want middlewareA to be called first, so is there a way to achieve this ordering?
The only way I could see this working would be if the parameter handler could utilize middleware but there is no documentation on the API docs on this subject, so is there any best practice to handle this sort of scenario? as I do not want to have to shoe horn my middlewareA logic into my :some-param handling logic as I also have many other :other-param handlers etc which would also need this authentication (and other) middleware run before they run.
Yes, param handlers run before middleware. You can deal with this by either:
recoding your param handler as a middleware. There's not that much difference between the 2 mechanisms.
OR, in your param handler, just run the desired middleware directly as below:
.
function someParam(req, res, next, paramValue) {
myAuthMiddleware(req, res, function (error, result) {
if (error) {
next(error);
return;
}
//Here the user will be logged in
// do what you need to do with req and paramValue
next();
});
}

How can I stop a user from accessing another route in a single page app directly in Backbone and Nodejs?

I am building an app that requires a login which if successful, passes you off to another page called events. However, Backbone works with the hash in the URL bar, therefore, the request that someone accessed that page is never sent to NodeJs Server.
The thing is, someone without login can access the page by just typing in http://www.mywebsite.com/#events
How can this be prevented?
Overwrite the 'execute' function in the backbone router.
From the docs:
router.execute(callback, args)
This method is called internally within the router, whenever a route
matches and its corresponding callback is about to be executed.
Override it to perform custom parsing or wrapping of your routes, for
example, to parse query strings before handing them to your route
callback, like so:
So, for example: (http://plnkr.co/edit/BqD4YfjQYz2RITWNhBKZ?p=preview)
var Router = Backbone.Router.extend({
execute: function(callback, args) {
if(!someLoginFunctionCheck()) {
this.navigate('#')
} else {
if (callback) callback.apply(this, args);
}
}
});

Resources