├── .env ├── .github └── stale.yml ├── .gitignore ├── app.js ├── config └── index.js ├── db └── index.js ├── error-handling └── index.js ├── models └── User.model.js ├── package.json ├── public ├── images │ └── favicon.ico ├── js │ └── script.js └── stylesheets │ └── style.css ├── readme.md ├── routes └── index.js ├── server.js └── views ├── error.hbs ├── index.hbs ├── layout.hbs └── not-found.hbs /.env: -------------------------------------------------------------------------------- 1 | PORT=3000 -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-stale - https://github.com/probot/stale 2 | 3 | # Number of days of inactivity before an Issue or Pull Request becomes stale 4 | daysUntilStale: 21 5 | 6 | # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable 7 | exemptLabels: 8 | - bugs 9 | - enhancements 10 | 11 | # Number of days of inactivity before an Issue or Pull Request with the stale label is closed. 12 | # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. 13 | daysUntilClose: 7 14 | 15 | # Label to use when marking as stale 16 | staleLabel: stale 17 | 18 | # Comment to post when marking as stale. Set to `false` to disable 19 | markComment: > 20 | This pull request has been automatically marked as stale because it didn't have any recent activity. It will be closed if no further activity occurs. Thank you 21 | for your contributions. 22 | closeComment: > 23 | This pull request is closed. Thank you. 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependency directory 2 | node_modules 3 | 4 | # Debug log from npm 5 | npm-debug.log 6 | 7 | # Environment Variables should NEVER be published 8 | # We are submitting it for learning purposes 9 | # .env 10 | 11 | # for maintenance purposes - not best practices 12 | package-lock.json 13 | 14 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | // ℹ️ Gets access to environment variables/settings 2 | // https://www.npmjs.com/package/dotenv 3 | require('dotenv/config'); 4 | 5 | // ℹ️ Connects to the database 6 | require('./db'); 7 | 8 | // Handles http requests (express is node js framework) 9 | // https://www.npmjs.com/package/express 10 | const express = require('express'); 11 | 12 | // Handles the handlebars 13 | // https://www.npmjs.com/package/hbs 14 | const hbs = require('hbs'); 15 | 16 | const app = express(); 17 | 18 | // ℹ️ This function is getting exported from the config folder. It runs most middlewares 19 | require('./config')(app); 20 | 21 | // default value for title local 22 | const projectName = 'lab-express-basic-auth'; 23 | const capitalized = string => string[0].toUpperCase() + string.slice(1).toLowerCase(); 24 | 25 | app.locals.title = `${capitalized(projectName)}- Generated with Ironlauncher`; 26 | 27 | // 👇 Start handling routes here 28 | const index = require('./routes/index'); 29 | app.use('/', index); 30 | 31 | // ❗ To handle errors. Routes that don't exist or errors that you handle in specific routes 32 | require('./error-handling')(app); 33 | 34 | module.exports = app; 35 | 36 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | // We reuse this import in order to have access to the `body` property in requests 2 | const express = require("express"); 3 | 4 | // ℹ️ Responsible for the messages you see in the terminal as requests are coming in 5 | // https://www.npmjs.com/package/morgan 6 | const logger = require("morgan"); 7 | 8 | // ℹ️ Needed when we deal with cookies (we will when dealing with authentication) 9 | // https://www.npmjs.com/package/cookie-parser 10 | const cookieParser = require("cookie-parser"); 11 | 12 | // ℹ️ Serves a custom favicon on each request 13 | // https://www.npmjs.com/package/serve-favicon 14 | const favicon = require("serve-favicon"); 15 | 16 | // ℹ️ global package used to `normalize` paths amongst different operating systems 17 | // https://www.npmjs.com/package/path 18 | const path = require("path"); 19 | 20 | // Middleware configuration 21 | module.exports = (app) => { 22 | // In development environment the app logs 23 | app.use(logger("dev")); 24 | 25 | // To have access to `body` property in the request 26 | app.use(express.json()); 27 | app.use(express.urlencoded({ extended: false })); 28 | app.use(cookieParser()); 29 | 30 | // Normalizes the path to the views folder 31 | app.set("views", path.join(__dirname, "..", "views")); 32 | // Sets the view engine to handlebars 33 | app.set("view engine", "hbs"); 34 | // Handles access to the public folder 35 | app.use(express.static(path.join(__dirname, "..", "public"))); 36 | 37 | // Handles access to the favicon 38 | app.use(favicon(path.join(__dirname, "..", "public", "images", "favicon.ico"))); 39 | }; 40 | -------------------------------------------------------------------------------- /db/index.js: -------------------------------------------------------------------------------- 1 | // ℹ️ package responsible to make the connection with mongodb 2 | // https://www.npmjs.com/package/mongoose 3 | const mongoose = require("mongoose"); 4 | 5 | // ℹ️ Sets the MongoDB URI for our app to have access to it. 6 | // If no env has been set, we dynamically set it to whatever the folder name was upon the creation of the app 7 | 8 | const MONGO_URI = process.env.MONGODB_URI || "mongodb://127.0.0.1:27017/lab-express-basic-auth"; 9 | 10 | mongoose 11 | .connect(MONGO_URI) 12 | .then((x) => { 13 | console.log(`Connected to Mongo! Database name: "${x.connections[0].name}"`); 14 | }) 15 | .catch((err) => { 16 | console.error("Error connecting to mongo: ", err); 17 | }); 18 | -------------------------------------------------------------------------------- /error-handling/index.js: -------------------------------------------------------------------------------- 1 | module.exports = (app) => { 2 | app.use((req, res, next) => { 3 | // this middleware runs whenever requested page is not available 4 | res.status(404).render("not-found"); 5 | }); 6 | 7 | app.use((err, req, res, next) => { 8 | // whenever you call next(err), this middleware will handle the error 9 | // always logs the error 10 | console.error("ERROR", req.method, req.path, err); 11 | 12 | // only render if the error ocurred before sending the response 13 | if (!res.headersSent) { 14 | res.status(500).render("error"); 15 | } 16 | }); 17 | }; 18 | -------------------------------------------------------------------------------- /models/User.model.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require("mongoose"); 2 | 3 | // TODO: Please make sure you edit the user model to whatever makes sense in this case 4 | const userSchema = new Schema({ 5 | username: { 6 | type: String, 7 | unique: true 8 | }, 9 | password: String 10 | }); 11 | 12 | const User = model("User", userSchema); 13 | 14 | module.exports = User; 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lab-express-basic-auth", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node server.js", 7 | "dev": "nodemon server.js" 8 | }, 9 | "dependencies": { 10 | "cookie-parser": "^1.4.5", 11 | "dotenv": "^8.2.0", 12 | "express": "^4.17.1", 13 | "hbs": "^4.1.1", 14 | "mongoose": "^6.1.2", 15 | "morgan": "^1.10.0", 16 | "serve-favicon": "^2.5.0" 17 | }, 18 | "devDependencies": { 19 | "nodemon": "^2.0.7" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /public/images/favicon.ico: -------------------------------------------------------------------------------- 1 |  h6 ��00 �%F(  @��������������������2?��2���3���2G��������������������������������1-��3���2���2���2���2���3���13��.�����������������2��3���2���1���2���2���2���2���2���2���3���2��������4��2���2���1���2���2���2���2���2���2���2���2���1���2���2���3 ��3g��2���2���3���3���5���5���4���1���?���5���1���2���2���2���3m��3s��1���1���M���G���c���z��Ձ��Ղ���A���y���i���-���2���1���3u��3s��1���1���L���}��։���]���o���n�����ڙ���F���2���2���1���3u��3s��1���1���:���9���H���(���N���@���b���C���N���+���2���1���3u��3u��1���1���G������{��ݜ���m������a���f������-���2���1���3u��3u��1���1���O��ܜ�������������>�������������/���2���1���3u��3u��1���1���N��ܙ���������ߔ������}������ޒ���.���2���1���3u��3o��2���2���2���3���4���,���(���.���,���1���4���2���2���2���3q��2 ��3���2���1���2���2���2���2���2���2���2���2���1���2���3���1��������2+��3���2���2���2���2���2���2���2���2���3���2-��������������������2=��2���2���2���2���2���3���2A��������������������������������3Q��3���2���3W��/�����������������������������������������������( @ ���������������������������������������@��1��1[��3���3���3k��2��@��������������������������������������������������������������������B�����3=��2���3���2���3���3���3���1M���������������������������������������������������������������3��2C��2���2���2���2���2���2���2���2���3���2���2M��3 �� ��3�����������������������������������������3�����1!��2���4���2���2���2���2���2���2���2���2���1���2���3���2���0+��3��-��������������������������������*�����3+��3}��3���3���2���2���2���2���2���2���2���2���2���2���2���2���3���2���3���21����������������������������G��2��2c��3���3���2���1���2���2���2���2���2���2���2���2���2���2���2���2���1���2���3���3���2k��3��G��U�����������B��1��2_��3���3���1���1���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���1���2���3���3���1e��2��8�����U��1��3���3���2���1���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2'��D��2 ��2���3���2���2���2���1���0���0���1���1���0���/���1���1���1���.���0���'���(���0���0���2���)���2���2���2���2���2���2���2���4��1��3���2���2���2���2���0���:���:���0���6���=���@���4���5���7���5���/���\���P���:���9���+���>���2���1���2���2���2���2���3���1��1��3���1���2���2���0���)���p���j���*���?��҂��ؚ���F���4��Հ��ӄ��ީ���t���`��Ӄ���R���e��ׇ������3���2���2���2���2���3���1��3��3���1���2���2���0���)���q���h������?��ԋ���]�����ٖ������[��ӂ��� �����ӆ��ֈ��ُ���)���3���1���2���2���2���2���3���1!��3��3���1���2���2���0���)���o�����ٚ��߬��ד���1��ۣ���K��֍���d���s���/���"��Մ�������)���2���1���2���2���2���2���2���3���1!��2��3���1���2���2���0���)���p���u���/���W��Տ�����׌��ڙ���K���a��Ӄ������ ��Ӈ��֋��ْ���*���5���1���2���2���2���2���3���1!��2��3���1���2���2���0���)���g���d���-���O��ҁ������P������/���1��ܞ��؛��с���w���G���[��Տ������3���2���2���2���2���3���1!��2��3���1���2���2���1���0���'���&���.������3���*������2���0������ ���:���1������0���'���)���0���2���2���2���2���2���3���1!��2��3���1���2���2���1���.���Q��Հ���F��׊���;���b��Ո���+���\��ݠ��؆���7���T���|���0���Q��։���#���3���2���2���2���2���3���1!��1��3���1���2���2���0���*���t�������d�������>����������C�������������چ���q�������#�����������,���1���2���2���2���2���3���1!��1��3���2���2���2���1���*���t�������e���������������@��ܝ����������������ӄ������Չ�����������/���2���2���2���2���2���3���1!��1��3���2���2���2���0���*���t�������f�������������ޝ��ە����������z������Ԋ����������ܣ�������*���2���2���2���2���2���3���1!��1��3���2���2���2���1���*���t�������e�������]����������i�������:���������{�����������D�������*���2���2���2���2���2���3���1!��1��3���2���2���2���1���)���p�������b��������������ٓ���3���������������g���a�������c���B�������+���2���2���2���2���2���3���1��1!��3���1���2���2���2���1���4���9���0���:���@���-��� ���*������=���������-���5���,���4���:���2���2���2���2���2���2���3���1!��1��2���2���2���2���2���1���1���0���1���/���(���0���3���2���4���,���1���3���2���0���2���1���0���2���2���2���2���2���2���3���2�����21��3���3���2���1���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���1���2���3���4���27�����������2%��3}��3���3���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���3���3���3}��2'��������������@�����1��2���3���3���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���3���2���3�����@�������������������� ��0��2C��4���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���1E��6�� ��������������������������������B�����2?��2���3���2���2���2���2���2���2���2���2���2���2���3���3���1C�����B��������������������������������������������@��4��3[��3���3���2���1���2���2���1���2���3���2���3_��1��@�����������������������������������������������������@�������3a��4���3���2���2���2���3���2i��8�����@����������������������������������������������������������������4��2��3{��2���2���2���2#��9�����������������������������������(0` �%��������������������������������������������������������@�����������1U��3���3���3o��3 ��������@��������������������������������������������������������������������������������������������������������U��U��������1E��1���4���5���5���5���2���2a�����������@��������������������������������������������������������������������������������������������U��@��������41��3���3���5���1���2���2���2���4���5���1���2I����������U����������������������������������������������������������������������������������3��������2%��1���2���5���2���2���2���2���2���2���2���2���4���4���2���29��������@�������������������������������������������������������������������������@��������3��2���2���5���2���2���2���2���2���2���2���2���2���2���2���2���5���2���3���2%��������@�������������������������������������������������������������3��������. ��2{��2���6���3���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���5���2���2���,��������3��������������������������������������������������@�����������3e��2���5���3���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���3���5���2���2u��@ ��������@��������������������������������������@����������4U��3���5���4���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���3���5���2���1c�����������@����������������������������U��������4A��2���4���4���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���4���5���2���3K��������U��U�����������������@��������33��2���3���5���1���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���4���4���2���0;��������@�����������U�����.��3���2���5���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���5���2���1���5#����������U�����15��2���6���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���5���2���3U�����U�����3��2���5���2���2���2���2���2���2���1���5���5���1���2���2���7���3���6���4���1���2���1���4���6���0���7���;���;���7���2���7���2���1���4���8���2���2���2���2���2���2���2���2���4���2���6!��������2Q��4���2���2���2���2���2���2���1���4���$���&���4���1���3������.������.���3���1���4���+������;���������������1������1���6���1������3���2���2���2���2���2���2���2���2���4���3[��������2[��4���2���2���2���2���2���2���4���)���Q���N���)���4���.���X���?���Z���<���4���:���2���B���^������M��ӊ��ԍ���f���6���Z���5���)���%���m���2���1���2���2���2���2���2���2���2���4���1_��������1Y��4���1���2���2���2���2���0���>�����ܧ��ٞ������?���������c��ܨ��Փ������0�����ܨ��ٝ���b������߰��ޭ��т���a�������(��������ۦ������8���2���2���2���2���2���2���2���4���1]��������3[��4���1���2���2���2���2���0���>�����ݫ��ڢ������A����������g���u�������K���a���V�������X������Փ������������l�������������������3���3���2���2���2���2���2���2���2���4���1_��������3[��4���2���2���2���2���2���0���>�����ܩ��؛������'���������x�������������ݧ������������������G���)���B������l�����ۦ���������/���5���1���2���2���2���2���2���2���2���4���1_��������3[��4���1���2���2���2���2���0���>�����ܧ������ެ�������������r�����ܧ��ڢ��������Ր���+�������I���#���:������R��������������9���6���1���2���2���2���2���2���2���2���2���4���1_��������3[��4���1���2���2���2���2���0���>�����ܩ������Y���t���g�������v������m������:�������D���A�������J���3���C������c���������с������?���1���2���2���2���2���2���2���2���2���4���1_��������2[��4���1���2���2���2���2���0���>�����ܩ��ؚ���������������w������%��߰�����ޮ������$�������l������������o������K������Ѐ������;���1���2���2���2���2���2���2���2���4���1_��������2[��4���1���2���2���2���2���0���>�����ޭ��ۥ������E����������y��������ф�������q��� �����֖������Ր��Ց���l���f����������Q������с������8���2���2���2���2���2���2���2���4���1_��������2[��4���1���2���2���2���2���1���7������p���m������7���1���}���Q���'���4���I��Ԏ���5���4���>�����҅��߰��߱��҄���E���}���:������c��҇������4���2���2���2���2���2���2���2���4���1_��������2[��4���1���2���2���2���2���2���0���8���������2���/��� ������+���6������������9���)���������������������������1���?���������9���1���2���2���2���2���2���2���2���4���1_��������2[��4���1���2���2���2���2���2���4���*���N���g���<���8���c���R���/���(���]���d���?������6���q���q���>������<���M���b���?���4��� ���b���X���!���5���2���2���2���2���2���2���2���4���1_��������2]��4���1���2���2���2���2���1���>�����ݪ�������t���Y������������Ԏ�������������҈������������������҈�����ܧ�������h������~����������� ���3���3���2���2���2���2���2���2���4���1_��������2]��4���2���2���2���2���2���0���@�����߱�������y���\���������������������`�������������י��֖�������������ݬ�������j������������������;���*���5���2���2���2���2���2���2���4���1_��������2]��4���2���2���2���2���2���1���?�����ޮ�������w���[���������ט������ۥ������k�������������������������?��ڣ�������N��҉���������������5���,���5���2���2���2���2���2���2���4���1_��������2]��4���2���2���2���2���2���0���?�����ޯ�������x���`��������������������������r�����������������������X��ڢ�������P�������������������+���-���5���2���2���2���2���2���2���4���1_��������2]��4���2���2���2���2���2���0���?�����ޯ�������x���]����������у����������ۦ���Y�����������������������V��ۥ������ݩ�������q�����������(���-���5���2���2���2���2���2���2���4���1_��������1]��4���2���2���2���2���2���1���?�����ޮ�������w���Z������߱�����������������5�������������������������:��ۤ��������������������������)���-���5���2���2���2���2���2���2���4���1_��������1]��4���2���2���2���2���2���0���@�����߲�������y���_����������҆����������߰�������������߱��߰�������������ܨ����������у��������������)���-���5���2���2���2���2���2���2���4���1_��������1]��4���2���2���2���2���2���1���>�����ۥ�������s���V�����������������������L������v�������������������w�����҈������������������������*���.���4���2���2���2���2���2���2���4���1]��������1]��4���1���2���2���2���2���2���2���/���=���L���8���-���@���Y���`���J������!���:���������T���S���������8���%���M������.���1���B���H���2���2���2���2���2���2���2���2���2���4���1]��������2a��5���2���2���2���2���2���2���2���3���+������/���2���%������������8���6���0���:���2���������3���9���1���3������3���4���2���(���"���2���2���2���2���2���2���2���2���2���4���2a��������1/��2���3���2���2���2���2���2���2���1���5���9���3���2���7���9���9���8���3���1���2���1���5���9���9���5���1���2���3���8���4���1���2���6���7���2���2���2���2���2���2���2���2���3���3���37����������3k��4���4���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���4���5���2{�����������������3A��2���5���4���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���4���5���2���3G�����������������U��������2g��2���6���3���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���3���6���2���2e�������������������������@��������9 ��1w��3���5���3���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���3���5���2���3y��9 ��������@��������������������������3��������.��3���2���6���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���5���2���2���5��������3�������������������������������������@��������6!��3���2���5���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���5���2���2���0%��������@������������������������������������������������@��������33��2���3���5���1���2���2���2���2���2���2���2���2���2���2���2���2���2���2���2���5���4���2���19��������@��U��������������������������������������������������������U��U��������4A��2���4���4���2���2���2���2���2���2���2���2���2���2���2���2���4���5���3���1I����������U��������������������������������������������������������������������@�����������4U��2���5���4���2���2���2���2���2���2���2���2���3���5���2���2a�����������@��������������������������������������������������������������������������������@����������3e��3���5���3���2���2���2���2���3���5���2���3s��9 ��������@��������������������������������������������������������������������������������������������3��������7��2{��3���6���3���2���6���2���2���5��������3�������������������������������������������������������������������������������������������������������3��������5��3���2���2���3���0%��������@����������������������������������������������������������������������������������������������������������������������������������������������������� -------------------------------------------------------------------------------- /public/js/script.js: -------------------------------------------------------------------------------- 1 | document.addEventListener( 2 | "DOMContentLoaded", 3 | () => { 4 | console.log("lab-express-basic-auth JS imported successfully!"); 5 | }, 6 | false 7 | ); 8 | -------------------------------------------------------------------------------- /public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ![logo_ironhack_blue 7](https://user-images.githubusercontent.com/23629340/40541063-a07a0a8a-601a-11e8-91b5-2f13e4e6b441.png) 2 | 3 | # LAB | Express Basic Auth 4 | 5 |

6 | 7 | ## Introduction 8 | 9 |
10 | 11 | In this lab, you are going to reinforce the knowledge of how to create basic authorization and authentication in a web app. 12 | 13 | ![](https://s3-eu-west-1.amazonaws.com/ih-materials/uploads/upload_044a7b23c9b4cf082e1c4fadcd12d308.png) 14 | 15 | ## Requirements 16 | 17 | - Fork this repo 18 | - Clone this repo 19 | 20 | ## Submission 21 | 22 | - Upon completion, run the following commands: 23 | 24 | ``` 25 | git add . 26 | git commit -m "done" 27 | git push origin master 28 | ``` 29 | 30 | - Create Pull Request so your TAs can check up your work. 31 | 32 |
33 | 34 | ## Instructions 35 | 36 | _In this lab, you literally have to recreate materials your instructors went through in the class. The point is not to blindly copy-paste them, but the opposite of that: to go once again, step by step through the process of registering users and authenticating them in the web app. Try to target all the weak spots, everything you missed to grasp during the lecture time, so you can ask your instructors and assistants to push you through the learning process._ 37 | 38 |
39 | 40 | ### Iteration 0 | Initialize the project 41 | 42 | After forking and cloning the project, you will have to install all the dependencies: 43 | 44 | ```sh 45 | $ cd lab-express-basic-auth 46 | $ npm install 47 | ``` 48 | 49 | Now you are ready to start 🚀 50 | 51 |
52 | 53 | ## Iteration 1 | Sign Up 54 | 55 | We have to create the _signup_ feature - the goal is to enable our users to register in our application. The users have to provide the following information: 56 | 57 | - **username**: must be unique in our application and will identify each user 58 | - **password**: must be encrypted (you can use the `bcryptjs` npm package). 59 | 60 | To complete this first iteration, you have to create the model as well as the corresponding routes and views. 61 | 62 |
63 | 64 | ## Iteration 2 | Login 65 | 66 | Once the user has signed up, he/she should be able to authenticate themselves. This means the user should be able to log in to the application. Your assignment in this iteration is to create corresponding routes as well as the views to let them log in to the application. 67 | 68 | As you know, it is not enough just to allow users to log in. Users should be able to maintain their "presence" in the application (stay logged in when going from a page to a page, after the refresh), and for that, there should be the user(s) in the session. You have learned that you can use the `express-session` and `connect-mongo` npm packages to create a session. 69 | 70 |
71 | 72 | ## Iteration 3 | Protected Routes 73 | 74 | At this point, you have implemented the basic authentication in this application. Your next assignment is to create the authentication middleware and protect some routes. Refresher: users can't visit these routes unless they are authenticated (logged in and exist in the session). 75 | 76 | Let's create two different routes protected by authentication: 77 | 78 | - `/main` - Add a funny picture of a cat and a link back to the home page 79 | - `/private` - Add your favorite `gif` and an `

` denoting the page as private. 80 | 81 | Create the views and the custom authentication middleware function. Once created, use the middleware and protect the routes to prevent access to users who are not being authenticated. 82 | 83 |

84 | 85 | ## Bonus | The validation 86 | 87 |
88 | 89 | ### Validation during the signup process 90 | 91 | You should handle validation errors when a user signs up: 92 | 93 | - The fields can't be empty. 94 | - The username can't be repeated. 95 | 96 |
97 | 98 | ### Bonus | Validation during the login process 99 | 100 | You should check if all the fields are correctly filled before authenticating the user. 101 | 102 |
103 | 104 | ### Frontend validation 105 | 106 | Let's add validations to our forms. Remember we have two different forms: sign up and log in. 107 | 108 | Remember, when a user signs up or logs in, both the username and password fields must be filled in. 109 | 110 | Check out the [documentation](https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Data_form_validation) at MDN. See if you can find a _constraint_ that requires the user to fill in a field before submission. 111 | 112 |
113 | 114 | ## Extra Resources 115 | 116 | - [HTML5 Form Validations](http://www.the-art-of-web.com/html/html5-form-validation/) 117 | 118 | 119 | **Happy coding!** :heart: 120 | 121 |
122 | 123 | ## FAQs 124 | 125 | 126 |
127 | I am stuck and don't know how to solve the problem or where to start. What should I do? 128 | 129 |
130 | 131 | If you are stuck in your code and don't know how to solve the problem or where to start, you should take a step back and try to form a clear question about the specific issue you are facing. This will help you narrow down the problem and come up with potential solutions. 132 | 133 | For example, is it a concept that you don't understand, or are you receiving an error message that you don't know how to fix? It is usually helpful to try to state the problem as clearly as possible, including any error messages you are receiving. This can help you communicate the issue to others and potentially get help from classmates or online resources. 134 | 135 | Once you have a clear understanding of the problem, you will be able to start working toward the solution. 136 | 137 |
138 | 139 | [Back to top](#faqs) 140 | 141 |
142 | 143 |
144 | When I try to run the app, I get an error "command not found: nodemon" 145 | 146 |
147 | Make sure you have nodemon installed on your machine: 148 | 149 | ```bash 150 | npm install -g nodemon 151 | ``` 152 | 153 | This will install nodemon globally on your system, making it available to all of your projects. 154 | 155 |
156 | 157 | [Back to top](#faqs) 158 | 159 |
160 | 161 |
162 | How to create a Mongoose model? 163 | 164 |
165 | 166 | The mongoose model serves as a blueprint for creating and managing documents within MongoDB collections. The mongoose model is an overlay on top of one MongoDB collection, that we use to query and interact with that database collection. 167 | 168 | Here is an example of creating a `User` model to manage documents in the `users` collection: 169 | 170 | ```js 171 | // IMPORT MONGOOSE 172 | const mongoose = require("mongoose"); 173 | 174 | // CREATE A SCHEMA - defines the shape of the documents 175 | const userSchema = new mongoose.Schema({ 176 | firstName: String, 177 | lastName: String 178 | }); 179 | 180 | // CREATE THE MODEL 181 | const User = mongoose.model('User', schema); 182 | 183 | // EXPORT THE MODEL 184 | module.exports = User; 185 | ``` 186 | 187 |
188 | 189 | In the above example, we created and exported a `User` model, so that it can be imported and used anywhere in the application for managing the database collection `users`. 190 | 191 | Let's break down the above example and the steps in creating a mongoose model: 192 | 193 | 1. **Import mongoose:** The first step is to import the `mongoose` library. 194 | 2. **Create a schema:** The next step is to create a schema, which defines the shape of the documents that will be stored in the `users` collection. In the above example, the schema has two fields `firstName` and `lastName` which are both strings. 195 | 3. **Create the model**: The last step is to create the model. This is done using the method `mongoose.model()`, which takes two arguments: the name of the model, in this case `'User'` and the schema it should use. 196 | Mongoose automatically pluralizes and converts to lowercase the provided model name and uses it as the name of the collection. In this case, the string `'User'` is automatically converted into a collection name -> `users`. 197 | 4. **Export the model:** After the model is created, it needs to be exported so it can be used in other parts of the application. 198 | 199 |
200 | 201 | [Back to top](#faqs) 202 | 203 |
204 | 205 |
206 | I got the error: "[ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client". How do I resolve it? 207 | 208 |
209 | 210 | The error `[ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client` occurs when you try to send a response after the response has already been sent. This means that you are calling `res.send()` or `res.render()` multiple times in your route, instead of only once at the end of the request. 211 | 212 | To fix the issue, check the route that threw the error and verify that you are only calling `res.send()` or `res.render()` once in the route in question, after all, database operations and other logic have been completed. 213 | You can start by trying to identify all the `res.send()` or `res.render()` calls made in the route code. 214 | 215 | This error commonly arises from having nested conditionals or Promises and having multiple calls to `res.send()` or `res.render()` in the route logic. To troubleshoot it, it is advisable to check these parts of the route code for any logic errors. 216 | 217 |
218 | 219 | [Back to top](#faqs) 220 | 221 |
222 | 223 |
224 | How do I resolve the error "ERR_HTTP_INVALID_STATUS_CODE" on my ExpressJS server? 225 | 226 |
227 | 228 | Check that your server route is sending a valid HTTP status code. HTTP status codes are 3-digit numbers that indicate the status of an HTTP request and must be in the range of 100-599. If the server is sending an invalid status code, In particular, if the status code is set by res.status() is invalid, it could cause this error. 229 | 230 |
231 | 232 | [Back to top](#faqs) 233 | 234 |
235 | 236 |
237 | What could be causing a redirect to fail in my Express app? 238 | 239 |
240 | 241 | Some possible reasons why a redirect might not work in an ExpressJS app are: 242 | 243 | 1. There might be a typo in the route name or path. Make sure that the route name or path in the res.redirect() function is spelled correctly and matches the name or path of the route you are trying to redirect to. 244 | 2. Check that you have correctly spelled the res.redirect() function name. 245 | 3. The route you are trying to redirect to might not be defined. Make sure that you have defined the route you are trying to redirect to. 246 | 247 |
248 | 249 | [Back to top](#faqs) 250 | 251 |
252 | 253 |
254 | How do I resolve the error "ValidationError: Path ... is required."? 255 | 256 |
257 | 258 | This error occurs when you try to save a document to the database without a value for a field that is marked as required in the model. 259 | To fix this error, make sure that you are providing a value for all required fields when creating or updating a document. You can verify that you are providing the correct values by using the console.log to inspect the data before saving it to the database. 260 | 261 |
262 | 263 | [Back to top](#faqs) 264 | 265 |
266 | 267 |
268 | How do I make a field in a Mongoose model, such as 'email', unique? 269 | 270 |
271 | 272 | To make a field in a Mongoose model unique, you should add the `unique: true` property in the field's schema definition. For example, to make the `email` field in a Mongoose model unique, you should do the following: 273 | 274 | ```js 275 | const userSchema = new mongoose.Schema({ 276 | name: String, 277 | email: { 278 | type: String, 279 | unique: true 280 | }, 281 | password: String 282 | }) 283 | ``` 284 | 285 | This will ensure that no two documents in the database can have the same value for the email field. 286 | 287 |
288 | 289 | [Back to top](#faqs) 290 | 291 |
292 | 293 |
294 | I am getting an error: "not defined". How do I fix it? 295 | 296 |
297 | 298 | The "ReferenceError: variable is not defined" error in JavaScript occurs when you try to access a variable or a function that has not been defined yet or is out of scope. 299 | 300 | To fix the issue, check that you have defined the variable or function that you are trying to use and double-check the spelling to make sure you are using the correct name. 301 | 302 | In case the variable or a function is defined in another file, make sure that the file has been imported or loaded correctly. 303 | 304 |
305 | 306 | [Back to top](#faqs) 307 | 308 |
309 | 310 |
311 | My GET form is not working properly. What should I do? 312 | 313 |
314 | 315 | Here are the things you should check in order to fix your GET form: 316 | 317 | 1. Check that the path for your GET route in Express matches the `action` and `method` attributes in the form. For example, if you have a route `GET` `/search`: 318 | 319 | ```js 320 | app.get('/search', (req, res) => { 321 | // form handling logic 322 | }); 323 | ``` 324 | 325 | Your form `action` attribute should have the same path and the `method` should be the same: 326 | 327 | ```html 328 |
329 | ``` 330 | 331 | 2. Check the data you are receiving from the form on the `req.query` by using `console.log()`. For example, if you have a route `GET` `/search`, you can add a `console.log()` like this: 332 | 333 | ```js 334 | app.get('/search', (req, res) => { 335 | // Print the data coming from the form 336 | console.log(req.query); 337 | }); 338 | ``` 339 | 340 | 3. Check that the `form` tag is properly formatted and that it has an opening and a closing tag. Example: 341 | 342 | ```html 343 | 344 | 345 |
346 | ``` 347 | 348 | 4. Check that the submit button is configured properly to submit the form when clicked. Make sure that the button is located inside of the form tag and that it has a `type="submit"` attribute. Example: 349 | 350 | ```html 351 |
352 | 353 | 354 | 355 | 356 |
357 | ``` 358 | 359 |
360 | 361 | [Back to top](#faqs) 362 | 363 |
364 | 365 |
366 | My links are not working properly. Should I use a relative or an absolute path? 367 | 368 |
369 | 370 | When linking to other pages within your Express app, as a general rule you should use relative paths that start with a forward slash `/`. 371 | 372 | This way you ensure that the links will work correctly both in your development environment and when the app is deployed. 373 | 374 | For example, instead of linking to a page with an absolute path like this: 375 | 376 | ```html 377 | Contact 378 | ``` 379 | 380 | You should use a relative path starting with a forward slash `/` like this: 381 | 382 | ```html 383 | Contact 384 | ``` 385 | 386 | If you are embedding values in your Handlebars template, you should still use the relative path that starts with a forward slash `/` like this: 387 | 388 | ```handlebars 389 | About 390 | ``` 391 | 392 |
393 | 394 | [Back to top](#faqs) 395 | 396 |
397 | 398 |
399 | I got the error "Error: listen EADDRINUSE: Address already in use". How do I fix it? 400 | 401 |
402 | 403 | This error means that the port is taken by another process that is still running on that port. 404 | To fix the issue, you need to kill the process using the port and then run the command again. Here's how to do it: 405 | 406 | 407 | #### On Mac/Linux 408 | 409 | To kill the process running on port `3000`, run the following command in the terminal: 410 | 411 | ```bash 412 | sudo kill -9 $(lsof -t -i:3000) 413 | ``` 414 | 415 | **Important:** Replace the above example port *3000* with the port number of the process you are trying to kill. 416 | 417 |
418 | 419 | #### On Windows 420 | 421 | ##### 1. Using the Task Manager 422 | 423 | To kill the running process on Windows using the Task Manager do the following: 424 | 425 | 1. Open the **Task Manager** by pressing: **Ctrl** + **Shift** + **Esc** 426 | 2. Find the Node process you want to terminate. 427 | 3. Right-click and select **End Task** 428 | 429 |
430 | 431 | ##### 2. Using Command Prompt 432 | 433 | To kill the running process on Windows using the Command Prompt do the following: 434 | 435 | 1. Open the windows **Start** menu 436 | 2. Search for **CMD** in the search bar 437 | 3. In the search results, right-click on **Command Prompt** and select **Run as administrator**. This will open the Command Prompt terminal. 438 | 4. In the Command Prompt terminal, run the following command to find the process ID: 439 | 440 | ```bash 441 | netstat -ano|findstr "PID :3000" 442 | ``` 443 | 444 | > If the process happens to be running on another port, simply replace `3000` with the number the port number the process is running on. 445 | 446 | This will return the process id (PID). You should then run the following command using the process id (PID) you got in the previous step to terminate the process: 447 | 448 | ```bash 449 | taskkill /PID 12345 /f 450 | ``` 451 | 452 | **Important:** Replace the above example PID *12345*, with the process id (PID) you got in the previous step. 453 | 454 |
455 | 456 | [Back to top](#faqs) 457 | 458 |
459 | 460 |
461 | I got the error "Port is already in use". How do I fix it? 462 | 463 |
464 | 465 | This error means that the port is taken by another process that is still running on that port. 466 | To fix the issue, you need to kill the process using the port and then run the command again. Here's how to do it: 467 | 468 | #### On Mac/Linux 469 | 470 | To kill the process running on port `3000`, run the following command in the terminal: 471 | 472 | ```bash 473 | sudo kill -9 $(lsof -t -i:3000) 474 | ``` 475 | 476 | **Important:** Replace the above example port *3000* with the port number of the process you are trying to kill. 477 | 478 |
479 | 480 | #### On Windows 481 | 482 | ##### 1. Using the Task Manager 483 | 484 | To kill the running process on Windows using the Task Manager do the following: 485 | 486 | 1. Open the **Task Manager** by pressing: **Ctrl** + **Shift** + **Esc** 487 | 2. Find the Node process you want to terminate. 488 | 3. Right-click and select **End Task** 489 | 490 |
491 | 492 | ##### 2. Using Command Prompt 493 | 494 | To kill the running process on Windows using the Command Prompt do the following: 495 | 496 | 1. Open the windows **Start** menu 497 | 2. Search for **CMD** in the search bar 498 | 3. In the search results, right-click on **Command Prompt** and select **Run as administrator**. This will open the Command Prompt terminal. 499 | 4. In the Command Prompt terminal, run the following command to find the process ID: 500 | 501 | ```bash 502 | netstat -ano|findstr "PID :3000" 503 | ``` 504 | 505 | > If the process happens to be running on another port, simply replace `3000` with the number the port number the process is running on. 506 | 507 | This will return the process id (PID). You should then run the following command using the process id (PID) you got in the previous step to terminate the process: 508 | 509 | ```bash 510 | taskkill /PID 12345 /f 511 | ``` 512 | 513 | **Important:** Replace the above example PID *12345*, with the process id (PID) you got in the previous step. 514 | 515 |
516 | 517 | [Back to top](#faqs) 518 | 519 |
520 | 521 |
522 | I got the error: "Error: connect ECONNREFUSED ::1:27017". What should I do? 523 | 524 |
525 | 526 | This error means that the Node.js application is unable to connect to a MongoDB instance running on the local (same) machine. 527 | There are a few things you should look at to troubleshoot this: 528 | 529 | 1. **Check the database connection string**: Check that the connection string is correct. The database connection string should be in the format: 530 | 531 | ```python 532 | mongodb://127.0.0.1:27017/databaseName 533 | ``` 534 | 535 | 2. **Verify that MongoDB is running on your machine**: Check that MongoDB is running on your machine. If it is not running, restart the service according to the following instructions: 536 | 537 | **On Mac:** 538 | 539 | Check if MongoDB is running on your machine, by running the command: 540 | 541 | ```bash 542 | brew services list 543 | ``` 544 | 545 | You should see the service `mongodb-community` listed as `started`. If not, run the following command to start it: 546 | 547 | ```bash 548 | brew services start mongodb-community 549 | ``` 550 | 551 | **On Ubuntu:** 552 | 553 | You can start the [`mongod`](https://www.mongodb.com/docs/manual/reference/program/mongod/#mongodb-binary-bin.mongod) process by issuing the following command: 554 | 555 | ```bash 556 | sudo systemctl start mongod 557 | ``` 558 | 559 | If you receive an error similar to the following when starting [`mongod`:](https://www.mongodb.com/docs/manual/reference/program/mongod/#mongodb-binary-bin.mongod) 560 | 561 | > ``` 562 | > Failed to start mongod.service: Unit mongod.service not found. 563 | > ``` 564 | 565 | Run the following command first: 566 | 567 | ```bash 568 | sudo systemctl daemon-reload 569 | ``` 570 | 571 | Then run the start command above again. 572 | 573 |
574 | 575 | **On Windows:** 576 | 577 | To open the *MongoDB* process on Windows, you will need to do these steps: 578 | - Go to your *Program Files* in your *C:* drive - the local disk 579 | - In *Program Files* go to the *MongoDB* folder 580 | - Inside the *MongoDB* folder, follow this path `Server/4.4/bin`. The version number on your system (`4.4`) may be slightly different for the newer installations. 581 | - Double-click on the file named **mongod.exe**. 582 | 583 |
584 | Check the image inside 585 | 586 |
587 | 588 | ![](https://education-team-2020.s3.eu-west-1.amazonaws.com/web-dev/prework/installations/win-installations-bootcamp-mongo-03.png) 589 | 590 |
591 | 592 |
593 | 594 | [Back to top](#faqs) 595 | 596 |
597 | 598 |
599 | Why is my database empty even though I am able to connect? 600 | 601 |
602 | 603 | It is normal for the database to be empty if you have not inserted any data into it. If you want to confirm that your connection to the database is working correctly, you can try inserting a simple document into a collection and then querying the collection or checking the database to see if the document was added. 604 | 605 |
606 | 607 | [Back to top](#faqs) 608 | 609 |
610 | 611 |
612 | I get the error "MongoDB is not running on the provided host and port" when trying to connect with MongoDB Compass. What should I do? 613 | 614 |
615 | 616 | If you are trying to connect to a MongoDB instance running locally, you should first check that MongoDB is running on your machine. If it is not running, restart the service according to the following instructions: 617 | 618 | **On Mac:** 619 | 620 | Check if MongoDB is running on your machine, by running the command: 621 | 622 | ```bash 623 | brew services list 624 | ``` 625 | 626 | You should see the service `mongodb-community` listed as `started`. If not, run the following command to start it: 627 | 628 | ```bash 629 | brew services start mongodb-community 630 | ``` 631 | 632 |
633 | 634 | **On Ubuntu:** 635 | 636 | You can start the [`mongod`](https://www.mongodb.com/docs/manual/reference/program/mongod/#mongodb-binary-bin.mongod) process by issuing the following command: 637 | 638 | ```bash 639 | sudo systemctl start mongod 640 | ``` 641 | 642 | If you receive an error similar to the following when starting [`mongod`:](https://www.mongodb.com/docs/manual/reference/program/mongod/#mongodb-binary-bin.mongod) 643 | 644 | > ``` 645 | > Failed to start mongod.service: Unit mongod.service not found. 646 | > ``` 647 | 648 | Run the following command first: 649 | 650 | ```bash 651 | sudo systemctl daemon-reload 652 | ``` 653 | 654 | Then run the start command above again. 655 | 656 |
657 | 658 | **On Windows:** 659 | 660 | To open the *MongoDB* process on Windows, you will need to do these steps: 661 | - Go to your *Program Files* in your *C:* drive - the local disk 662 | - In *Program Files* go to the *MongoDB* folder 663 | - Inside the *MongoDB* folder, follow this path `Server/4.4/bin`. The version number on your system (`4.4`) may be slightly different for the newer installations. 664 | - Double-click on the file named **mongod.exe**. 665 | 666 |
667 | Check the image inside 668 | 669 |
670 | 671 | ![](https://education-team-2020.s3.eu-west-1.amazonaws.com/web-dev/prework/installations/win-installations-bootcamp-mongo-03.png) 672 | 673 |
674 | 675 |
676 | 677 | [Back to top](#faqs) 678 | 679 |
680 | 681 |
682 | What is a timestamp in Mongoose schema and how do you use it? 683 | 684 |
685 | 686 | Mongoose schemas have an additional option called `timestamps`. If you set the option `timestamps: true`, Mongoose will automatically add two Date properties to your schema: 687 | 688 | - `createdAt`: a date that shows when the document was created 689 | - `updatedAt`: a date that shows the last time the document was updated 690 | 691 | Here's an example of how to set the `timestamps: true` option in a Mongoose schema: 692 | 693 | ```js 694 | const { Schema, model } = require("mongoose"); 695 | 696 | const userSchema = new Schema( 697 | { 698 | username: String, 699 | email: String, 700 | password: String, 701 | }, 702 | { 703 | // this option adds extra properties: `createdAt` and `updatedAt` 704 | timestamps: true, 705 | } 706 | ); 707 | 708 | 709 | const User = model("User", userSchema); 710 | 711 | module.exports = User; 712 | ``` 713 | 714 | For more information, check: [Mongoose: Timestamps](https://mongoosejs.com/docs/timestamps.html) 715 | 716 |
717 | 718 | [Back to top](#faqs) 719 | 720 |
721 | 722 |
723 | I am getting an error: "not defined". How do I fix it? 724 | 725 |
726 | 727 | The "ReferenceError: variable is not defined" error in JavaScript occurs when you try to access a variable or a function that has not been defined yet or is out of scope. 728 | 729 | To fix the issue, check that you have defined the variable or function that you are trying to use and double-check the spelling to make sure you are using the correct name. 730 | 731 | In case the variable or a function is defined in another file, make sure that the file has been imported or loaded correctly. 732 | 733 |
734 | 735 | [Back to top](#faqs) 736 | 737 |
738 | 739 |
740 | I am unable to push changes to the repository. What should I do? 741 | 742 |
743 | 744 | There are a couple of possible reasons why you may be unable to *push* changes to a Git repository: 745 | 746 | 1. **You have not committed your changes:** Before you can push your changes to the repository, you need to commit them using the `git commit` command. Make sure you have committed your changes and try pushing again. To do this, run the following terminal commands from the project folder: 747 | 748 | ```bash 749 | git add . 750 | git commit -m "Your commit message" 751 | git push 752 | ``` 753 | 754 | 2. **You do not have permission to push to the repository:** If you have cloned the repository directly from the main Ironhack repository without making a *Fork* first, you do not have write access to the repository. 755 | To check which remote repository you have cloned, run the following terminal command from the project folder: 756 | 757 | ```bash 758 | git remote -v 759 | ``` 760 | 761 | If the link shown is the same as the main Ironhack repository, you will need to fork the repository to your GitHub account first, and then clone your fork to your local machine to be able to push the changes. 762 | 763 | Note: You may want to make a copy of the code you have locally, to avoid losing it in the process. 764 | 765 |
766 | 767 | [Back to top](#faqs) 768 | 769 |
770 | -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | const router = require("express").Router(); 2 | 3 | /* GET home page */ 4 | router.get("/", (req, res, next) => { 5 | res.render("index"); 6 | }); 7 | 8 | module.exports = router; 9 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const app = require("./app"); 2 | 3 | // ℹ️ Sets the PORT for our app to have access to it. If no env has been set, we hard code it to 3000 4 | const PORT = process.env.PORT || 3000; 5 | 6 | app.listen(PORT, () => { 7 | console.log(`Server listening on port http://localhost:${PORT}`); 8 | }); 9 | -------------------------------------------------------------------------------- /views/error.hbs: -------------------------------------------------------------------------------- 1 |

Error!

2 |

There was an error on the server! Check the console!

3 | -------------------------------------------------------------------------------- /views/index.hbs: -------------------------------------------------------------------------------- 1 |

{{title}}

2 |

Welcome to {{title}}

3 | -------------------------------------------------------------------------------- /views/layout.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{title}} 9 | 10 | 11 | 12 | 13 | 14 | {{{body}}} 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /views/not-found.hbs: -------------------------------------------------------------------------------- 1 |

404 Error

2 |

This route does not exist on the app! Check if everything is ok!

--------------------------------------------------------------------------------