Handling command access

We've set up a bot. We've chosen which users are allowed which level of access. We've set the access levels of the commands which we are going to handle (& maybe some that we will get around to). Now all that we have to do is receive a command, check whether the user can run it & then actually run it! Let's start with the middle part :)

I have a lot of commands!

That fan of lines to the left shows all of the commands that might come in from my bot. The fan of lines on the left leads to quite a large set of nodes which actually execute the commands. I'll run through some of the principles for that in a while...

For now let's work through the process for an incoming (& recognised) telegram bot command. The first thing that happens is that everything passes through the first change node. It's set up like this

msg.topic= select Permission from command WHERE command = 
then the second rule is
msg.topic & "'" &  msg.originalMessage.text & "'"

So by the end of this the msg.topic is an instruction to find the permission level from the command table in the database which matches the original bot command. If you look back at the command table setup post you'll see that the example there used "/services" as the command that we were adding, so if this command was sent to the bot then the change node would be constructing a query to find the permission level for the /Services command. Note the addition of  single (') quotes as part of the query.
We pass the query to the database node & then handle the output using another change node. This copies the permission level that we received to  msg.commandpermission so that is doesn't get overwritten. Then it sets up a query of the database to find the permission level of the user (chatId) who sent the command.

"select Permission from users WHERE chatId = "  &  msg.originalMessage.from.id

We pass that through the database node (to find the user's permission level) & then arrive at the function node where a decision is made about whether this user can execute this command. The content of the function node is

//msg.result16 = msg.payload[0].Permission & 16;
msg.userpermission = msg.payload[0].Permission;
msg.result = msg.commandpermission & msg.payload[0].Permission;

//if (msg.commandpermission & msg.payload[0].Permission > 0){
if (msg.result > 0){
    msg.payload={};
    msg.payload.chatId = msg.originalMessage.chat.id;
    return[msg, null];
}
    else {
    return [null, msg];
}
return msg;

.Remember that comment about binary bits being set? We've got the user 's permission  & the command permission that we saved earlier on. If we "&" them together then what happens is we compare the permission level bits of the command with the permission level of the user. If both have the bit set (i.e. a value of 1) then the "&" will contain a 1, if they don't match then the result for that bit is a 0.
Which means that we can simply test for a non-zero result in order to see if the user's level was greater than or equal to the command's required permission. (I chose to set all of the bits up to the user's level to 1 in order to make this bit easy. I told you that this wasn't a perfect or carefully optimised design - it does work though :))
If the user is allowed to execute the command then the flow exits through the first (top) output connection, otherwise it goes out of the 2nd (lower) one - i.e. for "permission denied" handling. I just ditch these (into a debug node, in case I want to see them).

The last step is to pass the commands to the nodered flow that handles them. That's where the switch node comes in. Configure it to match the commands to the output & then link the output to the flow that the command initiates. The command that was originally received is held in msg.originalMessage.text.
As you can see from the picture at the top & the one below I have a catchall output, just in case.