Monthly Archives: January 2018

Serverless Development with Node, MongoDB Atlas, and AWS Lambda

By Chris Sevilleja

The developer landscape has dramatically changed in recent years. It used to be fairly common for us developers to run all of our tools (databases, web servers, development IDEs…) on our own machines, but cloud services such as GitHub, MongoDB Atlas and AWS Lambda are drastically changing the game. They make it increasingly easier for developers to write and run code anywhere and on any device with no (or very few) dependencies.

A few years ago, if you crashed your machine, lost it or simply ran out of power, it would have probably taken you a few days before you got a new machine back up and running with everything you need properly set up and configured the way it previously was.

With developer tools in the cloud, you can now switch from one laptop to another with minimal disruption. However, it doesn’t mean everything is rosy. Writing and debugging code in the cloud is still challenging; as developers, we know that having a local development environment, although more lightweight, is still very valuable.

What We’ll Learn

And that’s exactly what I’ll try to show you in this blog post: how to easily integrate an AWS Lambda Node.js function with a MongoDB database hosted in MongoDB Atlas, the DBaaS (database as a service) for MongoDB. More specifically, we’ll write a simple Lambda function that creates a single document in a collection stored in a MongoDB Atlas database. I’ll guide you through this tutorial step-by-step, and you should be done with it in less than an hour.

Requirements

Let’s start with the necessary requirements to get you up and running:

  1. An Amazon Web Services account available with a user having administrative access to the IAM and Lambda services. If you don’t have one yet, sign up for a free AWS account.
  2. A local machine with Node.js (I told you we wouldn’t get rid of local dev environments so easily…). We will use Mac OS X in the tutorial below but it should be relatively easy to perform the same tasks on Windows or Linux.
  3. A MongoDB Atlas cluster alive and kicking. If you don’t have one yet, sign up for a free MongoDB Atlas account and create a cluster in just a few clicks. You can even try our M0, free cluster tier, perfect for small-scale development projects!).

Now that you know about the requirements, let’s talk about the specific steps we’ll take to write, test and deploy our Lambda function:

  1. MongoDB Atlas is by default secure, but as application developers, there are steps we should take to ensure that our app complies with least privilege access best practices. Namely, we’ll fine-tune permissions by creating a MongoDB Atlas database user with only read/write access to our app database.
  2. We will set up a Node.js project on our local machine, and we’ll make sure we test our lambda code locally end-to-end before deploying it to Amazon Web Services.
  3. We will then create our AWS Lambda function and upload our Node.js project to initialize it.
  4. Last but not least, we will make some modifications to our Lambda function to encrypt some sensitive data (such as the MongoDB Atlas connection string) and decrypt it from the function code.

A short note about VPC Peering

I’m not delving into the details of setting up VPC Peering between our MongoDB Atlas cluster and AWS Lambda for 2 reasons: 1) we already have a detailed VPC Peering documentation page and a VPC Peering in Atlas post that I highly recommend and 2) M0 clusters (which I used to build that demo) don’t support VPC Peering.

Here’s what happens if you don’t set up VPC Peering though:

  1. You will have to add the infamous 0.0.0.0/0 CIDR block to your MongoDB Atlas cluster IP Whitelist because you won’t know which IP address AWS Lambda is using to make calls to your Atlas database.
  2. You will be charged for the bandwidth usage between your Lambda function and your Atlas cluster.

If you’re only trying to get this demo code to write, these 2 caveats are probably fine, but if you’re planning to deploy a production-ready Lambda-Atlas integration, setting up VPC Peering is a security best practice we highly recommend. M0 is our current free offering; check out our MongoDB Atlas pricing page for the full range of available instance sizes.

As a reminder, for development environments and low traffic websites, M0, M10 and M20 instance sizes should be fine. However, for production environments that support high traffic applications or large datasets, M30 or larger instances sizes are recommended.

Setting up security in your MongoDB Atlas cluster

Making sure that your application complies with least privilege access policies is crucial to protect your data from nefarious threats. This is why we will set up a specific database user that will only have read/write access to our travel database. Let’s see how to achieve this in MongoDB Atlas:

On the Clusters page, select the Security tab, and press the Add New User button

Cluster Security

In the pop-up window that opens, add a user name of your choice (such as lambdauser):

lambdauser

In the User Privileges section, select the Show Advanced Options link. This allows us to assign read/write on a specific database, not any database.

User Privileges

You will then have the option to assign more fine-grained access control privileges:

Access Control

In the Select Role dropdown list, select readWrite and fill out the Database field with the name of the database you’ll use to store documents. I have chosen to name it travel.

Select Role

In the Password section, use the Autogenerate Secure Password button (and make a note of the generated password) or set a password of your liking. Then press the Add User button to confirm this user creation.

Let’s grab the cluster connection string while we’re at it since we’ll need it to connect to our MongoDB Atlas database in our Lambda code:

Assuming you already created a MongoDB Atlas cluster, press the Connect button next to your cluster:

Connect Cluster

Copy the URI Connection String value and store it safely in a text document. We’ll need it later in our code, along with the password you just set.

URI Connection String

Additionally, if you aren’t using VPC Peering, navigate to the IP Whitelist tab and add the 0.0.0.0/0 CIDR block or press the Allow access from anywhere button. As a reminder, this setting is strongly NOT recommended for production use and potentially leaves your MongoDB Atlas cluster vulnerable to malicious attacks.

Add Whitelist Entry

Create a local Node.js project

Though Lambda functions are supported in multiple languages, I have chosen to use Node.js thanks to the growing popularity of JavaScript as a versatile programming language and the tremendous success of the MEAN and MERN stacks (acronyms for MongoDB, Express.js, Angular/React, Node.js – check out Andrew Morgan’s excellent developer-focused blog series on this topic). Plus, to be honest, I love the fact it’s an interpreted, lightweight language which doesn’t require heavy development tools and compilers.

Time to write some code now, so let’s go ahead and use Node.js as our language of choice for our Lambda function.

Start by creating a folder such as lambda-atlas-create-doc

mkdir lambda-atlas-create-doc 
&& cd lambda-atlas-create-doc

Next, run the following command from a Terminal console to initialize our project with a package.json file

npm init

You’ll be prompted to configure a few fields. I’ll leave them to your creativity but note that I chose to set the entry point to app.js (instead of the default index.js) so you might want to do so as well.

We’ll need to use the MongoDB Node.js driver so that we can connect to our MongoDB database (on Atlas) from our Lambda function, so let’s go ahead and install it by running the following command from our project root:

npm install mongodb --save

We’ll also want to write and test our Lambda function locally to speed up development and ease debugging, since instantiating a lambda function every single time in Amazon Web Services isn’t particularly fast (and debugging is virtually non-existent, unless you’re a fan of the console.log() function). I’ve chosen to use the lambda-local package because it provides support for environment variables (which we’ll use later):

(sudo) npm install lambda-local -g

Create an app.js file. This will be the file that contains our lambda function:

touch app.js

Now that you have imported all of the required dependencies and created the Lambda code file, open the app.js file in your code editor of choice (Atom, Sublime Text, Visual Studio Code…) and initialize it with the following piece of code:

use strict
var MongoClient = require(mongodb).MongoClient;
let atlas_connection_uri;
let cachedDb = null;
exports.handler = (event, context, callback) => {
var uri = process.env[MONGODB_ATLAS_CLUSTER_URI];
if (atlas_connection_uri != null) {
processEvent(event, context, callback);
}
else {
atlas_connection_uri = uri;
console.log(the Atlas connection string is + atlas_connection_uri);
processEvent(event, context, callback);
}
};
function processEvent(event, context, callback) {
console.log(Calling MongoDB Atlas from AWS Lambda with event: + JSON.stringify(event));
}

Let’s pause a bit and comment the code above, since you might have noticed a few peculiar constructs:

  • The file is written exactly as the Lambda code Amazon Web Services expects (e.g. with an “exports.handler” function). This is because we’re using lambda-local to test our lambda function locally, which conveniently lets us write our code exactly the way AWS Lambda expects it. More about this in a minute.
  • We are declaring the MongoDB Node.js driver that will help us connect to and query our MongoDB database.
  • Note also that we are declaring a cachedDb object OUTSIDE of the handler function. As the name suggests, it’s an object that we plan to cache for the duration of the underlying container AWS Lambda instantiates for our function. This allows us to save some precious milliseconds (and even seconds) to create a database connection between Lambda and MongoDB Atlas. For more information, please read my follow-up blog post on how to optimize Lambda performance with MongoDB Atlas.
  • We are using an environment variable called MONGODB_ATLAS_CLUSTER_URI to pass the uri connection string of our Atlas database, mainly for security purposes: we obviously don’t want to hardcode this uri in our function code, along with very sensitive information such as the username and password we use. Since AWS Lambda supports environment variables since November 2016 (as the lambda-local NPM package does), we would be remiss not to use them.
  • The function code looks a bit convoluted with the seemingly useless if-else statement and the processEvent function but it will all become clear when we add decryption routines using AWS Key Management Service (KMS). Indeed, not only do we want to store our MongoDB Atlas connection string in an environment variable, but we also want to encrypt it (using AWS KMS) since it contains highly sensitive data (note that you might incur charges when you use AWS KMS even if you have a free AWS account).

Now that we’re done with the code comments, let’s create an event.json file (in the root project directory) and fill it with the following data:

{
   "address" : {
      "street" : "2 Avenue",
      "zipcode" : "10075",
      "building" : "1480",
      "coord" : [ -73.9557413, 40.7720266 ]
   },
   "borough" : "Manhattan",
   "cuisine" : "Italian",
   "grades" : [
      {
         "date" : "2014-10-01T00:00:00Z",
         "grade" : "A",
         "score" : 11
      },
      {
         "date" : "2014-01-16T00:00:00Z",
         "grade" : "B",
         "score" : 17
      }
   ],
   "name" : "Vella",
   "restaurant_id" : "41704620"
}

(in case you’re wondering, that JSON file is what we’ll send to MongoDB Atlas to create our BSON document)

Next, make sure that you’re set up properly by running the following command in a Terminal console:

lambda-local -l app.js -e event.json -E {“MONGODB_ATLAS_CLUSTER_URI”:”mongodb://lambdauser:$PASSWORD@lambdademo-shard-00-00-7xh22.mongodb.net:27017,lambdademo-shard-00-01-7xh22.mongodb.net:27017,lambdademo-shard-00-02-7xh22.mongodb.net:27017/$DATABASE?ssl=true&replicaSet=lambdademo-shard-0&authSource=admin”}

If you want to test it with your own cluster URI Connection String (as I’m sure you do), don’t forget to escape the double quotes, commas and ampersand characters in the E parameter, otherwise lambda-local will throw an error (you should also replace the $PASSWORD and $DATABASE keywords with your own values).

After you run it locally, you should get the following console output:

console output

If you get an error, check your connection string and the double quotes/commas/ampersand escaping (as noted above).

Now, let’s get down to the meat of our function code by customizing the processEvent() function and adding a createDoc() function:

function processEvent(event, context, callback) {
console.log(Calling MongoDB Atlas from AWS Lambda with event: + JSON.stringify(event));
var jsonContents = JSON.parse(JSON.stringify(event));
//date conversion for grades array
if(jsonContents.grades != null) {
for(var i = 0, len=jsonContents.grades.length; i len; i++) {
//use the following line if you want to preserve the original dates
//jsonContents.grades[i].date = new Date(jsonContents.grades[i].date);
//the following line assigns the current date so we can more easily differentiate between similar records
jsonContents.grades[i].date = new Date();
}
}
//the following line is critical for performance reasons to allow re-use of database connections across calls to this Lambda function and avoid closing the database connection. The first call to this lambda function takes about 5 seconds to complete, while subsequent, close calls will only take a few hundred milliseconds.
context.callbackWaitsForEmptyEventLoop = false;
try {
if (cachedDb == null) {
console.log(=> connecting to database);
MongoClient.connect(atlas_connection_uri, function (err, db) {
cachedDb = db;
return createDoc(db, jsonContents, callback);
});
}
else {
createDoc(cachedDb, jsonContents, callback);
}
}
catch (err) {
console.error(an error occurred, err);
}
}
function createDoc (db, json, callback) {
db.collection(restaurants).insertOne( json, function(err, result) {
if(err!=null) {
console.error(an error occurred in createDoc, err);
callback(null, JSON.stringify(err));
}
else {
console.log(Kudos! You just created an entry into the restaurants collection with id: + result.insertedId);
callback(null, SUCCESS);
}
//we don’t need to close the connection thanks to context.callbackWaitsForEmptyEventLoop = false (above)
//this will let our function re-use the connection on the next called (if it can re-use the same Lambda container)
//db.close();
});
};

Note how easy it is to connect to a MongoDB Atlas database and insert a document, as well as the small piece of code I added to translate JSON dates (formatted as ISO-compliant strings) into real JavaScript dates that MongoDB can store as BSON dates.

You might also have noticed my performance optimization comments and the call to context.callbackWaitsForEmptyEventLoop = false. If you’re interested in understanding what they mean (and I think you should!), please refer to my follow-up blog post on how to optimize Lambda performance with MongoDB Atlas.

You’re now ready to fully test your Lambda function locally. Use the same lambda-local command as before and hopefully you’ll get a nice “Kudos” success message:

kudos message

If all went well on your local machine, let’s publish our local Node.js project as a new Lambda function!

Create the Lambda function

The first step we’ll want to take is to zip our Node.js project, since we won’t write the Lambda code function in the Lambda code editor. Instead, we’ll choose the zip upload method to get our code pushed to AWS Lambda.

I’ve used the zip command line tool in a Terminal console, but any method works (as long as you zip the files inside the top folder, not the top folder itself!) :

zip -r archive.zip node_modules/ app.js package.json

Next, sign in to the AWS Console and navigate to the IAM Roles page and create a role (such as LambdaBasicExecRole) with the AWSLambdaBasicExecutionRole permission policy:

AWSLambdaBasicExecutionRole

Let’s navigate to the AWS Lambda page now. Click on Get Started Now (if you’ve never created a Lambda function) or on the Create a Lambda function button. We’re not going to use any blueprint and won’t configure any trigger either, so select Configure function directly in the left navigation bar:

AWS Lambda Configure

In the Configure function page, enter a Name for your function (such as MongoDB_Atlas_CreateDoc). The runtime is automatically set to Node.js 4.3, which is perfect for us, since that’s the language we’ll use. In the Code entry type list, select Upload a .ZIP file, as shown in the screenshot below:

Configure Function

Click on the Upload button and select the zipped Node.js project file you previously created.

In the Lambda function handler and role section, modify the Handler field value to app.handler (why? here’s a hint: I’ve used an app.js file, not an index.js file for my Lambda function code…) and choose the existing LambdaBasicExecRole role we just created:

Lambda function handler

In the Advanced Settings section, you might want to increase the Timeout value to 5 or 10 seconds, but that’s always something you can adjust later on. Leave the VPC and KMS key fields to their default value (unless you want to use a VPC and/or a KMS key) and press Next.

Last, review your Lambda function and press Create function at the bottom. Congratulations, your Lambda function is live and you should see a page similar to the following screenshot:

Lambda Create Function

But do you remember our use of environment variables? Now is the time to configure them and use the AWS Key Management Service to secure them!

Configure and secure your Lambda environment variables

Scroll down in the Code tab of your Lambda function and create an environment variable with the following properties:

Name Value
MONGODB_ATLAS_CLUSTER_URI YOUR_ATLAS_CLUSTER_URI_VALUE

environment variables

At this point, you could press the Save and test button at the top of the page, but for additional (and recommended) security, we’ll encrypt that connection string.

Check the Enable encryption helpers check box and if you already created an encryption key, select it (otherwise, you might have to create one – it’s fairly easy):

encryption key

Next, select the Encrypt button for the MONGODB_ATLAS_CLUSTER_URI variable:

select encrypt

Back in the inline code editor, add the following line at the top:

const AWS = require('aws-sdk');

and replace the contents of the “else” statement in the “exports.handler” method with the following code:

const kms = new AWS.KMS();
kms.decrypt({ CiphertextBlob: new Buffer(uri, base64) }, (err, data) => {
if (err) {
console.log(Decrypt error:, err);
return callback(err);
}
atlas_connection_uri = data.Plaintext.toString(ascii);
processEvent(event, context, callback);
});

(hopefully the convoluted code we originally wrote makes sense now!)

If you want to check the whole function code I’ve used, check out the following Gist. And for the Git fans, the full Node.js project source code is also available on GitHub.

Now press the Save and test button and in the Input test event text editor, paste the content of our event.json file:

input test event

Scroll and press the Save and test button.

If you configured everything properly, you should receive the following success message in the Lambda Log output:

Lambda Log Output

Kudos! You can savor your success a few minutes before reading on.

What’s next?

I hope this AWS Lambda-MongoDB Atlas integration tutorial provides you with the right steps for getting started in your first Lambda project. You should now be able to write and test a Lambda function locally and store sensitive data (such as your MongoDB Atlas connection string) securely in AWS KMS.

So what can you do next?

And of course, don’t hesitate to ask us any questions or leave your feedback in a comment below. Happy coding!

Source:: scotch.io

Understand The JavaScript Ternary Operator like ABC

By William Imoh

If you made it this far then it’s either you know of ternary operators and want to know more, you have no idea of ternary operators, or you’re just somewhere in-between. Keep on.

From my time writing JavaScript, and of course looking through the JavaScript of others especially beginner developers, I have noticed the age-long trend of using if/else statements and really long chains of them too! As an advocate of DRY code -Don’t Repeat Yourself, I ensure my code stays DRY, and maybe cold-hearted, lol.

In this post, we’ll be explaining ternary operators in the simplest way and how they make coding and life in general, easier.

Operators in JavaScript

In the JavaScript theatre, various operations require operators, which are basically denoted with symbols- + - / = * %. For the various operations like arithmetic and assignment operations, various symbols are used. These operators in their usage are split into 3 types:

  • Unary Operators – Requires one operand either before or after the operator.
  • Binary Operators – Requires two operands on either side of the operator.
  • Ternary Operator – Requires three operands and is a conditional operator.
time++ //Unary operator (increment)
2 + 3 //Binary Operator (addition)
a ? 'hello' : 'world' //Ternary/Conditional operator

We will focus on the ternary operator as earlier stated.

Ternary Operator

The ternary operator has been around for a while now, but isn’t widely used, maybe because of the syntax or some form of ambiguity I’m unaware of. The ternary operator is a conditional operator and can effectively and efficiently replace several lines of IF statements. It simply verifies if a condition is true or false and returns an expression or carry out an operation based on the state of the condition, in probably one line of code. Using an IF statement we have:

var day = true;
if(day){
  alert('It is day-time')
} else{
  alert('It is night-time')
}
// It is day-time

Using the ternary operator:

var day = true; //conditon
alert(day ? 'It is day-time' : 'It is night-time') // It is day-time

This reduced the syntax of the IF statement to:

- ? - means IF 
- : - means Else

So, if day is true, alert It is daylight, else alert It is nighttime. Simple!

Let’s get to more details.

Variable Assignment

As stated earlier, the result of the condition evaluation can be an expression or an operation, and in this case a variable assignment.

var myName = false;
var age = false;
var message = myName ? "I have a name" : "I don't have a name, duh!"
console.log(message) // I have don't have a name, duh!

myName = true;
message = myName ? age = true : 'Get out of here, nameless'
console.log(message) // true

Notice we assigned the result of a ternary operation first to a global variable message, and later on, reassigned it when the condition changed. Notice the reassignment of the global variable age in the condition of the ternary operator. Reassignment operations can occur in a ternary operation – so much done in one line yeah? The ELSE part of the operation can also be an expression or an operation on its own, just like it’s done in conventional IF statements.

Usage in Functions

Usually, the next use case for IF statements are in functions, basically ternary operations make a function ‘syntactically sweet’. Same way variables are assigned the result of ternary operations is the same way functions return the result of ternary operations. With IF statements we have:

var dog = true;
function myPet(){
  if(dog){
    return 'How do i get it?';
  } else {
    return 'Get me a dog!';
  }
}
console.log(myPet()) // How do i get it?

with a ternary operator:

var dog = false;
function myPet(){
  return dog ? 'How do i get it?' : 'Get me a dog!';
}
console.log(myPet()) // Get me a dog!

Imagine if we had quite a number of IF statements, with a host of return expressions in them, now think of how these can be shortened using ternary operators. Next, we will see how we can chain multiple conditions together, you can have the conditions in functions as well!

Multiple Conditions

Just like in good old IF statement with IF/ELSE IF, multiple conditions can be chained in ternary operations to give one robust operation. Normally we would write:

var myName = true;
var myAge = true;
var message = '';
if (myName){
  if(myAge){
    message = "I'll like to know your age and name"
  }else{
    message = "I'll stick with just your name then"
  }
} else {
  "Oh, I'll call you JavaScript then, cus you fine and mysterious"
}
console.log(message) //I'll like to know your age and name

but with a ternary operator we have:

var myName = true;
var myAge = true;
var message = myName? (myAge ? "I'll like to know your age and name" : "I'll stick with just your name") : "Oh, I'll call you JavaScript then, cus you fine and mysterious"
console.log(message) // I'll like to know your age and name

This is just a simple illustration of having two conditions in one IF statement. Here’s a lighter one:

var email = false;
var phoneNumber = true;
var message = email ? 'Thanks for reaching out to us' : phoneNumber ? 'Thanks for reaching out to us' : 'Please fill in your email or phone-number'
console.log(message) //Thanks for reaching out to us

Here we simply have multiple conditions chained to one another, and if a condition doesn’t pass, another condition is put forward, and if it still doesn’t pass, (now you cannot be offered any further assistance, lol) an expression is returned.

Multiple Operations per Condition

A friend of mine would say “in code, you read A + B but later you are required to pull B from a remote server, make A a ninja, minify B, before they can be added together”. So far we have seen multiple conditions chained together, what about expressions or conditions per condition? Say we would like to make a request to an API if a condition passes as true. Just like in IF statements, here’s a simple one:

var home = true;
if(home){
  alert('Welcome 127.0.0.1');
  var port = prompt('What port do you like?');
  alert('Serving you a cool dish on ' + port)
} else {
  alert('Check back when you get home' )
}
//serving you a cool dish on ???

but with a ternary operator, simply separate each operation with a comma.

var home = true;
var port = '';
home ? (
  alert('Welcome 127.0.0.1'),
  port = prompt('What port do you like?'),
  alert('Serving you a cool dish on ' + port)
) : alert('Check back when you get home' )
//serving you a cool dish on ???

Syntactic sugar!

Note: All variables used in a ternary operation should be defined before the operation is created. Also, If the operations in the condition are assignment operations, the value of the last expression or operation is used i.e

var home = true;
var myLocation = 'Lagos';
myLocation = home ? ('Brussels', 'london', 'Rio de Janero', 'Newark' ) : 'Kinshasha'
console.log(myLocation) // Newark

Conclusion

So far, you have seen how invaluable using ternary operators to write conditional statements make code plain and effortless, from writing simple lines of conditional statements to writing large chunks of chained operations in or out of functions. Using ternary operators, keep writing better code, …and DRY code.

Source:: scotch.io

Node.js Weekly Update - January 12

By Tamas Kadlecsik

Node.js Weekly Update - January 12

Below you can find RisingStack‘s collection of the most important Node.js updates, projects & tutorials from this week:

Node v9.4.0 (Current) released

Notable Changes:

  • async_hooks:
    • deprecate AsyncHooks Sensitive API and runInAsyncIdScope. Neither API were documented. (Andreas Madsen)
  • deps:
    • update nghttp2 to 1.29.0 (James M Snell)
    • upgrade npm to 5.6.0 (Kat Marchán)
    • cherry-pick 50f7455 from upstream V8 (Michaël Zasso)
  • events:
    • remove reaches into _events internals (Anatoli Papirovski)
  • http:
    • add rawPacket in err of clientError event (XadillaX)
  • http2:
    • implement maxSessionMemory (James M Snell)
    • add initial support for originSet (James M Snell)
    • add altsvc support (James M Snell)
    • perf_hooks integration (James M Snell)
    • Refactoring and cleanup of Http2Session and Http2Stream destroy (James M Snell)

Click here for more info.

Node.js + face-recognition.js : Simple and Robust Face Recognition using Deep Learning

In this article you’ll learn how to perform robust face detection and face recognition using face-recognition.js.

I was looking for a promising Node.js library that produces accurate face recognition results, found none, thus decided to create one!

Node.js Weekly Update - January 12

8 Tips to Build Better Node.js Apps in 2018

In this article, we collected a few tips that we think Node.js developers should follow in 2018. Feel free to pick some development related New Year’s resolutions!

npm operational incident, 6 Jan 2018

The npm registry had an operations incident Saturday that caused 97 packages to be temporarily unavailable for download for approximately 30 minutes, and an additional 9 packages to be unavailable for approximately three hours.

Building Your First Node App Using Docker

In this article, you’ll read an overview of how Docker works and learn three examples of using Docker with Node.

? AmsterdamJS wants you to speak

What’s the next big thing in software development? Everyone has an opinion these days, and we’d love to hear yours.
Node.js Weekly Update - January 12

Running a Node app on Amazon ECS

Read the experiences Gosquared had with ECS and how they set up the infrastructure using ECS to run Node apps.

I’m harvesting credit card numbers and passwords from your site. Here’s how.

The author of this article decided to come clean and tell us all how he’s been stealing usernames, passwords and credit card numbers from sites for the past few years.

Previously in the Node.js Weekly Update

In the previous Node.js Weekly Update, we brough you the finest articles of the past week. This included the release of Node v8.9.4 (LTS), meltdown and spectre bugs, our article on 2017’s Node Community, optimizing middleware implementation, and much more! Click if you missed it!

We help you to stay up-to-date with Node.js on a daily basis too. Check out our Node.js news page and its Twitter feed!

Source:: risingstack.com

Template Driven Form Validation In Vue.js

By Ogundipe Samuel Ayo

Form validation (or more correctly, form field validation) forces a user to fill out all required fields in a web form. The validation is typically done where the developer can set up rules. For example: If the name field is blank, take the user back to the form and display an error message.

Template driven validation is a type of form validation where validation rules are set directly in the form elements using directives.

To implement template driven validations in Vue.js, we can use VeeValidate. VeeValidate is a plugin for Vue.js that allows you to validate input fields and display errors.

What We Will build

At the end of this piece, we will build a simple registration form which uses VeeValidate to validate its form input. Here is a pictorial view of what we will build.

Getting Started With VeeValidate

First, we need to grab Vue and the VeeValidate library.

Let us grab the browser build for Vue.js which is available here.

Next, we will grab the browser build for VeeValidate which is available via jsdeliver here.

Create a new file called register.html and add:

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>Vue Template Form Validation</title>
</head>
<body>
</body>
<!-- include the Vue.js library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<!-- include the VeeValidate library -->
<script src="https://cdn.jsdelivr.net/npm/vee-validate@latest/dist/vee-validate.js"></script>
<script>
// Notify vue about the VeeValidate plugin
 Vue.use(VeeValidate);
</script>

The code above shows how easy it is to include VeeValidate into our Vue project. Vue.js is notified that it can use the VeeValidate plugin at the line that says Vue.use(VeeValidate).

VeeValidate Rules

A VeeValidate rule is one that sets limits or conditions on what can be entered in one or more fields.
Validation rules are checked when you update a record containing fields requiring validation. If the rule is violated, a trappable error occurs.
How do you use a rule? Just apply the v-validate directive on your input and pass a string value which is a list of validations separated by a pipe. For example, we will use the required and the email validators:

<input v-validate="'required|email'" type="text" name="email">

Alternatively you can pass an object for more flexibility:

<input v-validate="{ required: true, email: true, regex: /[0-9]+/ }" type="text" name="email">

Now every time the input changes, the validator will run the list of validations from left to right, populating the errors helper object whenever an input fails validation.

As at the time of writing this tutorial, VeeValidate ships with 30 rules for form validation with an option of creating your own rules. You can take a peep at what rules are available here.

VeeValidate Errors

By default, VeeValidate provides us with a variable errors which is injected into the data section of the Vue component by the plugin. When a form validation fails, VeeValidate populates this errors variable with an array containing objects of failed validations, which can be accessed this way:

//check if an input has errors
this.errors.has(Inputname)
//return the first error of an input
this.errors.first(Inputname)

However, to use this method, some things must be put into consideration.

  • The name attribute must be specified. It serves as an identifier for VeeValidate to refer to. You can use data-vv-name if, for some reason, you can’t use name attribute in your template.

VeeValidate Custom Validation

While VeeValidate ships with around 30 rules, these rules might not do justice to your form as intended. What if I need a custom validation that VeeValidate does not come with? For example, what if I want to validate that a username is unique in my database? VeeValidate allows you to write custom validation rules and messages. Take a look at the code below for example:

//declare an array of some usernames user must not input
 var username = [
    'admin',
    'password',
    'administartor'
]
//create new rule
const newrule = {
// will be added to default English messages.
  getMessage(field, params, data) {
      return (data && data.message) || 'Something went wrong';
  },
  // Returns a Boolean or a Promise.
  validate(value) {
    return new Promise(resolve => {
      resolve({
        valid: username.includes(value.toLowerCase()) ? false : !! value,
        data: { message: `${value} has already been taken` }
      });
    });
  }
};

The important things to notice in the code below are:

  • The getMessage method in the object is used to return a custom error message. The message can either be passed directly or passed via a variable from called data from the validate method
  • The validate method in the object returns a boolean, an object or a promise. If it returns an object, the valid property must be present with a boolean value. This boolean value is what is checked to see if the form is valid or not. In our case, we checked if the value is included in the list of usernames we do not want people selecting from.

Now we have a new rule. Does VeeValidate automatically know about this rule? No. How do we tell VeeValidate that it can use this new rule we just created? By extending the default Validator and passing the new rule into it:

 VeeValidate.Validator.extend('checkuser',newrule);

In this snippet, we just extended the VeeValidate validator with our own custom validator named checkuser. So we can call the Validator for any input this way:

<input v-validate="'checkuser'" type="text" name="username">

Validating A Simple Registration Page

Let us whip up a small demo. We will be validating a simple registration page. Move back into the file created at the beginning of this exercise called register.html and add the following HTML:

      <body>
        <div class="container">
            <div class="row main">
                <div class="main-login main-center">
                <h5>Sign up once and watch any of our free demos.</h5>
                    <form id="signup-form" @submit.prevent="processForm">

                        <div class="form-group">
                            <label for="name" class="cols-sm-2 control-label">Your Name</label>
                            <div class="cols-sm-10">
                                <div class="input-group">
                                    <span class="input-group-addon"><i class="fa fa-user fa" aria-hidden="true"></i></span>
                  <input type="text" name="name" placeholder="Name" :class="{ 'form-control': true, 'is-danger': errors.has('name') }" v-model="name" v-validate="'required|alpha'">

                                </div>
                 <span v-show="errors.has('name')" class="help is-danger">{{ errors.first('name') }}</span>
                            </div>
                        </div>

                        <div class="form-group">
                            <label for="email" class="cols-sm-2 control-label">Your Email</label>
                            <div class="cols-sm-10">
                                <div class="input-group">
                                    <span class="input-group-addon"><i class="fa fa-envelope fa" aria-hidden="true"></i></span>
                                    <input type="email" :class="{ 'form-control': true, 'is-danger': errors.has('email') }" name="email" placeholder="my@email.com" v-model="email" v-validate="'required|email'">

                </div>
                <span v-show="errors.has('email')" class="help is-danger">{{ errors.first('email') }}</span>
                            </div>
                        </div>

                        <div class="form-group">
                            <label for="username" class="cols-sm-2 control-label">Username</label>
                            <div class="cols-sm-10">
                                <div class="input-group">
                                    <span class="input-group-addon"><i class="fa fa-users fa" aria-hidden="true"></i></span>
                                        <input type="text" :class="{ 'form-control': true, 'is-danger': errors.has('username') }" name="username" placeholder="Enter your username" v-model="username" v-validate="'required|checkuser'">
                                </div>
                 <span v-show="errors.has('username')" class="help is-danger">{{ errors.first('username') }}</span>
                            </div>
                        </div>

                        <div class="form-group">
                            <label for="password" class="cols-sm-2 control-label">Password</label>
                            <div class="cols-sm-10">
                                <div class="input-group">
                                    <span class="input-group-addon"><i class="fa fa-lock fa-lg" aria-hidden="true"></i></span>
                                    <input type="password" :class="{ 'form-control': true, 'is-danger': errors.has('password') }" name="password" placeholder="Enter a password" v-model="password" v-validate="'required|min:6'">
                                </div>
                <span v-show="errors.has('password')" class="help is-danger">{{ errors.first('password') }}</span>
                            </div>
                        </div>

                        <div class="form-group">
                            <label for="confirm" class="cols-sm-2 control-label">Confirm Password</label>
                            <div class="cols-sm-10">
                                <div class="input-group">
                                    <span class="input-group-addon"><i class="fa fa-lock fa-lg" aria-hidden="true"></i></span>

                                <input v-validate="'required|confirmed:password'" name="password_confirmation" type="password" :class="{ 'form-control': true, 'is-danger': errors.has('password') }" placeholder="Password, Again" data-vv-as="password">
                </div>
                <span v-show="errors.has('password_confirmation')" class="help is-danger">{{ errors.first('password_confirmation') }}</span>
                            </div>
                        </div>

                        <div class="form-group ">
                            <button id="button" :disabled="errors.any()" class="btn btn-primary btn-lg btn-block login-button">Register</button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </body>

In the code block above, we have 5 input elements which are:

  • Name: The name of the user registering. Note that the v-validate directive was also added to it, specifying required|alpha which means the input is required and can only contain alphabetic characters. Also notice a span element just after the input which shows up when errors.has('name') is true, courtesy of the v-show directive. It then displays the first error for that input via errors.first('name')
  • Email: The email of the user registering. Note that the v-validate directive was also added to it, specifying required|email which means the input is required and must contain a valid email. Like the name input, this also has a span input attached in similar fashion.
  • Username: The general username for the user registering. Note that we have something a bit different in the v-validate directive here. We passed in a rule called checkuser. Remember this custom validator that we made? Here we see it in action. Like the name and email input, this also has a span input attached in a similar fashion.
  • Password: The password the user registering must set. In the v-validate directive of this input, we have another rule specified min:6. This tells VeeValidate that the password must not be lesser than 6 characters. Like the name, email and username input, this also has a span input attached in a similar fashion.
  • Password_confirmation: Here we want the user to confirm his password. This is helpful, so he doesn’t make a mistake in his password unknowingly. Notice that in the v-validate directive, we passed in confirmed:password as one of the rules? This tells VeeValidate that the value of this input must equal the value of the password input. Like the name, email and username input, this also has a span input attached in a similar fashion.

Also, our markup consists of a button, which is used to submit the form. First, I want you to take a look at the Form declaration in the markup and notice the @submit.prevent="processForm". This prevents the form from refreshing or performing any other action when this button is clicked rather than the one defined in the processForm function in our Vue methods. Also, notice that in the button, we have a little condition for the disabled property of the button :disabled=”errors.any()”. The errors.any() is a method exposed by VeeValidate to verify if all validations were passed or not.

Next, let’s add some style to make it look great. Open a style tag and paste:

#playground-container {
    height: 500px;
    overflow: hidden !important;
    -webkit-overflow-scrolling: touch;
}
body, html{
     height: 100%;
     background-repeat: no-repeat;
     background:url(https://i.ytimg.com/vi/4kfXjatgeEU/maxresdefault.jpg);
     font-family: 'Oxygen', sans-serif;
        background-size: cover;
}

.main{
     margin:50px 15px;
}

h1.title { 
    font-size: 50px;
    font-family: 'Passion One', cursive; 
    font-weight: 400; 
}

hr{
    width: 10%;
    color: #fff;
}

.form-group{
    margin-bottom: 15px;
}

label{
    margin-bottom: 15px;
}

input,
input::-webkit-input-placeholder {
    font-size: 11px;
    padding-top: 3px;
}

.main-login{
     background-color: #fff;
    /* shadows and rounded borders */
    -moz-border-radius: 2px;
    -webkit-border-radius: 2px;
    border-radius: 2px;
    -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
    -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
    box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);

}
.form-control {
    height: auto!important;
padding: 8px 12px !important;
}
.input-group {
    -webkit-box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.21)!important;
    -moz-box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.21)!important;
    box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.21)!important;
}
#button {
    border: 1px solid #ccc;
    margin-top: 28px;
    padding: 6px 12px;
    color: #666;
    text-shadow: 0 1px #fff;
    cursor: pointer;
    -moz-border-radius: 3px 3px;
    -webkit-border-radius: 3px 3px;
    border-radius: 3px 3px;
    -moz-box-shadow: 0 1px #fff inset, 0 1px #ddd;
    -webkit-box-shadow: 0 1px #fff inset, 0 1px #ddd;
    box-shadow: 0 1px #fff inset, 0 1px #ddd;
    background: #f5f5f5;
    background: -moz-linear-gradient(top, #f5f5f5 0%, #eeeeee 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f5f5f5), color-stop(100%, #eeeeee));
    background: -webkit-linear-gradient(top, #f5f5f5 0%, #eeeeee 100%);
    background: -o-linear-gradient(top, #f5f5f5 0%, #eeeeee 100%);
    background: -ms-linear-gradient(top, #f5f5f5 0%, #eeeeee 100%);
    background: linear-gradient(top, #f5f5f5 0%, #eeeeee 100%);
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#eeeeee', GradientType=0);
}
.main-center{
     margin-top: 30px;
     margin: 0 auto;
     max-width: 400px;
    padding: 10px 40px;
    background:rgb(123, 131, 134);
        color: #FFF;
    text-shadow: none;
    -webkit-box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.31);
-moz-box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.31);
box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.31);

}
span.input-group-addon i {
    color: #009edf;
    font-size: 17px;
}

.login-button{
    margin-top: 5px;
}

.login-register{
    font-size: 11px;
    text-align: center;
}
.is-danger{
  color: red;
  font-weight: 700;
}
.help {
    background: white;
    }

Above are some CSS styles to make our page look great. Don’t forget to add the following to your head tag:

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

Above is the code to link bootstrap to our registration page. To make it much nicer.

Vue Component

Let us take a look at how our Vue Component should look now. Replace the script section where we have Vue.use(VeeValidate) with:

// Notify vue about the VeeValidate plugin
Vue.use(VeeValidate);
//declare an array of some usernames user must not input
 var username = [
    'admin',
    'password',
    'administartor'
]
//create new rule
const newrule = {
// will be added to default English messages.
  getMessage(field, params, data) {
      return (data && data.message) || 'Something went wrong';
  },
    // Returns a Boolean or a Promise.
  validate(value) {
    return new Promise(resolve => {
      resolve({
        valid: username.includes(value.toLowerCase()) ? false : !! value,
        data: { message: `${value} has already been taken` }
      });
    });
  }
};
// Tell the Validator about the new rule
  VeeValidate.Validator.extend('checkuser',newrule);
    const signupForm = new Vue({
        el: '#signup-form',
        data: {
            name: '',
            email: '',
            username: '',
            password: ''
        },
        methods: {
            processForm: function() {
        //attempt validating all
                this.$validator.validateAll().then((result) => {
                    if (result) {
            //validation passed succesfully

                       alert('Form validated succesfully');
                    }
                });
            }
        }
    });

The code block is pretty similar. First we see the custom rule we created earlier on, extended it to the default validator and mounted our Vue instance. Let’s move to the methods section and see what we have in our proessForm method. Here we call the $validator.validateAll() function, which is a method exposed by VeeValidate which tries to validate all inputs and then returns a promise. We then check if the validation was succesful and triggered an alert.

If we open our template.html file in a browser, it should work as seen:

Feel free to play with the demo here

Conclusion

In this article, we have seen how to validate form inputs using the template driven approach. VeeValidate has made it very simple to validate form inputs by exposing a v-validate directive as well as giving room to extend / add custom Validators.

When next you need to validate forms in Vue, and you want it template driven, you now know the way to go.

Source:: scotch.io

How to Build a Realtime Chat App with React and GraphQL

By Chris Nwamba

GraphQL and React are a match made in heaven. Their ecosystem provides a lot of tools to simplify common web programming tasks including realtime integrations. In this article, youíre going to learn how to use only React and GraphQL to make a realtime app (precisely a chat app).

What You Will Learn

  • How to setup a React + GraphQL project
  • Using Apollo to interact with a GraphQL server from React
  • Querying and mutating entities
  • Realtime messaging and subscription

I’m assuming you know the basic concepts of GraphQL and React. Therefore, this article will focus on showing you how to build a realtime app with both tools while skipping explanations for basic concepts.

GraphQL, Apollo, Graphcool, Duh…

Yes I understand these terms can be dunting. They were not so easy for me to get along with as well but with practice and knowing the fundamental knowledge, you will start getting a hang of it.

GraphQL

Basically, GraphQL is a query spec that is built around the Graph algorithm. It’s developed by Facebook and it’s so powerful that it seems to be replacing the REST we love. Rather than just sending JSON payloads through REST to a server, then the serverv in-turn queries a database, GraphQL gives you the power to serve these queries right from the client. This way you end up with just what the client needs and not what the REST endpoint exposed.

Apollo

GraphQL is just a spec that you can follow to build your own implementation. But that’s a hard journey. This is why tools like Apollo were built to server as GraphQL clients. From a beginner perspective, you can see it as an SDK for interacting with a GraphQL server that follows a GraphQL spec.

Graphcool

Speaking of servers, the process of setting up one and the tooling involved can also get overwhelming. Sometimes you might even get it wrong, exposing your products to security vulnerabilties. Graphcool is a highly extensive hosted Graphcool server that you can work with. You can manipulate anything on the server using its serverless functions. The service has a free tier that is generous enough to get you into business withoug paying a dime.

Setting Up a React Project

create-react-app has been developers favorite tool for scaffolding React apps. We’re just going to stick to because there is a high chance you know how it works and probably used it before. Scaffold a new project in React by running the following command:

 create-react-app graphql-chat

This would create a new folder named graphql-chat and download all the necessary React files you need to work with.

Update the dependencies in the package.json as follows:

"dependencies": {

  "apollo-client-preset": "^1.0.6",
  "apollo-link-ws": "^1.0.4",
  "graphql": "^0.12.3",
  "graphql-tag": "^2.6.1",
  "react": "^16.2.0",
  "react-apollo": "^2.0.4",
  "react-dom": "^16.2.0",
  "react-scripts": "1.0.17",
  "subscriptions-transport-ws": "^0.9.4"
},

Then run the install command to download all of these files:

npm install
# OR
yarn

We will learn about what each of these dependencies does when we encounter them.

Some global CSS files needs to be included so as to relieve styling concerns from us for this project. Update the head tag in public/index.html to include the following CSS files:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/7.0.0/normalize.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css" />

Setting up a GraphQL Instance

Rather than have a local server running, we can use an existing free hosted service to setup a GraphQL instance. This is not only free but less tasking and easier to get started with. Graphcool is fantastic fo small project and also amazing for large projects when your app grows.

To setup an instance, you need to first install the Graphcool CLI tool. This tool exposes commands for creating new GraphQL servers, updating them, as well as deploying them. It can also be used to manage the Graphcool cloud functions. Run the following command to install:

npm install -g graphcool-framework

Navigate to the React app we just setup through the terminal and start a new Graphool server:

graphcool-framework init server

This command will create a folder in the React project named server. The server command contains type and schema definitions for your GraphQL data. You can refer to Understanding GraphQL API Queries as well as the articles in this search result to learn more about GraphQL fundamentals.

For our chat app, we just need to focus on the types.graphql file generated in the server folder. This is where you tell GraphQl what the structure of your data looks like. It’s known as a type definition. Replace it’s content with the following:

type Chat @model {
  id: ID! @isUnique
  from: String!
  content: String!
  createdAt: DateTime!
}

You need to deploy this schema to the Graphcool server:

graphcool-framework deploy

This will first open a browser for you to setup a Graphcool account and then deploy your instance. You can open the instance from the menu on the top left of your Graphcool dashboard:

Back in the terminal, the process prints some important URL you need to interact with your Graphcool server. Please store this URL where you can refer to them:

Once you have the app deployed, open the playground to test if the deploy process has all your type definition in place:

graphcool-framework playground

Run the following query and mutation in the editor on the left and click the execute button to execute them:

    query FETCH_CHATS{
      allChats{
        from,
        content
      }
    }

    mutation CREATE_CHAT {
      createChat(content: "test", from: "test") {
        content,
        from
      }
    }

The playground would ask you which of the commands you want to run:

Provide GraphQL Instance to React

A React project is ready, and a GraphQL server is cooked. What next? We need to tie them together with all those modules we installed with the package.json file.

Letís start with importing them. Update the src/index.js entry file to import the following dependencies:

    import { ApolloProvider } from 'react-apollo';
    import { ApolloClient } from 'apollo-client';
    import { HttpLink } from 'apollo-link-http';
    import { InMemoryCache } from 'apollo-cache-inmemory';
    import { ApolloLink, split } from 'apollo-client-preset'
    import { WebSocketLink } from 'apollo-link-ws'
    import { getMainDefinition } from 'apollo-utilities'

Right under the imports, configure the WebSocket link. You can do this using the WebSocketLink module:

const wsLink = new WebSocketLink({

  uri: '[Subscriptions API URI]',
  options: {
    reconnect: true
  }
})

The constructor function takes an object with config options. The uri is required and should be the same as the Subscriptions API URI you received after deploying. The options are optional, but we are using the reconnect option to ask WebSocket to try reconnecting after a failed attempt.

We are not just making a WebSocket connection. We also need to setup an HTTP connection for a request-response operations. Add this right below the WebSocket link setup:

const httpLink = new HttpLink({ uri: '[SIMPLE API URI]' })

The same as the WebSocketLink constructor but uses the Simple API URI. We donít need to pass in any configuration option.

At this point, we have two links. How do we tell the server when to which. This is achievable using the split method we imported above:

const link = split(

  ({ query }) => {
    const { kind, operation } = getMainDefinition(query)
    return kind === 'OperationDefinition' && operation === 'subscription'
  },
  wsLink,
  httpLink,
)

The split method takes three arguments. The first is a test that returns a boolean. If the boolean value is true, the request is forwarded to the second (wsLink) argument. If false, itís forwarded to the third (httpLink) argument.

Now we can create an Apollo client with the returned link:

const client = new ApolloClient({

  link,
  cache: new InMemoryCache()
})

You can make requests directly to your server using the URLs provided. This is a bit messier than using a wrapper library that provides functionalities to simplify server interaction. Apollo is one of such libraries.

Provide the client using the AppProvider component:

ReactDOM.render(

  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById('root')
);

Querying the GraphQL Server

With the tie between our React app and our GraphQL set, itís time to start querying the database and displaying the data in the browser.

Update the src/App.js to setup a query:

import React, { Component } from 'react';

// Import GraphQL helpers
import { graphql } from 'react-apollo';
import gql from 'graphql-tag';

// App component styles
import './App.css';

class App extends Component {
  state = {
    from: 'anonymous',
    content: ''
  };
  componentDidMount() {
    // Get username form prompt
    // when page loads
    const from = window.prompt('username');
    from && this.setState({ from });
  }
  render() {
    // Coming up next
  }
}

const ALL_CHATS_QUERY = gql`
  query AllChatsQuery {
    allChats {
      id
      createdAt
      from
      content
    }
  }
`;

export default graphql(ALL_CHATS_QUERY, { name: 'allChatsQuery' })(App);

Letís breakdown whatís going on here:

  • We first import graphql and gql. This libraries will help setup and parse the query respectively.
  • At the end of the component class definition, we create the query. It looks exactly like what we did in the playground but wrapped with the gql method using template tagging.
  • The graphql HOC is then used to expose the result of this query to the App componentís props.

You can now render the query in the DOM through the props:

 // Chatbox UI component
import Chatbox from './components/Chatbox';

    class App extends Component {

      //...

      render() {
        const allChats = this.props.allChatsQuery.allChats || [];
        return (
          <div className="">
            <div className="container">
              <h2>Chats</h2>
              {allChats.map(message => (
                <Chatbox key={message.id} message={message} />
              ))}
            </div>
          </div>
        );
      }
    }

    // ...

    export default graphql(ALL_CHATS_QUERY, { name: 'allChatsQuery' })(App);

The render method iterates over each of the query results and prints them to the screen using the Chatbox component. This is what the component looks like in components/Chatbox.js:

import React from 'react';
import './Chatbox.css'
    const Chatbox = ({message}) => (
      <div className="chat-box">
        <div className="chat-message">
          <h5>{message.from}</h5>
          <p>
            {message.content}
          </p>
        </div>
      </div>
    );
    export default Chatbox;

You can refer to the repo to get the basic styles for Chatbox.css and App.css. Here is what the current output should look like when you run:

Remember I added some data via the playground which is why I have some messages in the view.

Creating New Messages

Mutations in GraphQL are used to create, edit, and delete values from your database. Where a query is the R (Read) in CRUD, a mutation can be the CRD (Create, Update, Delete). We are already able to read existing messages in our chat app. Next thing we should worry about is creating those messages from our React app.

Just like the way we created a query, we can also create a mutation:

import { graphql, compose } from 'react-apollo';

    // App component ...

    const CREATE_CHAT_MUTATION = gql`
      mutation CreateChatMutation($content: String!, $from: String!) {
        createChat(content: $content, from: $from) {
          id
          createdAt
          from
          content
        }
      }
    `;

    export default compose(
      graphql(ALL_CHATS_QUERY, { name: 'allChatsQuery' }),
      graphql(CREATE_CHAT_MUTATION, { name: 'createChatMutation' })
    )(App);

The mutation is a lot like a query but receives parameters ó content and from. We need to wrap the App component with both this mutation and our existing query. For this reason, we also import the compose method and use this method to wrap both HOCs.

In the render method, we can have an input element that collects these message contents:

render() {
   const allChats = this.props.allChatsQuery.allChats || [];
       return (
          <div className="">
            <div className="container">
              <h2>Chats</h2>
              {allChats.map(message => (
                <Chatbox key={message.id} message={message} />
              ))}

              {/* Message content input */}
              <input
                value={this.state.content}
                onChange={e => this.setState({ content: e.target.value })}
                type="text"
                placeholder="Start typing"
                onKeyPress={this._createChat}
              />
            </div>
          </div>
        );
      }
    }

The input triggers an event at every keyPress, and this event calls the _createChat method. Here is the definition of this method in the App class:

_createChat = async e => {
     if (e.key === 'Enter') {
       const { content, from } = this.state;
        await this.props.createChatMutation({
          variables: { content, from }
        });
        this.setState({ content: '' });
      }
    };

We only want to run the mutation when the enter key is pressed. Notice how the createChatMutation is also exposed on the props and the variable is passed in as an object to the mutation method.

When you send a new message, nothing happens until you reload:

This calls for realtime updates.

Setting up Realtime Subscriptions

Subscriptions in GraphQL are used to listen for changes by connected clients. These clients can act on these changes accordingly. Probably by updating the user interface with the changed data or even sending push notifications. The underlying technology that powers subscriptions is the well known WebSockets.

Add this method the the App class to setup a subscription:

_subscribeToNewChats = () => {
      this.props.allChatsQuery.subscribeToMore({
          document: gql`
            subscription {
              Chat(filter: { mutation_in: [CREATED] }) {
                node {
                  id
                  from
                  content
                  createdAt
                }
              }
            }
          `,
          updateQuery: (previous, { subscriptionData }) => {
            const newChatLinks = [
              ...previous.allChats,
              subscriptionData.data.Chat.node
            ];
            const result = {
              ...previous,
              allChats: newChatLinks
            };
            return result;
          }
        });
      };

The allChatsQuery exposes a subscribeToMore method. Once this method is called, it opens up a channel for realtime communication. The method takes an object which we can define the query document and an updateQuery method.

The document defines a subscription and listens for when a mutation occurs on the Chat entity before triggering an event. The update method receives the old and new value, and we are using these new value to update the old value.

You can kick off this subscription in the componentDidMount lifecycle method:

this._subscribeToNewChats();

Now run once more, and you should have a running chat app:

Further Learning

You already learned a lot, but there is more to GraphQL. You can dig our Scotch articles on GraphQL to discover more. The How to GraphQL tutorials are also excellent and walks you through steps on learning about the GraphQL fundamentals. Feel free to hit the comments section if you run into issues or find a bug.

Source:: scotch.io

Build User Registration with Node, React, and Okta

By Lee Brandt

Application Listing Screen

Today’s internet users expect a personalized experience. Developers must learn to develop websites that provide that personalized experience while keeping their user’s information private. Modern web applications also tend to have a server-side API and a client-side user interface. it can be challenging to get make both ends aware of the currently logged in user. In this tutorial, I will walk you through setting up a Node API that feeds a React UI, and build a user registration that keeps the user’s information private and personal.

In this tutorial, I won’t use any state management libraries like Redux or ReduxThunk. In a more robust application, you’ll probably want to do that, but it will be easy to wire up Redux and ReduxThunk and then add the fetch statements used here as your thunks. For the sake of simplicity, and to keep this article focused on adding user management, I’ll be adding fetch statements into componentDidMount functions.

Install the Node and React Prerequisites

To set up the base application, make sure you have these basic tools installed:

  • Node (8+)
  • npm (5+)
  • create-react-app (npm package)
  • express-generator (npm package)

You’ll also need an Okta developer account.

To install Node and npm, you can follow the instructions for your operating system at http://nodejs.org.

Then just install the two npm packages with the npm command line:

npm i -g create-react-app express-generator

Now you’re ready to set up the basic application structure.

Scaffold the Base Application

Go to the folder where you want your application to live and create a new folder for it:

mkdir MembershipSample
cd MembershipSample
express api
create-react-app client

This will create two folders in the MembershipSample folder called api and client, with a NodeJS and Express application in the api folder and a base React application in the client folder. So your folder structure will look like:

  • MembershipSample
    • api
    • client

To make this next part easier, open two terminals or terminal tabs; one to the express app folder api and the other to the React app folder client.

By default, the React app and the Node app will both run on port 3000 in development, so you’ll need to get the API to run on a different port and then proxy it in the client app.

In the api folder, open the /bin/www file and change the port the API will be running on to 3001.

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '3001');
app.set('port', port);

Then set up the proxy for the API in the client application so that you can still call /api/{resource} and have it proxied from port 3000 to port 3001. In the client/package.json file, add the proxy setting below name:

"name": "client",
"proxy": "http://localhost:3001"

Lastly, don’t forget to run npm install or yarn install for each subfolder (api and client) to ensure that the dependencies are installed.

You can now run both applications by running npm start or yarn start in the appropriate folders for the API and the client application.

Add an Okta Application

If you haven’t already done so, create a free forever developer account at https://developer.okta.com/signup/.

Once you’ve registered, click on Applications in the top menu. Then click the Add Application button.

You will then be taken to the application creation wizard. Choose the Single-Page App button and click Next at the bottom.

Single Page App Screen

On the next screen, you will see the default settings provided by the single-page application template. Change the name of the application to something more descriptive, like “Membership Application”. Also, change the base URIs and the login redirect URIs settings to use port 3000 because that is where your application will be running. The rest of the default settings are fine.

Single Page App Settings Screen

Then click the Done button at the bottom.

Once the application has been created, select it from the applications listing, and click on the general tab to view the general settings for your application.

General Settings Tab

At the bottom, you will see a “Client ID” setting (yours won’t be blurred out, obviously). Copy this to use in your React application. You will also need your Okta organization URL, which you can find at the top left of the dashboard page. It will probably look something like “https://dev-XXXXXX.oktapreview.com”.

Add Authentication to the ReactJS Application

Now that the application is created, add authentication using Okta by adding a couple of npm dependencies. From the client folder run:

npm install @okta/okta-auth-js @okta/okta-react react-router-dom --save

Or, if you’re using the yarn package manager:

yarn add @okta/okta-auth-js @okta/okta-react react-router-dom

Add a file to the client/src' folder calledapp.config.js`. The contents of the file are:

export default {
  url: '{yourOktaOrgUrl}',
  issuer: '{yourOktaOrgUrl}/oauth2/default',
  redirect_uri: window.location.origin + '/implicit/callback',
  client_id: '{yourClientID}'
}

Then, setup the index.js file to use the React Router and Okta’s React SDK. When the index.js file is complete, it will look like this:

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import { Security } from '@okta/okta-react';

import './index.css';
import config from './app.config';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

function onAuthRequired({ history }) {
  history.push('/login');
}

ReactDOM.render(
  <Router>
    <Security issuer={config.issuer}
      client_id={config.client_id}
      redirect_uri={config.redirect_uri}
      onAuthRequired={onAuthRequired}>
      <App />
    </Security>
  </Router>,
  document.getElementById('root')
);
registerServiceWorker();

Once complete, you will have added the BrowserRouter component (aliased as “Router”) from the React Router, and the Security component from Okta’s React SDK. Also that the app.config.js file is imported as “config” so that you can use the config values in the properties required by the Security component.

You will also have surrounded the App component with the Router and Security components, passing in the values specified. The onAuthRequired method, simply tells Okta’s React SDK that when somebody tries to access a secure route and they are not logged in, redirect them to the login page.

Everything else will have come from the create-react-app command you ran previously.

Add Pages to the ReactJS App

Before adding any routes to the React app, create some components to handle the routes you want to add.

Add a components folder to the client/src folder. This is where all your components will live and the easiest way to organize them. Then create a home folder for your home page components. For now there will be just one, but there may be more components used only for the home page later. Add a HomePage.js file to the folder with the following contents:

import React from 'react';

export default class HomePage extends React.Component{
  render(){
    return(
      <h1>Home Page</h1>
    );
  }
}

This is all you really need for the home page at the moment. The most important point is to make the HomePage component a class type. Even though right now it only contains a single h1 tag, it is meant to be a “page”, meaning it will likely contain other components, so it’s important that it be a container component.

Next, create an auth folder in components. This is where all components that have to do with authentication will live. In that folder, create a LoginForm.js file.

The first thing to note is that you’ll be using the withAuth higher-order component from Okta’s React SDK to wrap the entire login form. This adds a prop to the component called auth, making it possible to access things like the isAuthenticated and redirect functions on that higher-order component.

The code for the LoginForm component is as follows:

import React from 'react';
import OktaAuth from '@okta/okta-auth-js';
import { withAuth } from '@okta/okta-react';

export default withAuth(class LoginForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      sessionToken: null,
      error: null,
      username: '',
      password: ''
    }

    this.oktaAuth = new OktaAuth({ url: props.baseUrl });

    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleUsernameChange = this.handleUsernameChange.bind(this);
    this.handlePasswordChange = this.handlePasswordChange.bind(this);
  }

  handleSubmit(e) {
    e.preventDefault();
    this.oktaAuth.signIn({
      username: this.state.username,
      password: this.state.password
    })
      .then(res => this.setState({
        sessionToken: res.sessionToken
      }))
      .catch(err => {
        this.setState({error: err.message});
        console.log(err.statusCode + ' error', err)
      });
  }

  handleUsernameChange(e) {
    this.setState({ username: e.target.value });
  }

  handlePasswordChange(e) {
    this.setState({ password: e.target.value });
  }

  render() {
    if (this.state.sessionToken) {
      this.props.auth.redirect({ sessionToken: this.state.sessionToken });
      return null;
    }

    const errorMessage = this.state.error ? 
    <span className="error-message">{this.state.error}</span> : 
    null;

    return (
      <form onSubmit={this.handleSubmit}>
        {errorMessage}
        <div className="form-element">
          <label>Username:</label>
          <input
            id="username" type="text"
            value={this.state.username}
            onChange={this.handleUsernameChange} />
        </div>

        <div className="form-element">
          <label>Password:</label>
          <input
            id="password" type="password"
            value={this.state.password}
            onChange={this.handlePasswordChange} />
        </div>
        <input id="submit" type="submit" value="Submit" />
      </form>
    );
  }
});

The other thing of note here is the OktaAuth library being imported. This is the base library for doing things like signing in using the Okta application you created previously. You’ll notice an OktaAuth object being created in the constructor that gets a property of baseUrl passed to it. This is the URL for the issuer that is in your app.config.js file. The LoginForm component is meant to be contained in another component, so you’ll have to create a LoginPage.js file to contain this component. You’ll use the withAuth higher-order component again, to get access to the isAuthenticated function. The contents of LoginPage.js will be:

import React, { Component } from 'react';
import { Redirect } from 'react-router-dom';
import LoginForm from './LoginForm';
import { withAuth } from '@okta/okta-react';

export default withAuth(class Login extends Component {
  constructor(props) {
    super(props);
    this.state = { authenticated: null };
    this.checkAuthentication = this.checkAuthentication.bind(this);
    this.checkAuthentication();
  }

  async checkAuthentication() {
    const authenticated = await this.props.auth.isAuthenticated();
    if (authenticated !== this.state.authenticated) {
      this.setState({ authenticated });
    }
  }

  componentDidUpdate() {
    this.checkAuthentication();
  }

  render() {
    if (this.state.authenticated === null) return null;
    return this.state.authenticated ?
      <Redirect to={{ pathname: '/profile' }} /> :
      <LoginForm baseUrl={this.props.baseUrl} />;
  }
});

Although it’s a bit less than what’s in the login form component, there are still some important pieces to point out here.

Again, you’re using the withAuth higher-order component. This will be a recurring theme for every component that needs to use Okta’s authentication or authorization process. In this case, it’s primarily used to get the isAuthenticated function. The checkAuthentication() method is executed in the constructor and in the componentDidUpdate lifecycle method to ensure that when the component is created it is checked and every subsequent change to the component checks again.

When isAuthenticated returns true, then it is set in the component’s state. It is then checked in the render method to decide whether to show the LoginForm component, or to redirect to the user’s profile page, a component you’ll create next.

Now create the ProfilePage.js component inside the auth folder. The contents of the component are:

import React from 'react';
import { withAuth } from '@okta/okta-react';

export default withAuth(class ProfilePage extends React.Component {
  constructor(props){
    super(props);
    this.state = { user: null };
    this.getCurrentUser = this.getCurrentUser.bind(this);
  }

  async getCurrentUser(){
    this.props.auth.getUser()
      .then(user => this.setState({user}));
  }

  componentDidMount(){
    this.getCurrentUser();
  }

  render() {
    if(!this.state.user) return null;
    return (
      <section className="user-profile">
        <h1>User Profile</h1>
        <div>
          <label>Name:</label>
          <span>{this.state.user.name}</span>
        </div>
      </section>

    )
  }
});

The withAuth component here gives you access to the getUser function. Here, it’s been called from componentDidMount which is a common place for pulling data that will be used in the render method. The only odd thing you might see is the first line of the render method that renders nothing until there is actually a user returned from the getUser asynchronous call. Once there is a user in the state, it then renders the profile content, which in this case is just displaying the currently logged in user’s name.

Next, you’ll add a registration component. This could be done just like the login form, where there is a LoginForm component that is contained in a LoginPage component. In order to demonstrate another way to display this, you’ll just create a RegistrationForm component that will be the main container component. Create a RegistrationForm.js file in the auth folder with the following content:

import React from 'react'; 
import OktaAuth from '@okta/okta-auth-js';
import { withAuth } from '@okta/okta-react';

import config from '../../app.config';

export default withAuth(class RegistrationForm extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      firstName: '',
      lastName: '',
      email: '',
      password: '',
      sessionToken: null
    };
    this.oktaAuth = new OktaAuth({ url: config.url });
    this.checkAuthentication = this.checkAuthentication.bind(this);
    this.checkAuthentication();

    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleFirstNameChange = this.handleFirstNameChange.bind(this);
    this.handleLastNameChange = this.handleLastNameChange.bind(this);
    this.handleEmailChange = this.handleEmailChange.bind(this);
    this.handlePasswordChange = this.handlePasswordChange.bind(this);    
  }

  async checkAuthentication() {
    const sessionToken = await this.props.auth.getIdToken();
    if (sessionToken) {
      this.setState({ sessionToken });
    }
  }

  componentDidUpdate() {
    this.checkAuthentication();
  }

  handleFirstNameChange(e){
    this.setState({firstName:e.target.value});
  }
  handleLastNameChange(e) {
    this.setState({ lastName: e.target.value });
  }
  handleEmailChange(e) {
    this.setState({ email: e.target.value });
  }
  handlePasswordChange(e) {
    this.setState({ password: e.target.value });
  }

  handleSubmit(e){
    e.preventDefault();
    fetch('/api/users', { 
      method: 'POST', 
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(this.state)
    }).then(user => {
      this.oktaAuth.signIn({
        username: this.state.email,
        password: this.state.password
      })
      .then(res => this.setState({
        sessionToken: res.sessionToken
      }));
    })
    .catch(err => console.log);
  }

  render(){
    if (this.state.sessionToken) {
      this.props.auth.redirect({ sessionToken: this.state.sessionToken });
      return null;
    }

    return(
      <form onSubmit={this.handleSubmit}>
        <div className="form-element">
          <label>Email:</label>
          <input type="email" id="email" value={this.state.email} 
          onChange={this.handleEmailChange}/>
        </div>
        <div className="form-element">
          <label>First Name:</label>
          <input type="text" id="firstName" value={this.state.firstName} 
          onChange={this.handleFirstNameChange} />
        </div>
        <div className="form-element">
          <label>Last Name:</label>
          <input type="text" id="lastName" value={this.state.lastName} 
          onChange={this.handleLastNameChange} />
        </div>
        <div className="form-element">
          <label>Password:</label>
          <input type="password" id="password" value={this.state.password} 
          onChange={this.handlePasswordChange} />
        </div>
        <input type="submit" id="submit" value="Register"/>
      </form>
    );
  }

});

This component looks a lot like the LoginForm component with the exception that it calls the Node API (that you’ll build in a moment) that will handle doing the registration. Once the registration is completed by the Node API, the component logs the newly created user in, and the render method (when it sees a session token in the state) redirects the user to the home page of the application.

You may also notice the sessionToken property on the component’s state. This is set by the handleSubmit() function for the purpose of handling the login if the registration is successful. Then it is also used by the render() method to do the redirect once the login has completed, and a token has been received.

Add Routes to the React App

First, add a navigation component for the routes you’ll be adding. In the client/src/components folder, add a folder called shared. This will be the place where all components that are used in several places in the application will be located. In that new folder, add a file called Navigation.js. The file contains a basic component with links to all the pages in the app.

You’ll need to wrap the navigation component in the withAuth higher-order component. That way, you can check to see if there is an authenticated user and display the login or logout button as appropriate.

import React from 'react';
import { Link } from 'react-router-dom';
import { withAuth } from '@okta/okta-react';

export default withAuth(class Navigation extends React.Component {
  constructor(props) {
    super(props);
    this.state = { authenticated: null };
    this.checkAuthentication = this.checkAuthentication.bind(this);
    this.checkAuthentication();
  }

  async checkAuthentication() {
    const authenticated = await this.props.auth.isAuthenticated();
    if (authenticated !== this.state.authenticated) {
      this.setState({ authenticated });
    }
  }

  componentDidUpdate() {
    this.checkAuthentication();
  }

  render() {
    if (this.state.authenticated === null) return null;
    const authNav = this.state.authenticated ?
      <ul className="auth-nav">
        <li><a href="javascript:void(0)" onClick={this.props.auth.logout}>Logout</a></li>
        <li><Link to="/profile">Profile</Link></li>
      </ul> :
      <ul className="auth-nav">
        <li><a href="javascript:void(0)" onClick={this.props.auth.login}>Login</a></li>
        <li><Link to="/register">Register</Link></li>
      </ul>;
    return (
      <nav>
        <ul>
          <li><Link to="/">Home</Link></li>
          {authNav}
        </ul>
      </nav>
    )
  }
});

Now that you have components available to handle all the routes, create the routes to go with them. Update the App.js file so that the final version looks like:

import React, { Component } from 'react';
import { Route } from 'react-router-dom';
import { SecureRoute, ImplicitCallback } from '@okta/okta-react';

import Navigation from './components/shared/Navigation';
import HomePage from './components/home/HomePage';
import RegistrationForm from './components/auth/RegistrationForm';
import config from './app.config';
import LoginPage from './components/auth/LoginPage';
import ProfilePage from './components/auth/ProfilePage';
import './App.css';

export default class App extends Component {
  render() {
    return (
      <div className="App">
        <Navigation />
        <main>
          <Route path="/" exact component={HomePage} />
          <Route path="/login" render={() => <LoginPage baseUrl={config.url} />} />
          <Route path="/implicit/callback" component={ImplicitCallback} />
          <Route path="/register" component={RegistrationForm} />
          <SecureRoute path="/profile" component={ProfilePage} />
        </main>
      </div>
    );
  }
}

There are a couple of things of note here. The import of the SecureRoute and ImplicitCallback components from Okta’s React SDK. The ImplicitCallback component handles the callback from the authentication flow to ensure there is an endpoint within the React application to catch the return call from Okta. The SecureRoute component allows you to secure any route and redirect unauthenticated users to the login page.

The Route component from React Router does exactly what you’d expect: it takes a path that the user has navigated to and sets a component to handle that route. The SecureRoute component does an extra check to ensure the user is logged in before allowing access to that route. If they are not then the onAuthRequired function in index.js will be called to force the user to the login page.

The only other really odd-looking thing here is the route for the login path. Instead of simply setting a component to handle the path, it runs a render method that renders the LoginPage component and sets the baseUrl from the configuration.

Add API Endpoints to the Node App

You may remember that the Node API is doing the registration, so you’ll need to add the endpoint to the Node app to handle that call. To do that, you’ll need to add Okta’s Node SDK. From the ‘api’ folder run:

npm install @okta/okta-sdk-nodejs --save

Then, you’ll change the users.js file in api/routes. The file will look like:

const express = require('express');
const router = express.Router();
const oktaClient = require('../lib/oktaClient');

/* Create a new User (register). */
router.post('/', (req, res, next) => {
  if (!req.body) return res.sendStatus(400);
  const newUser = {
    profile: {
      firstName: req.body.firstName,
      lastName: req.body.lastName,
      email: req.body.email,
      login: req.body.email
    },
    credentials: {
      password: {
        value: req.body.password
      }
    }
  };
  oktaClient.createUser(newUser)
    .then(user => {
      res.status(201);
      res.send(user);
    })
    .catch(err => {
      res.status(400);
      res.send(err);
    })
});

module.exports = router;

The biggest things of note here are the importing of the lib/oktaClient (which you’ll add in a moment), the call to the createUser function on oktaClient, and the shape of the newUser object. The shape of the newUser object is documented in Okta’s API documentation.

For your Node application to make calls to your Okta application, it will need an API token. To create one, go into your Okta developer dashboard, hover over the API menu option and click on Tokens.

Okta API Tokens Screen

From there click Create Token. Give the token a name like “Membership” and click Create Token.

Create Token Screen

Copy the token to a safe location for use later.

Create a file called oktaClient.js in a new folder called lib in the Node application. The file will configure a Client object from Okta’s Node SDK using the API token you just created like this:

const okta = require('@okta/okta-sdk-nodejs');

const client = new okta.Client({
  orgUrl: '{yourOktaOrgUrl}',
  token: '{yourApiToken}'
});

module.exports = client;

In the app.js file at the root of the Node app, update the file to have all calls route to /api/. You’ll see a section below the block of app.use statements. Change the route set up so that it looks like this:

app.use('/api', index);
app.use('/api/users', users);

If your Node app is still running, you will need to stop the app (with CTRL+C) and rerun it (with npm start) for the updates to take effect.

Even though the site still needs some serious style love, you will now be able to register users, log in with the newly created user and get the logged in user’s profile for display on the profile page!

User Profile Page

Learn More

If you want to learn more about the technologies used in this articles, you can check out the documentation for:

Also, check out other articles using Okta for authentication:

As always, if you have questions, comments, or concerns about the article you can post a comment below, email me at lee.brandt@okta.com or post your questions to the developer forums. For more articles and tutorials, follow us on Twitter @OktaDev.

Source:: scotch.io