Skip to content

Instantly share code, notes, and snippets.

@bekaarcoder
Forked from bradtraversy/devcamper_specs.md
Last active June 19, 2020 07:26
Show Gist options
  • Save bekaarcoder/b45a172670dea84708d6d718b21d28ef to your computer and use it in GitHub Desktop.
Save bekaarcoder/b45a172670dea84708d6d718b21d28ef to your computer and use it in GitHub Desktop.

Revisions

  1. bekaarcoder revised this gist Jun 19, 2020. 4 changed files with 455 additions and 117 deletions.
    1 change: 1 addition & 0 deletions cloudSettings
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    {"lastUpload":"2020-06-19T07:25:49.035Z","extensionVersion":"v3.4.3"}
    117 changes: 0 additions & 117 deletions devcamper_specs.md
    Original file line number Diff line number Diff line change
    @@ -1,117 +0,0 @@
    # DevCamper Backend API Specifications

    Create the backend for a bootcamp directory website. The frontend/UI will be created by another team (future course). The html/css template has been created and can be used as a reference for functionality. All of the functionality below needs to be fully implmented in this project.

    ### Bootcamps
    - List all bootcamps in the database
    * Pagination
    * Select specific fields in result
    * Limit number of results
    * Filter by fields
    - Search bootcamps by radius from zipcode
    * Use a geocoder to get exact location and coords from a single address field
    - Get single bootcamp
    - Create new bootcamp
    * Authenticated users only
    * Must have the role "publisher" or "admin"
    * Only one bootcamp per publisher (admins can create more)
    * Field validation via Mongoose
    - Upload a photo for bootcamp
    * Owner only
    * Photo will be uploaded to local filesystem
    - Update bootcamps
    * Owner only
    * Validation on update
    - Delete Bootcamp
    * Owner only
    - Calculate the average cost of all courses for a bootcamp
    - Calculate the average rating from the reviews for a bootcamp

    ### Courses
    - List all courses for bootcamp
    - List all courses in general
    * Pagination, filtering, etc
    - Get single course
    - Create new course
    * Authenticated users only
    * Must have the role "publisher" or "admin"
    * Only the owner or an admin can create a course for a bootcamp
    * Publishers can create multiple courses
    - Update course
    * Owner only
    - Delete course
    * Owner only

    ### Reviews
    - List all reviews for a bootcamp
    - List all reviews in general
    * Pagination, filtering, etc
    - Get a single review
    - Create a review
    * Authenticated users only
    * Must have the role "user" or "admin" (no publishers)
    - Update review
    * Owner only
    - Delete review
    * Owner only

    ### Users & Authentication
    - Authentication will be ton using JWT/cookies
    * JWT and cookie should expire in 30 days
    - User registration
    * Register as a "user" or "publisher"
    * Once registered, a token will be sent along with a cookie (token = xxx)
    * Passwords must be hashed
    - User login
    * User can login with email and password
    * Plain text password will compare with stored hashed password
    * Once logged in, a token will be sent along with a cookie (token = xxx)
    - User logout
    * Cookie will be sent to set token = none
    - Get user
    * Route to get the currently logged in user (via token)
    - Password reset (lost password)
    * User can request to reset password
    * A hashed token will be emailed to the users registered email address
    * A put request can be made to the generated url to reset password
    * The token will expire after 10 minutes
    - Update user info
    * Authenticated user only
    * Separate route to update password
    - User CRUD
    * Admin only
    - Users can only be made admin by updating the database field manually

    ## Security
    - Encrypt passwords and reset tokens
    - Prevent NoSQL injections
    - Add headers for security (helmet)
    - Prevent cross site scripting - XSS
    - Add a rate limit for requests of 100 requests per 10 minutes
    - Protect against http param polution
    - Use cors to make API public (for now)

    ## Documentation
    - Use Postman to create documentation
    - Use docgen to create HTML files from Postman
    - Add html files as the / route for the api

    ## Deployment (Digital Ocean)
    - Push to Github
    - Create a droplet - https://m.do.co/c/5424d440c63a
    - Clone repo on to server
    - Use PM2 process manager
    - Enable firewall (ufw) and open needed ports
    - Create an NGINX reverse proxy for port 80
    - Connect a domain name
    - Install an SSL using Let's Encrypt

    ## Code Related Suggestions
    - NPM scripts for dev and production env
    - Config file for important constants
    - Use controller methods with documented descriptions/routes
    - Error handling middleware
    - Authentication middleware for protecting routes and setting user roles
    - Validation using Mongoose and no external libraries
    - Use async/await (create middleware to clean up controller methods)
    - Create a database seeder to import and destroy data
    412 changes: 412 additions & 0 deletions extensions.json
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,412 @@
    [
    {
    "metadata": {
    "id": "d3836729-9cc1-42c1-b2af-d50071f57d29",
    "publisherId": "formulahendry.auto-close-tag",
    "publisherDisplayName": "formulahendry"
    },
    "name": "auto-close-tag",
    "publisher": "formulahendry",
    "version": "0.5.7"
    },
    {
    "metadata": {
    "id": "2a658c1b-308a-41e8-805a-fc8abda483bc",
    "publisherId": "thekalinga.bootstrap4-vscode",
    "publisherDisplayName": "thekalinga"
    },
    "name": "bootstrap4-vscode",
    "publisher": "thekalinga",
    "version": "6.1.0"
    },
    {
    "metadata": {
    "id": "f583eafd-aa0d-4ccb-8f44-d1e610389660",
    "publisherId": "CoenraadS.bracket-pair-colorizer",
    "publisherDisplayName": "CoenraadS"
    },
    "name": "bracket-pair-colorizer",
    "publisher": "CoenraadS",
    "version": "1.0.61"
    },
    {
    "metadata": {
    "id": "e337c67b-55c2-4fef-8949-eb260e7fb7fd",
    "publisherId": "Shan.code-settings-sync",
    "publisherDisplayName": "Shan"
    },
    "name": "code-settings-sync",
    "publisher": "Shan",
    "version": "3.4.3"
    },
    {
    "metadata": {
    "id": "f57f68ea-9ee8-42b5-9a97-041d3e4278c4",
    "publisherId": "Dart-Code.dart-code",
    "publisherDisplayName": "Dart-Code"
    },
    "name": "dart-code",
    "publisher": "Dart-Code",
    "version": "3.11.0"
    },
    {
    "metadata": {
    "id": "19804510-b475-4dae-b0f7-6ca08fd1af0c",
    "publisherId": "dsznajder.es7-react-js-snippets",
    "publisherDisplayName": "dsznajder"
    },
    "name": "es7-react-js-snippets",
    "publisher": "dsznajder",
    "version": "2.8.0"
    },
    {
    "metadata": {
    "id": "f6c3ec04-6057-4d9c-b997-69cba07a6158",
    "publisherId": "Dart-Code.flutter",
    "publisherDisplayName": "Dart-Code"
    },
    "name": "flutter",
    "publisher": "Dart-Code",
    "version": "3.11.0"
    },
    {
    "metadata": {
    "id": "4de763bd-505d-4978-9575-2b7696ecf94e",
    "publisherId": "eamodio.gitlens",
    "publisherDisplayName": "eamodio"
    },
    "name": "gitlens",
    "publisher": "eamodio",
    "version": "10.2.2"
    },
    {
    "metadata": {
    "id": "6c6d4703-0393-49e4-bcbe-2c01f5184522",
    "publisherId": "andrejunges.Handlebars",
    "publisherDisplayName": "andrejunges"
    },
    "name": "Handlebars",
    "publisher": "andrejunges",
    "version": "0.4.1"
    },
    {
    "metadata": {
    "id": "198a707e-28af-4e84-8610-6e2f628dd12d",
    "publisherId": "redhat.java",
    "publisherDisplayName": "redhat"
    },
    "name": "java",
    "publisher": "redhat",
    "version": "0.62.0"
    },
    {
    "metadata": {
    "id": "c941a679-d500-46a8-b2a9-208063125901",
    "publisherId": "wholroyd.jinja",
    "publisherDisplayName": "wholroyd"
    },
    "name": "jinja",
    "publisher": "wholroyd",
    "version": "0.0.8"
    },
    {
    "metadata": {
    "id": "8b477a76-974c-403d-a454-58028c1709d1",
    "publisherId": "samuelcolvin.jinjahtml",
    "publisherDisplayName": "samuelcolvin"
    },
    "name": "jinjahtml",
    "publisher": "samuelcolvin",
    "version": "0.13.0"
    },
    {
    "metadata": {
    "id": "ad94b437-b5a7-4249-bf5f-df472ae0d084",
    "publisherId": "ritwickdey.live-sass",
    "publisherDisplayName": "ritwickdey"
    },
    "name": "live-sass",
    "publisher": "ritwickdey",
    "version": "3.0.0"
    },
    {
    "metadata": {
    "id": "b63c44fd-0457-4696-99e9-dbfdf70d77de",
    "publisherId": "ritwickdey.LiveServer",
    "publisherDisplayName": "ritwickdey"
    },
    "name": "LiveServer",
    "publisher": "ritwickdey",
    "version": "5.6.1"
    },
    {
    "metadata": {
    "id": "f015bc3c-a098-4245-8765-615e002e09ab",
    "publisherId": "yzane.markdown-pdf",
    "publisherDisplayName": "yzane"
    },
    "name": "markdown-pdf",
    "publisher": "yzane",
    "version": "1.4.4"
    },
    {
    "metadata": {
    "id": "3b1db1fc-c7f7-4bd6-9fa4-b499dfa99a8a",
    "publisherId": "shd101wyy.markdown-preview-enhanced",
    "publisherDisplayName": "shd101wyy"
    },
    "name": "markdown-preview-enhanced",
    "publisher": "shd101wyy",
    "version": "0.5.12"
    },
    {
    "metadata": {
    "id": "a4f91432-1b7d-4acd-b906-76d8ac8ad7e7",
    "publisherId": "mdickin.markdown-shortcuts",
    "publisherDisplayName": "mdickin"
    },
    "name": "markdown-shortcuts",
    "publisher": "mdickin",
    "version": "0.12.0"
    },
    {
    "metadata": {
    "id": "5db78037-f674-459f-a236-db622c427c5b",
    "publisherId": "PKief.material-icon-theme",
    "publisherDisplayName": "PKief"
    },
    "name": "material-icon-theme",
    "publisher": "PKief",
    "version": "4.1.0"
    },
    {
    "metadata": {
    "id": "26a529c9-2654-4b95-a63f-02f6a52429e6",
    "publisherId": "zhuangtongfa.material-theme",
    "publisherDisplayName": "zhuangtongfa"
    },
    "name": "material-theme",
    "publisher": "zhuangtongfa",
    "version": "3.8.0"
    },
    {
    "metadata": {
    "id": "4bf45e86-a448-4531-8c01-ef33f4536306",
    "publisherId": "ms-mssql.mssql",
    "publisherDisplayName": "ms-mssql"
    },
    "name": "mssql",
    "publisher": "ms-mssql",
    "version": "1.9.0"
    },
    {
    "metadata": {
    "id": "61e5eed3-2093-4ada-9be3-877fd5e50167",
    "publisherId": "gunturpoetra.nodejs-module-snippet",
    "publisherDisplayName": "gunturpoetra"
    },
    "name": "nodejs-module-snippet",
    "publisher": "gunturpoetra",
    "version": "0.0.2"
    },
    {
    "metadata": {
    "id": "dff6b801-247e-40e9-82e8-8c9b1d19d1b8",
    "publisherId": "christian-kohler.npm-intellisense",
    "publisherDisplayName": "christian-kohler"
    },
    "name": "npm-intellisense",
    "publisher": "christian-kohler",
    "version": "1.3.0"
    },
    {
    "metadata": {
    "id": "a41c1549-4053-44d4-bf30-60fc809b4a86",
    "publisherId": "christian-kohler.path-intellisense",
    "publisherDisplayName": "christian-kohler"
    },
    "name": "path-intellisense",
    "publisher": "christian-kohler",
    "version": "2.2.1"
    },
    {
    "metadata": {
    "id": "96fa4707-6983-4489-b7c5-d5ffdfdcce90",
    "publisherId": "esbenp.prettier-vscode",
    "publisherDisplayName": "esbenp"
    },
    "name": "prettier-vscode",
    "publisher": "esbenp",
    "version": "5.0.0"
    },
    {
    "metadata": {
    "id": "f1f59ae4-9318-4f3c-a9b5-81b2eaa5f8a5",
    "publisherId": "ms-python.python",
    "publisherDisplayName": "ms-python"
    },
    "name": "python",
    "publisher": "ms-python",
    "version": "2020.5.86806"
    },
    {
    "metadata": {
    "id": "f0c5397b-d357-4197-99f0-cb4202f22818",
    "publisherId": "ms-vscode-remote.remote-wsl",
    "publisherDisplayName": "ms-vscode-remote"
    },
    "name": "remote-wsl",
    "publisher": "ms-vscode-remote",
    "version": "0.44.2"
    },
    {
    "metadata": {
    "id": "529697b9-b343-4b1c-ba2f-f5ef692132d4",
    "publisherId": "ms-vscode.sublime-keybindings",
    "publisherDisplayName": "ms-vscode"
    },
    "name": "sublime-keybindings",
    "publisher": "ms-vscode",
    "version": "4.0.7"
    },
    {
    "metadata": {
    "id": "fb374ce1-5343-46c8-a425-900fdad15523",
    "publisherId": "wesbos.theme-cobalt2",
    "publisherDisplayName": "wesbos"
    },
    "name": "theme-cobalt2",
    "publisher": "wesbos",
    "version": "2.1.6"
    },
    {
    "metadata": {
    "id": "484d897a-6711-403c-ab54-a96f12be5833",
    "publisherId": "Equinusocio.vsc-community-material-theme",
    "publisherDisplayName": "Equinusocio"
    },
    "name": "vsc-community-material-theme",
    "publisher": "Equinusocio",
    "version": "1.4.1"
    },
    {
    "metadata": {
    "id": "dffaf5a1-2219-434b-9d87-cb586fd59260",
    "publisherId": "Equinusocio.vsc-material-theme",
    "publisherDisplayName": "Equinusocio"
    },
    "name": "vsc-material-theme",
    "publisher": "Equinusocio",
    "version": "32.6.0"
    },
    {
    "metadata": {
    "id": "0808d236-6faf-4f68-9f17-28f51a572ee4",
    "publisherId": "deerawan.vscode-faker",
    "publisherDisplayName": "deerawan"
    },
    "name": "vscode-faker",
    "publisher": "deerawan",
    "version": "1.4.1"
    },
    {
    "metadata": {
    "id": "61fcd0cf-64d7-4836-8d6b-d55f4fb83281",
    "publisherId": "vscjava.vscode-java-debug",
    "publisherDisplayName": "vscjava"
    },
    "name": "vscode-java-debug",
    "publisher": "vscjava",
    "version": "0.26.0"
    },
    {
    "metadata": {
    "id": "7865e561-1c83-410e-9b99-aabada597a7e",
    "publisherId": "vscjava.vscode-java-dependency",
    "publisherDisplayName": "vscjava"
    },
    "name": "vscode-java-dependency",
    "publisher": "vscjava",
    "version": "0.10.2"
    },
    {
    "metadata": {
    "id": "96f11e1f-1a46-4592-b084-f025b2c2a81f",
    "publisherId": "vscjava.vscode-java-pack",
    "publisherDisplayName": "vscjava"
    },
    "name": "vscode-java-pack",
    "publisher": "vscjava",
    "version": "0.9.1"
    },
    {
    "metadata": {
    "id": "67c06b0d-1891-42ca-b2a8-113e79bff069",
    "publisherId": "vscjava.vscode-java-test",
    "publisherDisplayName": "vscjava"
    },
    "name": "vscode-java-test",
    "publisher": "vscjava",
    "version": "0.23.0"
    },
    {
    "metadata": {
    "id": "b0f06c6b-24fb-4d7b-bd79-bc5e2fa17312",
    "publisherId": "vscjava.vscode-maven",
    "publisherDisplayName": "vscjava"
    },
    "name": "vscode-maven",
    "publisher": "vscjava",
    "version": "0.22.0"
    },
    {
    "metadata": {
    "id": "0bdca1de-109d-4135-8ca9-0d72cac04c26",
    "publisherId": "fabiospampinato.vscode-open-in-terminal",
    "publisherDisplayName": "fabiospampinato"
    },
    "name": "vscode-open-in-terminal",
    "publisher": "fabiospampinato",
    "version": "1.3.7"
    },
    {
    "metadata": {
    "id": "76b073cf-a5e7-434b-89a5-dc9203e312f8",
    "publisherId": "JakeWilson.vscode-placeholder-images",
    "publisherDisplayName": "JakeWilson"
    },
    "name": "vscode-placeholder-images",
    "publisher": "JakeWilson",
    "version": "0.1.0"
    },
    {
    "metadata": {
    "id": "9b2c953d-6ad4-46d1-b18e-7e5992d1d8a6",
    "publisherId": "akamud.vscode-theme-onedark",
    "publisherDisplayName": "akamud"
    },
    "name": "vscode-theme-onedark",
    "publisher": "akamud",
    "version": "2.2.1"
    },
    {
    "metadata": {
    "id": "f2fd462f-f1bd-4c62-b54f-59a4e5ffc6a3",
    "publisherId": "WakaTime.vscode-wakatime",
    "publisherDisplayName": "WakaTime"
    },
    "name": "vscode-wakatime",
    "publisher": "WakaTime",
    "version": "4.0.0"
    },
    {
    "metadata": {
    "id": "3262c42b-a248-4b97-9f4d-5a6812bac132",
    "publisherId": "midnightsyntax.vscode-wrap-console-log",
    "publisherDisplayName": "midnightsyntax"
    },
    "name": "vscode-wrap-console-log",
    "publisher": "midnightsyntax",
    "version": "1.7.2"
    }
    ]
    42 changes: 42 additions & 0 deletions settings.json
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,42 @@
    {
    "workbench.colorTheme": "Material Theme Darker High Contrast",
    "workbench.iconTheme": "material-icon-theme",
    "terminal.integrated.shell.windows": "C:\\WINDOWS\\System32\\cmd.exe",
    "editor.tabSize": 2,
    "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "editor.formatOnSave": true,
    "html.format.enable": true,
    "html.format.indentHandlebars": true,
    "html.format.maxPreserveNewLines": 0,
    "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "terminal.integrated.rendererType": "dom",
    "workbench.startupEditor": "newUntitledFile",
    "python.formatting.provider": "black",
    "python.linting.pylintArgs": [
    "--load-plugins=pylint_django",
    "--errors-only"
    ],
    "javascript.updateImportsOnFileMove.enabled": "always",
    "kite.showWelcomeNotificationOnStartup": false,
    "prettier.disableLanguages": [
    "scss",
    "sass"
    ],
    "liveSassCompile.settings.formats": [
    // This is Default.
    {
    "format": "expanded",
    "extensionName": ".css",
    "savePath": "/dist/css"
    }
    ],
    "[python]": {
    "editor.formatOnSave": false
    },
    "liveServer.settings.donotShowInfoMsg": true,
    "sync.gist": "b45a172670dea84708d6d718b21d28ef"
    }
  2. @bradtraversy bradtraversy revised this gist Oct 11, 2019. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions devcamper_specs.md
    Original file line number Diff line number Diff line change
    @@ -84,11 +84,11 @@ Create the backend for a bootcamp directory website. The frontend/UI will be cre

    ## Security
    - Encrypt passwords and reset tokens
    - Prevent cross site scripting - XSS
    - Prevent NoSQL injections
    - Add headers for security (helmet)
    - Prevent cross site scripting - XSS
    - Add a rate limit for requests of 100 requests per 10 minutes
    - Protect against http param polution
    - Add headers for security (helmet)
    - Use cors to make API public (for now)

    ## Documentation
  3. @bradtraversy bradtraversy created this gist Sep 24, 2019.
    117 changes: 117 additions & 0 deletions devcamper_specs.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,117 @@
    # DevCamper Backend API Specifications

    Create the backend for a bootcamp directory website. The frontend/UI will be created by another team (future course). The html/css template has been created and can be used as a reference for functionality. All of the functionality below needs to be fully implmented in this project.

    ### Bootcamps
    - List all bootcamps in the database
    * Pagination
    * Select specific fields in result
    * Limit number of results
    * Filter by fields
    - Search bootcamps by radius from zipcode
    * Use a geocoder to get exact location and coords from a single address field
    - Get single bootcamp
    - Create new bootcamp
    * Authenticated users only
    * Must have the role "publisher" or "admin"
    * Only one bootcamp per publisher (admins can create more)
    * Field validation via Mongoose
    - Upload a photo for bootcamp
    * Owner only
    * Photo will be uploaded to local filesystem
    - Update bootcamps
    * Owner only
    * Validation on update
    - Delete Bootcamp
    * Owner only
    - Calculate the average cost of all courses for a bootcamp
    - Calculate the average rating from the reviews for a bootcamp

    ### Courses
    - List all courses for bootcamp
    - List all courses in general
    * Pagination, filtering, etc
    - Get single course
    - Create new course
    * Authenticated users only
    * Must have the role "publisher" or "admin"
    * Only the owner or an admin can create a course for a bootcamp
    * Publishers can create multiple courses
    - Update course
    * Owner only
    - Delete course
    * Owner only

    ### Reviews
    - List all reviews for a bootcamp
    - List all reviews in general
    * Pagination, filtering, etc
    - Get a single review
    - Create a review
    * Authenticated users only
    * Must have the role "user" or "admin" (no publishers)
    - Update review
    * Owner only
    - Delete review
    * Owner only

    ### Users & Authentication
    - Authentication will be ton using JWT/cookies
    * JWT and cookie should expire in 30 days
    - User registration
    * Register as a "user" or "publisher"
    * Once registered, a token will be sent along with a cookie (token = xxx)
    * Passwords must be hashed
    - User login
    * User can login with email and password
    * Plain text password will compare with stored hashed password
    * Once logged in, a token will be sent along with a cookie (token = xxx)
    - User logout
    * Cookie will be sent to set token = none
    - Get user
    * Route to get the currently logged in user (via token)
    - Password reset (lost password)
    * User can request to reset password
    * A hashed token will be emailed to the users registered email address
    * A put request can be made to the generated url to reset password
    * The token will expire after 10 minutes
    - Update user info
    * Authenticated user only
    * Separate route to update password
    - User CRUD
    * Admin only
    - Users can only be made admin by updating the database field manually

    ## Security
    - Encrypt passwords and reset tokens
    - Prevent cross site scripting - XSS
    - Prevent NoSQL injections
    - Add a rate limit for requests of 100 requests per 10 minutes
    - Protect against http param polution
    - Add headers for security (helmet)
    - Use cors to make API public (for now)

    ## Documentation
    - Use Postman to create documentation
    - Use docgen to create HTML files from Postman
    - Add html files as the / route for the api

    ## Deployment (Digital Ocean)
    - Push to Github
    - Create a droplet - https://m.do.co/c/5424d440c63a
    - Clone repo on to server
    - Use PM2 process manager
    - Enable firewall (ufw) and open needed ports
    - Create an NGINX reverse proxy for port 80
    - Connect a domain name
    - Install an SSL using Let's Encrypt

    ## Code Related Suggestions
    - NPM scripts for dev and production env
    - Config file for important constants
    - Use controller methods with documented descriptions/routes
    - Error handling middleware
    - Authentication middleware for protecting routes and setting user roles
    - Validation using Mongoose and no external libraries
    - Use async/await (create middleware to clean up controller methods)
    - Create a database seeder to import and destroy data