How to Add API Key to Usage Plan in AWS API Getaway - aws-sdk

I have a problem with creating API Key associated with an Usage Plan in AWS API Getaway (using AWS SDK for node.js).
In AWS Console you can attach API Key to Usage Plan via this button:
However I could not find a similar function in AWS SDK documentation

This code do the magic:
var params = {
keyId: 'STRING_VALUE', /* required */
keyType: 'STRING_VALUE', /* required */
usagePlanId: 'STRING_VALUE' /* required */
};
apigateway.createUsagePlanKey(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
What I was missing was that keyType must be "API_KEY"

This is a full example of creating an API Key and assigning it to a usage plan.
async function createApiKey(apikey_name, usage_plan="free") {
const usage_plans = {
free: "kotc0f", // usage plan IDs
basic: "ju5fea"
};
if (!usage_plan || !(usage_plan in usage_plans)) {
console.log(usage_plan + " usage plan does not exist");
return false;
}
var params = {
name: apikey_name,
description: "Created via API on " + (new Date).toISOString(),
enabled: true,
generateDistinctId: true
};
let api_key = await new Promise((resolve) => {
apigateway.createApiKey(params, function (err, data) {
if (err) {
console.log("ERROR", err, err.stack); // an error occurred
resolve(false);
}
else {
resolve(data);
}
});
});
if (!api_key) return false;
params = {
keyId: api_key.id,
keyType: "API_KEY",
usagePlanId: usage_plans[usage_plan]
};
await new Promise((resolve) => {
apigateway.createUsagePlanKey(params, function(err, data) {
if (err) {
console.log(err, err.stack); // an error occurred
resolve(false);
}
else {
resolve(data);
}
});
});
return api_key;
}

Related

MySQL Transactions in Node

Before I commit anything to the database, I want all my update promises resolve; otherwise, I rollback. In other words, I want atomicity. I suppose I could handle the rollback by deleting out rows, but this has its own risks. I noticed if there is an error in any of the promises, the data still gets updated in database. What am I doing wrong?
I have written a simple program to illustrate the issue.
This is the main process:
const db = require('./db.js');
const async = require('async');
let insertList = [];
for (let i = 0; i<3; i++) {
insertList.push(i);
}
async function func1 () {
return new Promise((resolve, reject) => {
console.log("In Func1");
async.forEachOf(insertList, function(value, key, callback) {
console.log('>>>>' + value + '<<<<<<' + key );
db.insertOne('coll1', {value}).then(() => {
callback();
}).catch(err => {callback(err)})
}, function(err) {
// if any of the file processing produced an error, err would equal that error
if( err ) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('err:', err);
reject(err);
} else {
console.log('Col1 All inserts have been processed successfully');
resolve("Success");
}
});
})
}
function func2 () {
return new Promise((resolve, reject) => {
console.log("In Func2");
async.forEachOf(insertList, function(value, key, callback) {
console.log('>>>>' + value + '<<<<<<' + key );
db.insertOne('coll2', {value}).then(() => {
callback();
}).catch(err => {callback(err)})
}, function(err) {
// if any of the file processing produced an error, err would equal that error
if( err ) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('err:', err);
reject(err);
} else {
console.log('Col2 All inserts have been processed successfully');
resolve("Success");
}
});
})
}
function func3 () {
return new Promise((resolve, reject) => {
console.log("In Func3");
async.forEachOf(insertList, function(value, key, callback) {
console.log('>>>>' + value + '<<<<<<' + key );
if(key === 1) {
value = 'a';
}
db.insertOne('coll3', {value}).then(() => {
callback();
}).catch(err => {callback(err)})
}, function(err) {
// if any of the file processing produced an error, err would equal that error
if( err ) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('err:', err);
reject(err);
} else {
console.log('Col3 All inserts have been processed successfully');
resolve("Success");
}
});
})
}
db.connect().then((pool) => {
pool.getConnection((err, connection) =>{
if (err)
return console.error(err);
else {
}
connection.beginTransaction((err) => {
if (err) {
return console.error(err);
}
let func1Promise = new Promise((resolve, reject) => {func1().then(() => {
console.log("Func1 complete");
resolve("Func1 complete");
}).catch((err) => {
console.error("Func1 ERROR: ", err);
reject("Func1 ERROR: ", err);
})});
let func2Promise = new Promise((resolve, reject) => {func2().then(() => {
console.log("Func2 complete");
resolve("Func2 complete");
}).catch((err) => {
console.error("Func2 ERROR: ", err);
reject("Func2 ERROR: ", err);
})});
let func3Promise = new Promise((resolve, reject) => {func3().then(() => {
console.log("Func3 complete");
resolve("Func3 complete");
}).catch((err) => {
console.error("Func3 ERROR: ", err);
reject("Func3 ERROR: ", err);
})});
Promise.all([func1Promise, func2Promise, func3Promise])
.then(()=> {
console.log("All Processes completed successfully.");
connection.commit(err => {
if (err) {
connection.rollback(() => {
throw err;
});
}
console.log('Commit Complete.');
connection.release();
});
})
.catch((err)=> {
console.error(err);
console.error("An update process has failed.");
connection.rollback(() => {
console.error(err);
connection.release();
});
})
});
})
});
The db.js looks like this:
const mysql = require('mysql');
const config = {
db: {
host: 'localhost',
user: process.env.DBUSER,
password: process.env.DBPASSWORD,
database: 'test',
}
};
var pool;
class DB {
constructor(host, user, password, database) {
this.host = host;
this.user = user;
this.password = password;
this.database = database;
}
connect() {
return new Promise((resolve, reject) => {
pool = mysql.createPool({
connectionLimit: 10,
host : this.host,
user : this.user,
password : this.password,
database : this.database
});
resolve(pool);
});
}
objToArray(obj) {
let arr = obj instanceof Array;
return (arr ? obj : Object.keys(obj)).map((i) => {
let val = arr ? i : obj[i];
if(typeof val === 'object' && val !== null)
return this.objToArray(val);
else
return val;
});
}
insertOne(collection, insertObj) {
return new Promise((resolve, reject) => {
pool.getConnection((err, connection) => {
if (err) {
resolve(err);
} else {
let sql = "INSERT INTO " + collection + " VALUES (?)";
// Convert the array of objects into an array of arrays.
let responseJson = this.objToArray(insertObj);
// The query object expects an array of objects so you pass in 'responseJson' as is
console.log(responseJson);
connection.query(sql, [responseJson], (err, result) => {
if (err) {
console.error(err);
return reject(err);
}
//console.log(result);
resolve("SUCCESS: object inserted into database");
});
}
});
});
}
}
const db = new DB(config.db.host, config.db.user, config.db.password, config.db.database);
Object.freeze(db);
module.exports = db;
My database "test" is simple and consists of 3 tables, coll1, coll2, coll3 and each has on field which is type int. In the third function I replace the 1 with 'a' This causes an error and the code catches this error and attempts a rollback, which does not work. If I set a breakpoint after func1 is executed and check the database, the values are already in the database.
Here is the version of MySQL that I am running:
Variable_name,Value
innodb_version,8.0.11
protocol_version,10
slave_type_conversions,
tls_version,"TLSv1,TLSv1.1,TLSv1.2"
version,8.0.11
version_comment,"MySQL Community Server - GPL"
version_compile_machine,x86_64
version_compile_os,macos10.13
version_compile_zlib,1.2.11
I am using the following NPM packages in node:
"async": "^2.6.2",
"mysql": "^2.15.0"
You're creating a transaction on a connection created in your test program, but your db.js's insertOne is grabbing a new connection from the pool that does not have a transaction. You should be passing in the connection you created in the test program.

Error POST http:abc/ 404 (Not Found) in angular2+ and nodejs

I am making a http request from my angular2+ code to database present in node.js file. The ajax call from angular2+ hits the controller.js file and then redirects to service.js file which has the connection to the database:
angular.ts ==> controller.js ==> service.js
From the database the service.js file gives the output to controller.js file and then answers the ajax call to angular.ts file:
service.js ==> controller.js ==> angular.ts
However, I am getting the error:
POST http://localhost:8096/dashboard/abcEntireSuccess1/ 404 (Not Found)
UPDATED
Cannot GET /dashboard/experianEntireSuccess1/
And one more issue -
UnauthorizedError: No authorization token was found
And one more issue -
After coming back from the hit in service.js which has the data i want ==> to => controller.js , here the data is acquired is undefined. As seen below -
The output on Nodejs -
output -
service.js
closed connection
yessss [ RowDataPacket { ....
controller.js
we are coming back to controller undefined
some error occured of abcEntireSuccess1
My Entire Code:
UPDATED
abc.component.ts
viewAbcEntireSuccess1() {
var url = config.url;
var port = config.port;
this.http.post("http://" + url + ":" + port + "/dashboard
/abcEntireSuccess1/", this.emptyObj
, { headers: new Headers({ 'Authorization': 'Bearer ' +
localStorage.getItem('Token') }) })
.map(resultConnection => this.resultConnection =
resultConnection.json(), )
.subscribe((res: Response) => {
this.records = res;
this.resultConnectionlength = this.resultConnection.length;
});
}
abc.controller.js
router.post('/experianEntireSuccess1',experianEntireSuccess1);
module.exports = router;
function abcEntireSuccess1(req, res) {
dashboardService.abcEntireSuccess1(req.body)
.then(function (result) {
console.log("we are coming back to controller",result)
if (result.length > 0) {
console.log("we get data in node of abcEntireSuccess1 ::
" + Object.values(result));
console.log(result.length + " record found ");
res.send(result);
}
else {
result=[];
res.send(result);
}
})
.catch(function (err) {
res.status(400).send(err);
console.log("some error occured of abcEntireSuccess1");
});
}
abc.service.js
async function abcEntireSuccess1() {
console.log("function called")
const db = new Database();
await db.query(`select * from TRANSACTION_PAYLOAD where INTERFACE_NAME
= 'Abc' AND (STATUS ='SUCCESS_RESPONSE')`
).then(rows => {
console.log("closed connection");
console.log("yessss",rows)
return rows;
});
};
class Database {
constructor() {
this.connection = mysql.createConnection({
host: "127.0.0.1",
user: "abc",
password: "abc",
database: "DB"
});
}
query(sql, args) {
console.log("sql is", sql)
return new Promise((resolve, reject) => {
this.connection.query(sql, (err, rows) => {
console.log("connection function called")
if (err) {
console.log("error is", err)
return reject(err);
}
console.log("rows are",rows);
resolve(rows);
});
});
}
close() {
console.log("calling connection close")
return new Promise((resolve, reject) => {
console.log("called connection close")
this.connection.end(err => {
if (err){
return reject(err);
}
resolve();
});
});
}
}

Node Js Query MySql Before Sending Notification in Firebase

Please how do I Query MySql and wait for result before sending notification to device. Here is my code
exports.pushNotification = functions.database
.ref("/messages")
.onWrite((change, context) => {
console.log("Push notification event triggered");
const payload = {
notification: {
title: "Test Message",
body: "Welcome to Node",
sound: "default"
},
data: {
title: "Test Message",
message: "Welcome to Node"
}
};
/* Create an options object that contains the time to live for the notification and the priority. */
const options = {
priority: "high",
timeToLive: 60 * 60 * 24 //24 hours
};
var token = new Promise(function(resolve, reject) {
con.connect(function(err) {
if (err) {
reject(err);
} else {
con.query("SELECT fcm_token FROM users WHERE id = 24", function(
err,
result,
fields
) {
if (err) {
reject(err);
} else {
token = result[0].fcm_token;
resolve(token);
}
});
}
});
});
console.log("Token : " + token);
return admin.messaging().sendToDevice(token, payload, options);
});
I keep getting the following errors:
According to the documentation sendToDevice does not take a promise as a parameter. So you will have to call sendToDevice with the resolved token(s) instead and only then resolve/reject.
exports.pushNotification = functions.database
.ref("/messages")
.onWrite((change, context) => {
console.log("Push notification event triggered");
...
return new Promise(function(resolve, reject) {
con.connect(function(err) {
if (err) {
reject(err);
} else {
con.query("SELECT fcm_token FROM users WHERE id = 24", function(
err,
result,
fields
) {
if (err) {
reject(err);
} else {
token = result[0].fcm_token;
console.log("Token : " + token);
admin.messaging().sendToDevice(token, payload, options).then(function() {
resolve();
}).catch(function(err) {
reject(err);
});
}
});
}
});
});
});

Google Authentication using Sails.js

When I have tried to implement Google authentication in my site, using sails JavaScript, and MySQL getting error. I have using passport and passport-Google-auth Strategy. Problem is not getting data to my site from Google
My Express Config(express.js) file is like below,
var passport = require('passport')
, GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
var verifyHandler = function(token, tokenSecret, profile, done) {
process.nextTick(function() {
console.log(profile)
User.findOne({uid: profile.id}, function(err, user) {
if (user) {
return done(null, user);
} else {
var data = {
provider: profile.provider,
uid: profile.id,
name: profile.displayName
};
if (profile.emails && profile.emails[0] && profile.emails[0].value) {
data.email = profile.emails[0].value;
}
if (profile.name && profile.name.givenName) {
data.firstname = profile.name.givenName;
}
if (profile.name && profile.name.familyName) {
data.lastname = profile.name.familyName;
}
User.create(data, function(err, user) {
return done(err, user);
});
}
});
});
};
passport.serializeUser(function(user, done) {
console.log(user)
done(null, user.uid);
});
passport.deserializeUser(function(uid, done) {
User.findOne({uid: uid}, function(err, user) {
done(err, user);
});
});
module.exports.http = {
customMiddleware: function(app) {
passport.use(new GoogleStrategy({
clientID: 'Client Id here',
clientSecret: 'Secret key here',
callbackURL: 'http://localhost:1337/auth/google/callback'
}, verifyHandler));
app.use(passport.initialize());
app.use(passport.session());
}
};
module.exports.cache = {
// The number of seconds to cache files being served from disk
// (only works in production mode)
maxAge: 31557600000
};
module.exports.userlogin = {
userModel: 'user'
};
And My Auth Controller I have added code like below,
google: function(req, res) {
passport.authenticate('google',{
failureRedirect: '/login', scope: ['profile', 'email']
}, function(err, user) {
req.logIn(user, function(err) {
if (err) {
console.log(err);
res.view('500');
return;
}
res.redirect('/');
return;
});
})(req, res);
},
You didn't post your code, so we can't find the exact problem :/
I usually use this method for google/facebook authentication with sails.js.
I follow at first this documentation to add the authentication buttons in the frontend:
https://developers.google.com/identity/sign-in/web/sign-in
Then I post the token that I got from google/facebook to the backend where I can check if the user is banned or whatever... If everything is correct, I create an account for him in the database, I send him his password to his email and finally authenticate him using sessions
(req.session.userId = createdUser.id)
In the next time the user can log in using his email and password or just using google. And both options lead him to the same account :D
My Sails.js function in the authentication controller:
googleAuth: function(req, res) {
if (_.isUndefined(req.param('googleToken'))) {
return res.json({
success: false,
msg: 'Error! Please post your google token'
});
}
var urlToRq = "https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=" + req.param('googleToken');
// Get information about the google user with the specified access token.
request.get({url: urlToRq}, function(err, response, body) {
if(err) {
return res.json({
success: false,
msg: 'Server Error'
});
}
var receivedData = JSON.parse(body);
var userId = receivedData.sub;
var userEmail = receivedData.email;
var emailVerified = receivedData.email_verified;
var userName = receivedData.name;
var userPicture = receivedData.picture;
if (emailVerified == false) {
return res.json({
success: false,
msg: 'Your email is not verified'
});
}
else {
// AUTHENTICATION VERIFIED, YOU CAN SAVE THE CONNECTED USER IN A SESSION, OR ADD HIM TO THE DATABASE AS A NEW ACCOUNT, OR CHECK IF HE HAS A PREVIOUS ACCOUNT OR WHATEVER YOU WANT...
}
});
},
Of course don't forget to run npm install request --save
If anyone needs the facebookAuth function just tell me :D I will post it for you :)

Assign One to Many Relationships in Bulk using Mongoose

How do I map one to many relationships as a batch operation using Mongoose?
I have controllers for building seed data for accounts and users.
This data is sourced from a spreadsheet. I then map ONE account to MANY users with another controller, this mapping is bi-direction, i.e Account has array of userIds and user has single accountId.
The code listed, below all works correctly, but it took me 8 hours to write and was quite painful to debug with all the Async and Callback issues that I had to work with.
I researched into bulk operations, native mongo drive stuff etc... and this was the best I could come up with.
I feel that this code could use faster and/or better techniques but I'm not sure how to improve it.
I have included some screenshots or code for
test data in Excel and JSON
SPEC that fires account, user and relationship generation
relationship builder controller with debug code left in place.
screenshot of the output
I'm hoping for feedback.
Seed Data SPEC
describe('Relationship', function () {
beforeEach(td.accounts.teardown);
beforeEach(td.users.teardown);
beforeEach(td.users.seedData);
beforeEach(td.users.setAuthenticatedTokenAdmin);
it('should create relationships between the user and accounts table', function (done) {
// Build Account Data
request(app).put('/api/seeds/accountCreateSeed').set('Authorization', 'Bearer ' + td.users.authenticatedToken).send({ logDetail: 0, useSampleJson: true })
.end(function (err, res) {
if (err) {
l.logTheUnknown(err);
return done(err);
}
// Build User Data
request(app).put('/api/seeds/userCreateSeed').set('Authorization', 'Bearer ' + td.users.authenticatedToken).send({ logDetail: 0, useSampleJson: true })
.end(function (err, res) {
if (err) {
l.logTheUnknown(err);
return done(err);
}
// Build User /Account Relationship Data
request(app)
.put('/api/seed-relationships/createUserAccountRelationship')
.set('Authorization', 'Bearer ' + td.users.authenticatedToken)
.send({ logDetail: 0, useSampleJson: true })
.end(function (err, res) {
if (err) {
l.logTheUnknown(err);
return done(err);
}
return done(err);
});
});
});
});
});
Seed Data Relationship Controller
// ----------------------------------------------------------------------
// User / Account - Relationships
// ----------------------------------------------------------------------
exports.createUserAccountRelationship = function (req, res) {
var useSampleJson = req.body.useSampleJson ? req.body.useSampleJson : false;
// userAccounts = the input data to be processed
var userAccounts = useSampleJson ? readFile('accountUserRelationship.json') : req.body.data;
var logDetail = req.body.logDetail ? req.body.logDetail : 0;
if (logDetail >= LOG_DETAIL) {
l.kv('useSampleJson', useSampleJson);
l.kv('logDetail', logDetail);
}
if (logDetail >= LOG_LOW) {
l.block('Relationship Data for User/Account');
}
if (logDetail >= LOG_LOW) {
l.line('User / Account Relationships JSON');
if (userAccounts) {
l.kv('Length', userAccounts.length);
l.inspect(userAccounts);
}
}
async.eachSeries(userAccounts,
function (userAccount, callback) {
l.kv('Search Account', userAccount.accountName);
Account.findOne({ name: userAccount.accountName }, function (err, account) {
if (err) {
l.inspect(err);
} else {
if (account) {
findAccountUsers(userAccount, account, callback);
} else {
l.kv('Could not find Account', userAccount.accountName);
callback();
}
}
});
},
function (err) {
if (err) {
l.inspect(err);
} else {
l.block('User Account Relations Processed ');
}
return res.sendStatus(200);
});
};
function findAccountUsers(userAccount, account, callback) {
// userAccount = A single relationship between account and multipleUsers
// account = the DB account to work with
// Find all the users that are associated with this account
l.inspect(userAccount.userEmail);
User.find({ email: { $in: userAccount.userEmail } }, function (err, users) {
l.inspect(_.map(users, function (user) { return user.id + ' - ' + user.email; }));
assignAccountUserRelationship(account, users, callback);
});
}
function assignAccountUserRelationship(account, users, callback) {
// account = the DB account to work with
// users = the DB users to work with
account.userIds = [];
for (var userIndex = 0; userIndex < users.length; userIndex++) {
var user = users[userIndex];
user.accountId = account._id;
account.userIds.push(user._id);
}
account.save(function (err) {
if (err) {
l.inspect(err);
} else {
l.kv('Account Saved', account.name);
}
async.eachSeries(users,
function (user, userCallback) {
user.save(function (err) {
if (err) {
l.inspect(err);
} else {
l.kv('user saved', user.email);
}
userCallback();
});
},
function (err) {
if (err) {
l.inspect(err);
} else {
l.block('User Relation Processed ');
}
callback();
});
});
}
Test Data
Test Data Relationship as JSON
Sample Log Output
Sample Output from Mongo Shell