Skip to content
This repository has been archived by the owner on Sep 24, 2020. It is now read-only.

Commit

Permalink
Added more explanatory comments throughout the codebase
Browse files Browse the repository at this point in the history
  • Loading branch information
barnesjt committed May 15, 2020
1 parent 4e83707 commit 8d7df99
Show file tree
Hide file tree
Showing 13 changed files with 84 additions and 30 deletions.
3 changes: 3 additions & 0 deletions chatbot/bot.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ controller.ready(() => {
}
});

// If any pages need to be served by the application, they would be below:

// This is a route added by the Bot Framework template.
controller.webserver.get('/', (req, res) => {
res.send(`This app is running Botkit ${ controller.version }.`);
});
Expand Down
4 changes: 4 additions & 0 deletions chatbot/features/bot_local_commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ const usage = require('./lib/usage');
const logGroup = 'NitroChatbot';
const auth_log_lib = require('./util/cwlogs')(logGroup);

//Each of these events below match potential events that may be triggered by the user.
//This file contains commands that do not need to query the Relay.
//Each event matches a support command with a regex.
module.exports = function (controller) {

//help : Shows usage text
Expand All @@ -28,6 +31,7 @@ module.exports = function (controller) {
} catch (e) {
await bot.reply(message, "Error: " + e);
}
//Sends a log message to the log stream "RequestedAuths" with the following object format:
auth_log_lib.send('RequestedAuths' ,{
"ATTENTION": cmd.command,
"Name": usr.name,
Expand Down
9 changes: 9 additions & 0 deletions chatbot/features/bot_relay_commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ const relayUrl = process.env.RELAY_URL;

const http_relay = require('./util/http_relay')(relayUrl, totpKey);

//This file contains message event triggers that match all commands that require communication with the relay.

//Each event contains the following ordered operations:
//get_user parses the user information out of the message
//make_cmd verifies and parses the message text into the object the relay expects
//http_relay makes the request to the relay, logs the result if the relay is contacted, and the event awaits the async function
//bot.reply send the result to the user, using the pp (prettyprint) function to create a string that will display nicely in teams
//the whole thing is contained in a try catch block, if any function has an error, it will throw it and instead send the thrown string to the user prepended by "Error:"

module.exports = function(controller) {

//listall : List all resources
Expand Down
3 changes: 2 additions & 1 deletion chatbot/features/bot_unmatched_commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

module.exports = function(controller) {

//Catch all event for unmatched messages from user
//Catch-all event for unmatched messages from user
//This will display a generic error message to the user, suggesting they instead view the usage text with "help".
controller.hears(async (message) => message.text, ['message', 'direct_message'], async (bot, message) => {
await bot.reply(message, 'Error: Command not recognized. Try again or type "help" to see the full usage text.');
});
Expand Down
2 changes: 1 addition & 1 deletion chatbot/features/util/cwlogs.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ module.exports = (group) => {
}
});
},
/* This is specialized for our use case, it will generate objects in a standard format.
/* This is specialized for our use case (reponses from our relay), it will generate objects in a standard format.
*/
make: (request, res) => {
return {
Expand Down
16 changes: 16 additions & 0 deletions relay/lib/nitro/nitro.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,23 @@ module.exports = (baseURL, token) => {
//Relay must use try-catch blocks to catch errors (as NitroError objects),
//Which are then passed with next(NitroError) to our error case within the relay
//Each function here matches a route within the relay

//This passes through a couple levels: nitroUtil.js -> nitro_list.js
listVServers: async () => {
var results = await nitroUtil.vServerListAllNames(baseURL, token);
return results;
},

//This passes through to nitroUtil -> nitro_list_all.js
listAllResources: async() => {
var results = await nitroUtil.resourcesListAll(baseURL, token);
return results;
},

//Uses the find resource function, then calls a different internal function based on the type of resource
//If the resource name isn't matched, an error is thrown and the error route will grab it
//If the resource is a server (which cannot have bound resources), then the nitro error is generated and throw here
// Which is then grabbed by the error route
listBoundResourcesByName: async (resource) => {
var search = await nitroUtil.findResource(baseURL, token, resource);
switch(search.type) {
Expand All @@ -36,6 +45,8 @@ module.exports = (baseURL, token) => {
});
}
},
//As with the previous function, the resource is searched for (if not found an error is thrown)
// If successful, a different internal function is called based on the resource type.
getResourceStatusByName: async (resource) => {
var search = await nitroUtil.findResource(baseURL, token, resource);
switch(search.type) {
Expand All @@ -53,6 +64,8 @@ module.exports = (baseURL, token) => {
return results;
}
},
//As with the previous function, the resource is searched for (if not found an error is thrown)
// If successful, a different internal function is called based on the resource type.
enableResourceByName: async (resource) => {
search = await nitroUtil.findResource(baseURL, token, resource);
switch(search.type){
Expand All @@ -70,6 +83,9 @@ module.exports = (baseURL, token) => {
return results;
}
},
//As with the previous function, the resource is searched for (if not found an error is thrown)
// If successful, a different internal function is called based on the resource type.
// This will pass a delay to function if it can accept one
disableResourceByName: async (resource, delay, graceful) => {
search = await nitroUtil.findResource(baseURL, token, resource);
switch(search.type){
Expand Down
15 changes: 15 additions & 0 deletions relay/lib/nitro/nitro_util.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,23 @@ module.exports = {
}
});
},
//This is passed through to the nitro_list.js file
vServerListAllNames: async(baseURL, token) => {
return await nitroList.vServerListAllNames(baseURL,token);
},
//This is passed through to the nitro_list.js file
serviceGroupListAllNames: async(baseURL, token) => {
return await nitroList.serviceGroupListAllNames(baseURL,token);
},
//This is passed through to the nitro_list.js file
serviceListAllNames: async(baseURL, token) => {
return await nitroList.serviceListAllNames(baseURL,token);
},
//This is passed through to the nitro_list.js file
serverListAllNames: async(baseURL, token) => {
return await nitroList.serverListAllNames(baseURL,token);
},
//Accepts a vServer name, parses bound entities and returns them
listVServerBoundEntities: async(baseURL, token, vServer) => {
let output = {};
let url = baseURL+"/nitro/v1/config/lbvserver_binding/"+vServer;
Expand All @@ -62,6 +67,7 @@ module.exports = {
if(output instanceof NitroError) throw output;
else return output;
},
//Accepts a servicegroup name, parses bound entities and returns them
listServiceGroupBoundEntities: async(baseURL, token, serviceGroup) => {
let output = {};
let url = baseURL+"/nitro/v1/config/servicegroup_binding/"+serviceGroup;
Expand All @@ -81,6 +87,7 @@ module.exports = {
if(output instanceof NitroError) throw output;
else return output;
},
//Accepts a service name, parses bound entities and returns them
listServiceBoundEntity: async(baseURL, token, service) => {
let output = {};
let url = baseURL+"/nitro/v1/config/service/"+service;
Expand All @@ -98,6 +105,8 @@ module.exports = {
if(output instanceof NitroError) throw output;
else return output;
},
//Accepts a vServer name, queries for specific stats.
//To modify the stats returned, add to the url variable and the output object (The frontend will display whatever you send it)
vServerListStats: async (baseURL, token, vServer) => {
let output = {};
let url = baseURL+"/nitro/v1/config/lbvserver/"+vServer+"?attrs=name,ipv46,port,curstate,effectivestate,totalservices,activeservices";
Expand All @@ -122,6 +131,8 @@ module.exports = {
if(output instanceof NitroError) throw output;
else return output;
},
//Accepts a servicegroup name, queries for specific stats.
//To modify the stats returned, add to the url variable and the output object (The frontend will display whatever you send it)
serviceGroupListStats: async(baseURL, token, serviceGroup) => {
let output = {};
let url = baseURL+"/nitro/v1/config/servicegroup/"+serviceGroup+"?attrs=servicegroupname,numofconnections,state";
Expand All @@ -143,6 +154,8 @@ module.exports = {
if(output instanceof NitroError) throw output;
else return output;
},
//Accepts a service name, queries for specific stats.
//To modify the stats returned, add to the url variable and the output object (The frontend will display whatever you send it)
serviceListStats: async(baseURL, token, service) => {
let output = {};
let url = baseURL+"/nitro/v1/config/service/"+service+"?args=internal:false&attrs=name,numofconnections,servername,ipaddress,port,svrstate";
Expand All @@ -167,6 +180,8 @@ module.exports = {
if(output instanceof NitroError) throw output;
else return output;
},
//Accepts a server name, queries for specific stats.
//To modify the stats returned, add to the url variable and the output object (The frontend will display whatever you send it)
serverListStats: async(baseURL, token, server) => {
let output = {};
let url = baseURL+"/nitro/v1/config/server/"+server+"?args=internal:false&attrs=name,ipaddress,state";
Expand Down
3 changes: 3 additions & 0 deletions relay/lib/nitro_login_mw.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

nitroLogin = require("./nitro_login");

//This middleware uses the nitro_login file, which returns an instance of nitro, which has been logged into the server.
// This internally maintains the token needed for further requests, However the object is destroyed after a response is sent to the user.
// This is to avoid saving any credentials locally, also removeing the need to handle credentials at the top level.
module.exports = async (req, res, next) => {
var url = req.auth.url;
var username = req.auth.username;
Expand Down
1 change: 0 additions & 1 deletion relay/mw/auth/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ sm = require('./auth_aws_sm');
module.exports = {
getCreds: async(id) => {
var creds;
//creds = await csvparser(id);
creds = await sm(id);
return creds;
}
Expand Down
8 changes: 8 additions & 0 deletions relay/mw/auth/auth_aws_sm.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ var client = new AWS.SecretsManager({
region: region
});

//This file uses the AWS SDK to query secrets manager for the stored keyvalue pairs that correspond to the user ID.
//If the id doesn't exist, the string "Unauthorized" is thrown, eventually caught and sent to the user.

module.exports = async (id) => {
//The secrets are stored by unique user ID
secretName = id;
var secret;
await client.getSecretValue({SecretId: secretName}, async (err, data) => {
Expand All @@ -21,12 +25,16 @@ module.exports = async (id) => {
else if(err.code === 'ResourceNotFoundException') throw "Unauthorized"
} else {
if('SecretString' in data) {
//This sets the secret variable as the value we retrieved from SecretsManager
secret = data.SecretString;
} else {
//This won't trigger with our current setup, but it is part of the SDK template given by AWS
let buff = new Buffer(data.SecretBinary, 'base64');
decodedBinarySecret = buff.toString('ascii');
}
}
}).promise(); //transforms AWS.Request into a promise so we can use await

//Return the secret, making sure it's parsed into a JSON object.
return JSON.parse(secret);
}
27 changes: 0 additions & 27 deletions relay/mw/auth/auth_csv.js

This file was deleted.

3 changes: 3 additions & 0 deletions relay/mw/auth/auth_mw.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
auth = require('./auth');

//This file is used at a middleware by express in relay.js
// Internally, this relies on auth.js (which in turn can use whatever method to retrieve credentials)
module.exports = async (req, res, next) => {
body = JSON.parse(JSON.stringify(req.body));
//Need to check that id is of the exactly format with a regex.
Expand All @@ -20,6 +22,7 @@ module.exports = async (req, res, next) => {
});
}
} else {
//If the initial request is malformed, we'll immediately send a response to the frontend
res.status(400).send({
error: {
status: 400,
Expand Down
20 changes: 20 additions & 0 deletions relay/relay.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,25 @@ app.use(bodyParser.json());

//auth_mw places 3 properties in req.auth: url, username, password
app.use(auth_mw);

//This middleware tests our totp password (generated from the shared symmetric key).
//If the totp password is invalid or missing, the request is immeditaely responded to and it will never hit the routes below
app.use(totp_test_mw(process.env.TOTP_KEY, 1));

//If the request makes it this far, it will attempt to log into Nitro.
//This middleware will leave a Nitro object in the request at req.nitro
app.use(nitro_login_mw);

//Each of the express routes below follows the same pattern:
// gather the body as a JSON
// Use the nitro object to make the matching request
// If it throws an error, pass the error to the error handler
// Otherwise send the result as the response body with 200 (OK) at the status

//Note: All request logic is contained within the Nitro object library,
// This is to keep the file clean and readable.
// See /lib/nitro/nitro.js to view individual route logic (Also this is where to add more nitro commands for future expansion)

//POST /api/listall
app.post('/api/listall', validate({body: schema.api_listall_schema}), async (req, res, next) => {
var body = JSON.parse(JSON.stringify(req.body));
Expand Down Expand Up @@ -125,8 +141,11 @@ app.use( (err, req, res, next) => {
}
};
res.status(400).send(responseData);
//If the error is an instance of Nitro Error, we know the error came from our nitro object
// As such, it has these specific fields to populate the status code and response body
} else if (err instanceof NitroError) {
res.status(err.status).send({"error":err})
//Otherwise something else happened, shouldn't be hitting this block, but it's here anyways
} else {
next(err); //pass error if not matched
}
Expand All @@ -140,4 +159,5 @@ app.use('*', (req, res) => {
}
});
});
//Start the relay
app.listen(port, () => console.log(`Relay listening on port ${port}!`));

0 comments on commit 8d7df99

Please sign in to comment.