diff --git a/challenges/05-apis-and-microservices/api-and-microservice-projects.json b/challenges/05-apis-and-microservices/api-and-microservice-projects.json index 56ae62fb6a..a0f430e438 100644 --- a/challenges/05-apis-and-microservices/api-and-microservice-projects.json +++ b/challenges/05-apis-and-microservices/api-and-microservice-projects.json @@ -36,9 +36,9 @@ "id": "bd7158d8c443edefaeb5bdef", "title": "Timestamp Microservice", "description": [ - "Build a full stack JavaScript app that is functionally similar to this: https://curse-arrow.gomix.me/.", - "Working on this project will involve you writing your code on Gomix on our starter project. After completing this project you can copy your public gomix url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.", - "Start this project on Gomix using this link or clone this repository on GitHub! If you use Gomix, remember to save the link to your project somewhere safe!" + "Build a full stack JavaScript app that is functionally similar to this: https://curse-arrow.glitch.me/.", + "Working on this project will involve you writing your code on Glitch on our starter project. After completing this project you can copy your public glitch url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.", + "Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!" ], "challengeSeed": [], "tests": [ @@ -72,9 +72,9 @@ "id": "bd7158d8c443edefaeb5bdff", "title": "Request Header Parser Microservice", "description": [ - "Build a full stack JavaScript app that is functionally similar to this: https://dandelion-roar.gomix.me/.", - "Working on this project will involve you writing your code on Gomix on our starter project. After completing this project you can copy your public gomix url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.", - "Start this project on Gomix using this link or clone this repository on GitHub! If you use Gomix, remember to save the link to your project somewhere safe!" + "Build a full stack JavaScript app that is functionally similar to this: https://dandelion-roar.glitch.me/.", + "Working on this project will involve you writing your code on Glitch on our starter project. After completing this project you can copy your public glitch url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.", + "Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!" ], "challengeSeed": [], "tests": [ @@ -100,9 +100,9 @@ "id": "bd7158d8c443edefaeb5bd0e", "title": "URL Shortener Microservice", "description": [ - "Build a full stack JavaScript app that is functionally similar to this: https://thread-paper.gomix.me/.", - "Working on this project will involve you writing your code on Gomix on our starter project. After completing this project you can copy your public gomix url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.", - "Start this project on Gomix using this link or clone this repository on GitHub! If you use Gomix, remember to save the link to your project somewhere safe!" + "Build a full stack JavaScript app that is functionally similar to this: https://thread-paper.glitch.me/.", + "Working on this project will involve you writing your code on Glitch on our starter project. After completing this project you can copy your public glitch url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.", + "Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!" ], "challengeSeed": [], "tests": [ @@ -136,9 +136,9 @@ "id": "bd7158d8c443edefaeb5bdee", "title": "Exercise Tracker", "description": [ - "Build a full stack JavaScript app that is functionally similar to this: https://fuschia-custard.gomix.me/.", - "Working on this project will involve you writing your code on Gomix on our starter project. After completing this project you can copy your public gomix url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.", - "Start this project on Gomix using this link or clone this repository on GitHub! If you use Gomix, remember to save the link to your project somewhere safe!" + "Build a full stack JavaScript app that is functionally similar to this: https://fuschia-custard.glitch.me/.", + "Working on this project will involve you writing your code on Glitch on our starter project. After completing this project you can copy your public glitch url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.", + "Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!" ], "challengeSeed": [], "tests": [ @@ -180,9 +180,9 @@ "id": "bd7158d8c443edefaeb5bd0f", "title": "File Metadata Microservice", "description": [ - "Build a full stack JavaScript app that is functionally similar to this: https://purple-paladin.gomix.me/.", - "Working on this project will involve you writing your code on Gomix on our starter project. After completing this project you can copy your public gomix url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.", - "Start this project on Gomix using this link or clone this repository on GitHub! If you use Gomix, remember to save the link to your project somewhere safe!" + "Build a full stack JavaScript app that is functionally similar to this: https://purple-paladin.glitch.me/.", + "Working on this project will involve you writing your code on Glitch on our starter project. After completing this project you can copy your public glitch url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.", + "Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!" ], "challengeSeed": [], "tests": [ diff --git a/challenges/05-apis-and-microservices/basic-node-and-express.json b/challenges/05-apis-and-microservices/basic-node-and-express.json index 8f96192d71..ad8bc8ae08 100644 --- a/challenges/05-apis-and-microservices/basic-node-and-express.json +++ b/challenges/05-apis-and-microservices/basic-node-and-express.json @@ -17,7 +17,7 @@ [ "", "", - "Working on these challenges will involve you writing your code on Gomix on our starter project. After completing each challenge you can copy your public gomix url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.
Start this project on Gomix using this link or clone this repository on GitHub! If you use Gomix, remember to save the link to your project somewhere safe!", + "Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.
Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!", "" ] ], @@ -33,7 +33,7 @@ "id": "587d7fb0367417b2b2512bed", "title": "Meet the Node console", "description": [ - "During the development process, is important to be able to check what’s going on in your code. Node is just a javascript environment. Like client side javascript, you can use the console to display useful debug information. On your local machine, you would see the console output in a terminal. On Gomix you can open the logs in the lower part of the screen. You can toggle the log panel if you push the button ‘Logs’ (top-left, under the app name).", + "During the development process, is important to be able to check what’s going on in your code. Node is just a javascript environment. Like client side javascript, you can use the console to display useful debug information. On your local machine, you would see the console output in a terminal. On Glitch you can open the logs in the lower part of the screen. You can toggle the log panel if you push the button ‘Logs’ (top-left, under the app name).", "To get started, just put the classic Hello World in the console. We recommend to keep the log panel open while working at these challenges. Reading the logs you can be aware of the nature of the errors that may occur." ], "challengeSeed": [], @@ -52,12 +52,12 @@ "id": "587d7fb0367417b2b2512bee", "title": "Start a Working Express Server", "description": [ - "In the first two lines of the file myApp.js you can see how it’s easy to create an Express app object. This object has several methods, and we will learn many of them in these challenges. One fundamental method is app.listen(). It tells your server to listen on a given port, putting it in running state. You can see it at the bottom of the file. It is inside comments because for testing reasons we need the app to be running in background. All the code that you may want to add goes between these two fundamental parts. Gomix stores the port number in the environemet variable process.env.PORT. Its value is 3000.", + "In the first two lines of the file myApp.js you can see how it’s easy to create an Express app object. This object has several methods, and we will learn many of them in these challenges. One fundamental method is app.listen(). It tells your server to listen on a given port, putting it in running state. You can see it at the bottom of the file. It is inside comments because for testing reasons we need the app to be running in background. All the code that you may want to add goes between these two fundamental parts. Glitch stores the port number in the environemet variable process.env.PORT. Its value is 3000.", "Let’s serve our first string ! In Express, routes takes the following structure: app.METHOD(PATH, HANDLER). METHOD is an http method in lowercase. PATH is a relative path on the server (it can be a string, or even a regular expression). HANDLER is a function that Express calls when the route is matched.", "Handlers take the form function(req, res) {...}, where req is the request object, and res is the response object. For example, the handler", "
function(req, res) {
res.send('Response String');
}
", "will serve the string 'Response String'.", - "Use the app.get() method to serve the string Hello Express, to GET requests matching the / root path. Be sure that your code works by looking at the logs, then see the results in your browser, clicking the button ‘Show Live’ in the Gomix UI." + "Use the app.get() method to serve the string Hello Express, to GET requests matching the / root path. Be sure that your code works by looking at the logs, then see the results in your browser, clicking the button ‘Show Live’ in the Glitch UI." ], "challengeSeed": [], "tests": [ diff --git a/challenges/05-apis-and-microservices/managing-packages-with-npm.json b/challenges/05-apis-and-microservices/managing-packages-with-npm.json index 283a9b8e49..75fbcf88d2 100644 --- a/challenges/05-apis-and-microservices/managing-packages-with-npm.json +++ b/challenges/05-apis-and-microservices/managing-packages-with-npm.json @@ -17,7 +17,7 @@ [ "", "", - "Working on these challenges will involve you writing your code on Gomix on our starter project. After completing each challenge you can copy your public gomix url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.
Start this project on Gomix using this link or clone this repository on GitHub! If you use Gomix, remember to save the link to your project somewhere safe!", + "Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.
Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!", "" ] ], @@ -35,11 +35,11 @@ "description": [ "The file package.json is the center of any Node.js project or npm package. It stores information about your project just like the -section in a HTML document describes the content of a webpage. The package.json consists of a single JSON-object where information is stored in \"key\": value-pairs. There are only two required fields in a minimal package.json - name and version - but it’s a good practice to provide additional information about your project that could be useful to future users or maintainers.", "The author-field", - "If you go to the Gomix project that you set up previously and look at on the left side of your screen, you’ll find the file tree where you can see an overview of the various files in your project. Under the file tree’s back-end section, you’ll find package.json - the file that we’ll be improving in the next couple of challenges.", + "If you go to the Glitch project that you set up previously and look at on the left side of your screen, you’ll find the file tree where you can see an overview of the various files in your project. Under the file tree’s back-end section, you’ll find package.json - the file that we’ll be improving in the next couple of challenges.", "One of the most common pieces of information in this file is the author-field that specifies who’s the creator of a project. It can either be a string or an object with contact details. The object is recommended for bigger projects but in our case, a simple string like the following example will do.", "\"author\": \"Jane Doe\",", "Instructions", - "Add your name to the author-field in the package.json of your Gomix project.", + "Add your name to the author-field in the package.json of your Glitch project.", "Remember that you’re writing JSON.", "All field-names must use double-quotes (\"), e.g. \"author\"", "All fields must be separated with a comma (,)" @@ -65,7 +65,7 @@ "Regardless of what you plan for your project, a description is definitely recommended. Let’s add something similar to this:", "\"description\": \"A project that does something awesome\",", "Instructions", - "Add a description to the package.json in your Gomix project.", + "Add a description to the package.json in your Glitch project.", "Remember to use double-quotes for field-names (\") and commas (,) to separate fields." ], "challengeSeed": [], @@ -89,7 +89,7 @@ "\"keywords\": [ \"descriptive\", \"related\", \"words\" ],", "As you can see, this field is structured as an array of double-quoted strings.", "Instructions", - "Add an array of suitable strings to the keywords-field in the package.json of your Gomix project.", + "Add an array of suitable strings to the keywords-field in the package.json of your Glitch project.", "One of the keywords should be freecodecamp." ], "challengeSeed": [], @@ -123,7 +123,7 @@ "Example", "\"license\": \"MIT\",", "Instructions", - "Fill the license-field in the package.json of your Gomix project as you find suitable." + "Fill the license-field in the package.json of your Glitch project as you find suitable." ], "challengeSeed": [], "tests": [ @@ -145,7 +145,7 @@ "Example", "\"version\": \"1.2\",", "Instructions", - "Add a version to the package.json in your Gomix project." + "Add a version to the package.json in your Glitch project." ], "challengeSeed": [], "tests": [ diff --git a/challenges/05-apis-and-microservices/mongodb-and-mongoose.json b/challenges/05-apis-and-microservices/mongodb-and-mongoose.json index a3900e0627..1d9e76f51f 100644 --- a/challenges/05-apis-and-microservices/mongodb-and-mongoose.json +++ b/challenges/05-apis-and-microservices/mongodb-and-mongoose.json @@ -17,7 +17,7 @@ [ "", "", - "Working on these challenges will involve you writing your code on Gomix on our starter project. After completing each challenge you can copy your public gomix url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.
Start this project on Gomix using this link or clone this repository on GitHub! If you use Gomix, remember to save the link to your project somewhere safe!", + "Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.
Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!", "" ] ], @@ -68,7 +68,7 @@ "more fields, use simple validators like required or unique,", "and set default values. See the mongoose docs.", "[C]RUD Part I - CREATE", - "Note: Gomix is a real server, and in real servers the interactions with the db happen in handler functions. These function are executed when some event happens (e.g. someone hits an endpoint on your API). We’ll follow the same approach in these exercises. The done() function is a callback that tells us that we can proceed after completing an asynchronous operation such as inserting, searching, updating or deleting. It’s following the Node convention and should be called as done(null, data) on success, or done(err) on error.", + "Note: Glitch is a real server, and in real servers the interactions with the db happen in handler functions. These function are executed when some event happens (e.g. someone hits an endpoint on your API). We’ll follow the same approach in these exercises. The done() function is a callback that tells us that we can proceed after completing an asynchronous operation such as inserting, searching, updating or deleting. It’s following the Node convention and should be called as done(null, data) on success, or done(err) on error.", "Warning - When interacting with remote services, errors may occur !", "/* Example */", "var someFunc = function(done) {", diff --git a/challenges/06-information-security-and-quality-assurance/advanced-express-tools.json b/challenges/06-information-security-and-quality-assurance/advanced-express-tools.json index ecac2f79b0..927594a48f 100644 --- a/challenges/06-information-security-and-quality-assurance/advanced-express-tools.json +++ b/challenges/06-information-security-and-quality-assurance/advanced-express-tools.json @@ -11,7 +11,7 @@ [ "", "", - "Authentication is the process or action of verifying the identity of a user or process. Up to this point you have not been able to create an app utilizing this key concept.
The most common and easiest to use authentication middleware for Node.js is Passport. It is easy to learn, light-weight, and extremely flexible allowing for many strategies, which we will talk about in later challenges. In addition to authentication we will also look at template engines which allow for use of Pug and web sockets which allow for real time communication between all your clients and your server. Working on these challenges will involve you writing your code on Gomix on our starter project. After completing each challenge you can copy your public gomix url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.
Start this project on Gomix using this link or clone this repository on GitHub! If you use Gomix, remember to save the link to your project somewhere safe!", + "Authentication is the process or action of verifying the identity of a user or process. Up to this point you have not been able to create an app utilizing this key concept.
The most common and easiest to use authentication middleware for Node.js is Passport. It is easy to learn, light-weight, and extremely flexible allowing for many strategies, which we will talk about in later challenges. In addition to authentication we will also look at template engines which allow for use of Pug and web sockets which allow for real time communication between all your clients and your server. Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.
Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!", "" ] ], @@ -27,7 +27,7 @@ "id": "5895f700f9fc0f352b528e63", "title": "Set up a Template Engine", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "A template engine enables you to use static template files (such as those written in Pug) in your app. At runtime, the template engine replaces variables in a template file with actual values which can be supplied by your server, and transforms the template into a static HTML file that is then sent to the client. This approach makes it easier to design an HTML page and allows for displaying of variables on the page without needing to make an API call from the client.", "To set up Pug for use in your project, you will need to add it as a dependency first in your package.json. \"pug\": \"^0.1.0\"", "Now to tell Node/Express to use the templating engine you will have to tell your express app to set 'pug' as the 'view-engine'. app.set('view engine', 'pug')", @@ -59,7 +59,7 @@ "id": "5895f70bf9fc0f352b528e64", "title": "Use a Template Engine's Powers", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "One of the greatest features of using a template engine is being able to pass variables from the server to the template file before rendering it to HTML.", "In your Pug file, you're about to use a variable by referencing the variable name as #{variable_name} inline with other text on an element or by using an equal side on the element without a space such as p= variable_name which sets that p elements text to equal the variable.", "We strongly recommend looking at the syntax and structure of Pug here on their Githubs README. Pug is all about using whitespace and tabs to show nested elements and cutting down on the amount of code needed to make a beautiful site.", @@ -85,7 +85,7 @@ "id": "5895f70cf9fc0f352b528e65", "title": "Set up Passport", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "It's time to set up Passport so we can finally start allowing a user to register or login to an account! In addition to Passport, we will use Express-session to handle sessions. Using this middleware saves the session id as a cookie in the client and allows us to access the session data using that id on the server. This way we keep personal account information out of the cookie used by the client to verify to our server they are authenticated and just keep the key to access the data stored on the server.", "To set up Passport for use in your project, you will need to add it as a dependency first in your package.json. \"passport\": \"^0.3.2\"", "In addition, add Express-session as a dependency now as well. Express-session has a ton of advanced features you can use but for now we're just going to use the basics! \"express-session\": \"^1.15.0\"", @@ -124,7 +124,7 @@ "id": "5895f70cf9fc0f352b528e66", "title": "Serialization of a User Object", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "Serialization and deserialization are important concepts in regards to authentication. To serialize an object means to convert its contents into a small key essentially that can then be deserialized into the original object. This is what allows us to know whos communicated with the server without having to send the authentication data like username and password at each request for a new page.", "To set this up properly, we need to have a serialize function and a deserialize function. In passport we create these with passport.serializeUser( OURFUNCTION ) and passport.dederializeUser( OURFUNCTION )", "The serializeUser is called with 2 arguments, the full user object and a callback used by passport. Returned in the callback should be a unique key to identify that user- the easiest one to use being the users _id in the object as it should be unique as it generated by MongoDb. Similarly deserializeUser is called with that key and a callback function for passport as well, but this time we have to take that key and return the users full object to the callback. To make a query search for a Mongo _id you will have to create const ObjectID = require('mongodb').ObjectID;, and then to use it you call new ObjectID(THE_ID). Be sure to add MongoDB as a dependency. You can see this in the examples below:", @@ -161,7 +161,7 @@ "id": "5895f70cf9fc0f352b528e67", "title": "Implement the Serialization of a Passport User", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "Right now we're not loading an actually users object since we haven't set up our database. This can be done many different ways, but for our project we will connect to the database once when we start the server and keep a persistent connection for the full life-cycle of the app.", "To do this, add MongoDB as a dependency and require it in your server. (const mongo = require('mongodb').MongoClient;)", "Now we want to the connect to our database then start listening for requests. The purpose of this is to not allow requests before our database is connected or if there is a database error. To accomplish you will want to encompass your serialization and your app listener in the following:", @@ -190,7 +190,7 @@ "id": "5895f70df9fc0f352b528e68", "title": "Authentication Strategies", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "A strategy is a way of authenticating a user. You can use a strategy for allowing users to authenticate based on locally saved information (if you have them register first) or from a variety of providers such as Google or Github. For this project we will set up a local strategy. To see a list of the 100's of strategies, visit Passports site here.", "Add passport-local as a dependency and add it to your server as follows: const LocalStrategy = require('passport-local');", "Now you will have to tell passport to use an instantiated LocalStartegy object with a few settings defined. Make sure this as well as everything from this point on is encapsulated in the database connection since it relies on it!
passport.use(new LocalStrategy(\n  function(username, password, done) {\n    db.collection('users').findOne({ username: username }, function (err, user) {\n      console.log('User '+ username +' attempted to log in.');\n      if (err) { return done(err); }\n      if (!user) { return done(null, false); }\n      if (password !== user.password) { return done(null, false); }\n      return done(null, user);\n    });\n  }\n));
This is defining the process to take when we try to authenticate someone locally. First it tries to find a user in our database with the username entered, then it checks for the password to match, then finally if no errors have popped up that we checked for, like an incorrect password, the users object is returned and they are authenticated.", @@ -218,7 +218,7 @@ "id": "5895f70df9fc0f352b528e69", "title": "How to Use Passport Strategies", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "In the index.pug file supplied there is actually a login form. It has previously been hidden because of the inline javascript if showLogin with the form indented after it. Before showLogin as a variable was never defined, it never rendered the code block containing the form. Go ahead and on the res.render for that page add a new variable to the object showLogin: true. When you refresh your page, you should then see the form! This form is set up to POST on /login so this is where we should set up to accept the POST and authenticate the user.", "For this challenge you should add the route /login to accept a POST request. To authenticate on this route you need to add a middleware to do so before then sending a response. This is done by just passing another argument with the middleware before your function(req,res) with your response! The middleware to use is passport.authenticate('local').", "passport.authenticate can also take some options as an argument such as: { failureRedirect: '/' } which is incredibly useful so be sure to add that in as well. As a response after using the middleware (which will only be called if the authentication middleware passes) should be to redirect the user to /profile and that route should render the view 'profile.pug'.", @@ -247,7 +247,7 @@ "id": "5895f70df9fc0f352b528e6a", "title": "Create New Middleware", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "As in, any user can just go to /profile whether they authenticated or not by typing in the url. We want to prevent this by checking if the user is authenticated first before rendering the profile page. This is the perfect example of when to create a middleware.", "The challenge here is creating the middleware function ensureAuthenticated(req, res, next), which will check if a user is authenticated by calling passports isAuthenticated on the request which in turn checks for req.user is to be defined. If it is then next() should be called, otherwise we can just respond to the request with a redirect to our homepage to login. An implementation of this middleware is:", "
function ensureAuthenticated(req, res, next) {\n  if (req.isAuthenticated()) {\n      return next();\n  }\n  res.redirect('/');\n};
", @@ -276,7 +276,7 @@ "id": "5895f70ef9fc0f352b528e6b", "title": "How to Put a Profile Together", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "Now that we can ensure the user accessing the /profile is authenticated, we can use the information contained in 'req.user' on our page!", "Go ahead and pass the object containing the variable username equaling 'req.user.username' into the render method of the profile view. Then go to your 'profile.pug' view and add the line h2.center#welcome Welcome, #{username}! creating the h2 element with the class 'center' and id 'welcome' containing the text 'Welcome, ' and the username!", "Also in the profile, add a link to /logout. That route will host the logic to unauthenticate a user. a(href='/logout') Logout", @@ -299,7 +299,7 @@ "id": "58965611f9fc0f352b528e6c", "title": "Logging a User Out", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "Creating the logout logic is easy. The route should just unauthenticate the user and redirect to the home page instead of rendering any view.", "In passport, unauthenticating a user is as easy as just calling req.logout(); before redirecting.", "
app.route('/logout')\n  .get((req, res) => {\n      req.logout();\n      res.redirect('/');\n  });
", @@ -328,7 +328,7 @@ "id": "58966a17f9fc0f352b528e6d", "title": "Registration of New Users", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "Now we need to allow a new user on our site to register an account. On the res.render for the home page add a new variable to the object passed along- showRegistration: true. When you refresh your page, you should then see the registration form that was already created in your index.pug file! This form is set up to POST on /register so this is where we should set up to accept the POST and create the user object in the database.", "The logic of the registration route should be as follows: Register the new user > Authenticate the new user > Redirect to /profile", "The logic of step 1, registering the new user, should be as follows: Query database with a findOne command > if user is returned then it exists and redirect back to home OR if user is undefined and no error occurs then 'insertOne' into the database with the username and password and as long as no errors occur then call next to go to step 2, authenticating the new user, which we've already written the logic for in our POST /login route.", @@ -368,7 +368,7 @@ "id": "58a25c98f9fc0f352b528e7f", "title": "Hashing Your Passwords", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "Going back to the information security section you may remember that storing plaintext passwords is never okay. Now it is time to implement BCrypt to solve this issue.", "
Add BCrypt as a dependency and require it in your server. You will need to handle hashing in 2 key areas: where you handle registering/saving a new account and when you check to see that a password is correct on login.", "Currently on our registeration route, you insert a user's password into the database like the following: password: req.body.password. An easy way to implement saving a hash instead is to add the following before your database logic var hash = bcrypt.hashSync(req.body.password, 8); and replacing the req.body.password in the database saving with just password: hash. (In our small scale app, it is fine to use sync hashing especially with a low cost of 8 as it wont block the thread very much at all)", @@ -396,7 +396,7 @@ "id": "589690e6f9fc0f352b528e6e", "title": "Clean Up Your Project with Modules", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "Right now everything you have is in your server.js file. This can lead to hard to manage code that isn't very expandable.", "Create 2 new files: Routes.js and Auth.js", "Both should start with the following code:
module.exports = function (app, db) {\n\n\n}
", @@ -405,7 +405,7 @@ "Finally, take all of the routes in your server and paste them into your new files and remove them from your server file. Also take the ensureAuthenticated since we created that middleware function for routing specifically. You will have to now correctly add the dependencies in that are used, such as const passport = require('passport');, at the very top above the export line in your routes.js file.", "Keep adding them until no more errors exist, and your server file no longer has any routing!", "Now do the same thing in your auth.js file with all of the things related to authentication such as the serialization and the setting up of the local strategy and erase them from your server file. Be sure to add the dependencies in and call auth(app,db) in the server in the same spot. Be sure to have auth(app, db) before routes(app, db) since our registration route depends on passport being initiated!", - "Congratulations- you're at the end of this section of Advanced Node and Express and have some beautiful code to show for it! Submit your page when you think you've got it right. If you're running into errors, you can check out an example of the completed project here." + "Congratulations- you're at the end of this section of Advanced Node and Express and have some beautiful code to show for it! Submit your page when you think you've got it right. If you're running into errors, you can check out an example of the completed project here." ], "challengeSeed": [], "tests": [ @@ -427,7 +427,7 @@ [ "", "", - "OAuth 2.0 is the industry-standard authorization and is used across the internet for social login such as letting you login to freeCodeCamp with your Github account.
Implementing social login with passport using OAuth is extremely easy to do because of the 300+ modules already on npm for adding new strategies to your app. In addition to the ease of installation, it is also easier to use because you do not have to deal with a separate registration or any user input.
Start this project on Gomix using this link or clone this repository on GitHub! If you use Gomix, remember to save the link to your project somewhere safe. Be sure to enter your database in the .env file- it can be the same one from last project since you'll be using a new collection!", + "OAuth 2.0 is the industry-standard authorization and is used across the internet for social login such as letting you login to freeCodeCamp with your Github account.
Implementing social login with passport using OAuth is extremely easy to do because of the 300+ modules already on npm for adding new strategies to your app. In addition to the ease of installation, it is also easier to use because you do not have to deal with a separate registration or any user input.
Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe. Be sure to enter your database in the .env file- it can be the same one from last project since you'll be using a new collection!", "" ] ], @@ -443,10 +443,10 @@ "id": "589a69f5f9fc0f352b528e70", "title": "Implementation of Social Authentication", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "The basic path this kind of authentication will follow in your app is:
  1. User clicks a button or link sending them to our route to authenticate using a specific strategy (EG. Github)
  2. Your route calls passport.authenticate('github') which redirects them to Github.
  3. The page the user lands on, on Github, allows them to login if they aren't already then asks them to approve access to their profile from our app.
  4. The user is then returned to our app at a specific callback url with their profile if they approved.
  5. They are now authenticated and your app should check if it is a returning profile, or save it in your database if it is not.
", "Strategies with OAuth require you to have at least a Client ID and a Client Secret which is a way for them to verify who the authentication request is coming from and if it is valid. These are obtained from the site you are trying to implement authentication with, such as Github, and are unique to your app- THEY ARE NOT TO BE SHARED and should never be uploaded to a public repository or written directly in your code. A common practice is to put them in your .env file and reference them like: process.env.GITHUB_CLIENT_ID. For this challenge we're going to use the Github strategy.", - "Obtaining your Client ID and Secret from Github is done in your account profile settings under 'developer settings', then 'OAuth applications'. Click 'Register a new application', name your app, paste in the url to your gomix homepage (Not the project code's url), and lastly for the callback url, paste in the same url as the homepage but with '/auth/github/callback' added on. This is where users will be redirected to for us to handle after authenticating on Github. Save the returned information as 'GITHUB_CLIENT_ID' and 'GITHUB_CLIENT_SECRET' in your .env file.", + "Obtaining your Client ID and Secret from Github is done in your account profile settings under 'developer settings', then 'OAuth applications'. Click 'Register a new application', name your app, paste in the url to your glitch homepage (Not the project code's url), and lastly for the callback url, paste in the same url as the homepage but with '/auth/github/callback' added on. This is where users will be redirected to for us to handle after authenticating on Github. Save the returned information as 'GITHUB_CLIENT_ID' and 'GITHUB_CLIENT_SECRET' in your .env file.", "On your remixed project, create 2 routes accepting GET requests: /auth/github and /auth/github/callback. The first should only call passport to authenticate 'github' and the second should call passport to authenticate 'github' with a failure redirect to '/' and then if that is successful redirect to '/profile' (similar to our last project).", "An example of how '/auth/github/callback' should look is similar to how we handled a normal login in our last project:
app.route('/login')\n  .post(passport.authenticate('local', { failureRedirect: '/' }), (req,res) => { \n    res.redirect('/profile'); \n  });
", "Submit your page when you think you've got it right. If you're running into errors, you can check out the project up to this point here." @@ -472,7 +472,7 @@ "id": "589a69f5f9fc0f352b528e71", "title": "Implementation of Social Authentication II", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "The last part of setting up your Github authentication is to create the strategy itself. For this, you will need to add the dependency of 'passport-github' to your project and require it as GithubStrategy like const GitHubStrategy = require('passport-github').Strategy;.", "To set up the Github strategy, you have to tell passport to use an instantiated GithubStrategy, which accepts 2 arguments: An object (containing clientID, clientSecret, and callbackURL) and a function to be called when a user is successfully authenticated which we will determine if the user is new and what fields to save initially in the user's database object. This is common across many strategies but some may require more information as outlined in that specific strategy's github README; for example, Google requires a scope as well which determines what kind of information your request is asking returned and asks the user to approve such access. The current strategy we are implementing has its usage outlined here, but we're going through it all right here on freeCodeCamp!", "Here's how your new strategy should look at this point:
passport.use(new GitHubStrategy({\n    clientID: process.env.GITHUB_CLIENT_ID,\n    clientSecret: process.env.GITHUB_CLIENT_SECRET,\n    callbackURL: /*INSERT CALLBACK URL ENTERED INTO GITHUB HERE*/\n  },\n  function(accessToken, refreshToken, profile, cb) {\n      console.log(profile);\n      //Database logic here with callback containing our user object\n  }\n));
", @@ -504,11 +504,11 @@ "id": "589a8eb3f9fc0f352b528e72", "title": "Implementation of Social Authentication III", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "The final part of the strategy is handling the profile returned from Github. We need to load the users database object if it exists or create one if it doesn't and populate the fields from the profile, then return the user's object. Github supplies us a unique id within each profile which we can use to search with to serialize the user with (already implemented). Below is an example implementation you can use in your project- it goes within the function that is the second argument for the new strategy, right below the console.log(profile); currently is:", "
db.collection('socialusers').findAndModify(\n    {id: profile.id},\n    {},\n    {$setOnInsert:{\n        id: profile.id,\n        name: profile.displayName || 'John Doe',\n        photo: profile.photos[0].value || '',\n        email: profile.emails[0].value || 'No public email',\n        created_on: new Date(),\n        provider: profile.provider || ''\n    },$set:{\n        last_login: new Date()\n    },$inc:{\n        login_count: 1\n    }},\n    {upsert:true, new: true},\n    (err, doc) => {\n        return cb(null, doc.value);\n    }\n);
", "With a findAndModify, it allows you to search for an object and update it, as well as upsert the object if it doesn't exist and receive the new object back each time in our callback function. In this example, we always set the last_login as now, we always increment the login_count by 1, and only when we insert a new object(new user) do we populate the majority of the fields. Something to notice also is the use of default values. Sometimes a profile returned won't have all the information filled out or it will have been chosen by the user to remain private; so in this case we have to handle it to prevent an error.", - "You should be able to login to your app now- try it! Submit your page when you think you've got it right. If you're running into errors, you can check out an example of this mini-project's finished code here." + "You should be able to login to your app now- try it! Submit your page when you think you've got it right. If you're running into errors, you can check out an example of this mini-project's finished code here." ], "challengeSeed": [], "tests": [ @@ -530,7 +530,7 @@ [ "", "", - "Socket.IO enables real-time, reliable, speedy communication between your server and clients from all devices and browsers. It listens for connects on your server that come from the client which connects with a single javascript statement. The whole library is based on emitting, broadcasting, and recieving events that contain an event name and some data which can include things like strings, objects, arrays, and even blobs like files or video. This is used for all sorts of purposes including instant messaging online, real-time analytics, streaming, and document collaboration.
Start this project on Gomix using this link or clone this repository on GitHub! If you use Gomix, remember to save the link to your project somewhere safe.", + "Socket.IO enables real-time, reliable, speedy communication between your server and clients from all devices and browsers. It listens for connects on your server that come from the client which connects with a single javascript statement. The whole library is based on emitting, broadcasting, and recieving events that contain an event name and some data which can include things like strings, objects, arrays, and even blobs like files or video. This is used for all sorts of purposes including instant messaging online, real-time analytics, streaming, and document collaboration.
Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe.", "" ], [ @@ -569,7 +569,7 @@ "id": "589fc830f9fc0f352b528e74", "title": "Set up the Enviroment", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "Add Socket.IO as a dependency and require/instanciate it in your server defined as 'io' with the http server as an argument. const io = require('socket.io')(http);", "The first thing needing to be handled is listening for a new connection from the client. The on keyword does just that- listen for a specific event. It requires 2 arguments: a string containing the title of the event thats emitted, and a function with which the data is passed though. In the case of our connection listener, we use socket to define the data in the second argument. A socket is an individual client who is connected.", "For listening for connections on our server, add the following between the comments in your project:
io.on('connection', socket => {\n  console.log('A user has connected');\n});
", @@ -607,7 +607,7 @@ "id": "589fc831f9fc0f352b528e75", "title": "Communicate by Emitting", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "Emit is the most common way of communicating you will use. When you emit something from the server to 'io', you send an event's name and data to all the connected sockets. A good example of this concept would be emiting the current count of connected users each time a new user connects!", "
Start by adding a variable to keep track of the users just before where you are currently listening for connections. var currentUsers = 0;", "Now when someone connects you should increment the count before emiting the count so you will want to add the incrementer within the connection listener. ++currentUsers;", @@ -641,7 +641,7 @@ "id": "589fc831f9fc0f352b528e76", "title": "Handle a Disconnect", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "You may notice that up to now you have only been increasing the user count. Handling a user disconnecting is just as easy as handling the initial connect except the difference is you have to listen for it on each socket versus on the whole server.", "
To do this, add in to your existing connect listener a listener that listens for 'disconnect' on the socket with no data passed through. You can test this functionality by just logging to the console a user has disconnected. socket.on('disconnect', () => { /*anything you want to do on disconnect*/ });", "To make sure clients continuously have the updated count of current users, you should decrease the currentUsers by 1 when the disconnect happens then emit the 'user count' event with the updated count!", @@ -669,7 +669,7 @@ "id": "589fc831f9fc0f352b528e77", "title": "Authentication with Socket.IO", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "Currently, you cannot determine who is connected to your web socket. While 'req.user' containers the user object, thats only when your user interacts with the web server and with web sockets you have no req (request) and therefor no user data. One way to solve the problem of knowing who is connected to your web socket is by parsing and decoding the cookie that contains the passport session then deserializing it to obtain the user object. Luckily, there is a package on NPM just for this that turns a once complex task into something simple!", "
Add 'passport.socketio' as a dependency and require it as 'passportSocketIo'.", "Now we just have to tell Socket.IO to use it and set the options. Be sure this is added before the existing socket code and not in the existing connection listener. For your server it should look as follows:
io.use(passportSocketIo.authorize({\n  cookieParser: cookieParser,\n  key:          'express.sid',\n  secret:       process.env.SESSION_SECRET,\n  store:        sessionStore\n}));
You can also optionally pass 'success' and 'fail' with a function that will be called after the authentication process completes when a client trys to connect.", @@ -701,7 +701,7 @@ "id": "589fc832f9fc0f352b528e78", "title": "Announce New Users", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "Many chat rooms are able to annouce when a user connects or disconnects and then display that to all of the connected users in the chat. Seeing as though you already are emitting an event on connect and disconnect, you will just have to modify this event to support such feature. The most logical way of doing so is sending 3 pieces of data with the event: name of the user connected/disconnected, the current user count, and if that name connected or disconnected.", "
Change the event name to 'user' and as the data pass an object along containing fields 'name', 'currentUsers', and boolean 'connected' (to be true if connection, or false for disconnection of the user sent). Be sure to make the change to both points we had the 'user count' event and set the disconnect one to sent false for field 'connected' instead of true like the event emitted on connect. io.emit('user', {name: socket.request.user.name, currentUsers, connected: true});", "Now your client will have all the nesesary information to correctly display the current user count and annouce when a user connects or disconnects! To handle this event on the client side we should listen for 'user' and then update the current user count by using jQuery to change the text of #num-users to '{NUMBER} users online', as well as append a <li> to the unordered list with id 'messages' with '{NAME} has {joined/left} the chat.'.", @@ -729,7 +729,7 @@ "id": "589fc832f9fc0f352b528e79", "title": "Send and Display Chat Messages", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "It's time you start allowing clients to send a chat message to the server to emit to all the clients! Already in your client.js file you should see there is already a block of code handling when the messgae form is submitted! ($('form').submit(function(){ /*logic*/ });)", "
Within the code you're handling the form submit you should emit an event after you define 'messageToSend' but before you clear the text box #m. The event should be named 'chat message' and the data should just be 'messageToSend'. socket.emit('chat message', messageToSend);", "Now on your server you should be listening to the socket for the event 'chat message' with the data being named 'message'. Once the event is recieved it should then emit the event 'chat message' to all sockets io.emit with the data being an object containing 'name' and 'message'.", diff --git a/challenges/06-information-security-and-quality-assurance/information-security-with-helmetjs.json b/challenges/06-information-security-and-quality-assurance/information-security-with-helmetjs.json index b06d848d8a..2db802d0ee 100644 --- a/challenges/06-information-security-and-quality-assurance/information-security-with-helmetjs.json +++ b/challenges/06-information-security-and-quality-assurance/information-security-with-helmetjs.json @@ -11,7 +11,7 @@ [ "", "", - "Working on these challenges will involve you writing your code on Gomix on our starter project. After completing each challenge you can copy your public gomix url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.
Start this project on Gomix using this link or clone this repository on GitHub! If you use Gomix, remember to save the link to your project somewhere safe!", + "Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.
Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!", "" ] ], @@ -27,7 +27,7 @@ "id": "587d8247367417b2b2512c36", "title": "Install and Require Helmet", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "Helmet helps you secure your Express apps by setting various HTTP headers. Install the package, then require it." ], "challengeSeed": [], @@ -48,7 +48,7 @@ "id": "587d8247367417b2b2512c37", "title": "Hide Potentially Dangerous Information Using helmet.hidePoweredBy()", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "Hackers can exploit known vulnerabilities in Express/Node if they see that your site is powered by Express. X-Powered-By: Express is sent in every request coming from Express by default. The helmet.hidePoweredBy() middleware will remove the X-Powered-By header. You can also explicitly set the header to something else, to throw people off. e.g. app.use(helmet.hidePoweredBy({ setTo: 'PHP 4.2.0' }))" ], "challengeSeed": [], @@ -69,7 +69,7 @@ "id": "587d8247367417b2b2512c38", "title": "Mitigate the Risk of Clickjacking with helmet.frameguard()", "description": [ - "As a reminder, this project is being built upon the following starter project on Gomix, or cloned from GitHub.", + "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", "Your page could be put in a or