GithubHelp home page GithubHelp logo

university's Introduction

hapijs university

Use JavaScript and hapijs to build web applications. See the essentials of how to build hapi applications: authentication, validation, application architecture, and testing. Plus, delve into deeper topics like: bearer-tokens, caching, the request lifecycle.

Assignments and Solutions

[Assignment1] Let's get started!

First, we need some basic structure: a lib folder, a package.json file, and an initial ./lib/index.js. Since we will be using hapi, we need to include that in the project dependencies. Second, create a basic hapi server on port 8000 which responds to /version requests and replies with a simple { "version": "0.1.1" } JSON payload. The version data in the response should come from the package.json file.

npm init
npm install --save hapi

View Solution

credits for assignment1

Above assignment is from original assignment1 by @hueniverse and work by @AdriVanHoudt. See this PR.

pre-assignment2 reading:

[Assignment2] plugins

The right way to work with hapi is to build your application using plugins. Plugins provide a way to organize your code into logical components and then put them together in different combinations or deploy them in different configurations. While some plugins are published as general purpose utilities (e.g. adding authentication), you should think of plugins as a way to break your code into pieces.

Now that we have a basic server with one endpoint, we want to move the creation of the endpoint to a plugin, and then register that plugin with the server. Create a new file lib/version.js and move the /version endpoint there. Then, change our current lib/index.js to require the new plugin file and register the version plugin with our server. The server.register() function is used to register the plugin.

Remember to follow the style guide, and ask any questions in the comments of the issue created for the assignment. If you are not sure how to get your fork back in sync with the current updated code, use the git guide.

/version end point should reply with a simple JSON payload:

{
    version: Package.version,
    message: options.message
}

Highlights

  • Notice that const plugins = [] is an array. An array is used to register the Version plugin because more plugins are to be registered in later assignments.
  • Notice how options are passed to the plugin: { message: 'assignment2' }. The /version point returns the message value.
  • In contrast to plugin options, notice how server.register options are passed: { once: true }. Often there is confusion between hapi's server.register options and options passed to a plugin being registered. lesson2 clearly shows the difference. { message: 'assingment2' } illustrates options passed to a plugin. These are options used inside the Version plugin. And, the { once: true } option is passed to the server when registering plugins: server.register(). See /lib/index.js for details.

Helps

  • require('./version') should be declared at the top and assigned to Version`.
  • no need for specifying the plugin version in the attributes. This is an internal plugin, not a publicly published one.

compare assignment2 solution to assignment1
view assignment2 solution source

Assignment2 Credits

This assignment is from the original assignment2 convert to plugin and discussion related to the assignment written by @hueniverse. The code solution is from work done by @MylesBorins.

[Assignment3] Testing & 100% coverage

Things are getting a bit more interesting...

It's time to add tests, verify coverage, confirm style, and automate all of this with CI (CI means: Continuous Integration). We will be using the lab module to perform these tasks and automate them with travis. Code will be our test's assertian library.

  1. Export init() and move the server invocation to a new lib/start.js file. The lib/start.js file calls the exported init() function and passes configurations options to it. The resolved promise function in start.js outputs the server config details to the console. Change package.json file to use start.js as the start up script. start.js file is not covered by tests. Designing the server to start with an exported init function allows other scripts and applications to start and stop the server. This is important for several reasons:
    • It allows testing scripts to start and stop the server to execute tests.
    • It allows another program to start and stop the application. This is useful when using hapi to build services - soa (service oriented architecture). Sometimes you make several hapi services to run on one computer and collaborate with each other.
    • It allows for the start.js script to start and stop the application.
  2. Add a .travis.yml file. When a .travis.yml file exists in a GitHub repository the project is built and all tests are executed. .travis reports if all tests successfully pass or not. Note, you must configure github to excute travis CI upon events (push or PR) to the repository. This is found under: Settings -> Integration & Services.
  3. Add a test folder with two files, version.js and index.js, each testing the corresponding file under /lib.
  4. Modify the package.json file to include tests. Install the dev dependencies lab and code.
  5. When using lab, enable coverage, require 100% coverage, enable linting with default rules, and install and use code assertion library. See package.json file to view the test command or see a test command write up here.
  6. Write a basic test to verify our version endpoint in version.js.
  7. Write tests to get 100% coverage. To get 100% test coverage you also need to confirm style. lab confirms if the project's code abides by the hapijs style guide. This is called 'linting'.

Everything should be pretty straight forward. If you are not sure on how to use lab and code, look at other hapi.js modules and copy their test scripts and setup.

Getting 100% coverage can be tricky sometimes so if you are not sure, get as much coverage as you can, and comment on the lines in your pull request where you are having a hard time reaching and someone will give you a clue.

Remember to properly stop() your servers when calling the init() method in each test.

For now, avoid using any of the before() and after() lab features.

As always, ask for help and help others!

Helps

  • When stubbing / patching code in a test, mark that test with the { parallel: false } lab option to make it both safe for future parallel testing as well as visual cue.
  • Never return anything other than an actual Error as an error (e.g. no strings, plain objects, etc.).
  • Never use fixed port numbers in tests, only 0 or the default.
  • Always return before next() unless there is a reason to continue.
  • Make arguments / options in init() required.
  • When calling server.inject() with a GET request, just pass the path string as the first argument instead of an options object. Makes the code much more readable.
  • Use the testing shortcuts boilerplate used in hapi. Makes reading tests easier.

lab summary

  • elegant lab and code
    good lesson three game plan
    go test for dirty bugs
    • clean up guy on github see travis agree
    • talk style, value guidance, hapi emotion,
      lab enforces all.
      Seek linting, Geek leadership no excuses find lab have fun.

Compare Assignment3 Solution to Assignment2
view assignment3 solution source

Credits

Assignment is from original assignment3 and discussion related to it. The author was @hueniverse. Original code for the solution was written by idanwe. See: PR for original source code for solution. The .travis.yml file is from the hapi project.

[Assignment4] Use server.app properties

  • Read documentation server.app property
  • Use the server.app property to store the application's response.version and options.message.
  • Access the request.server property in the ./lib/version.js handler to return the server.app.version and server.app.message values.
  • Note: The server.app property is useful to set a DB connections in. server.app properties are available wherever the request.server is exposed. As the documentation says:

    server.app provides a place to store run-time application data. Data can be accessible wherever the server object can be accessed.

Compare Assignment4 Solution to Assignment3

[Assignment5] Project Structure

  • In this lesson we change the /version route handler function location. The goal is design program code that is easy to maintain and reuse. Moving route functions from the plugin which registers routes makes for readable route registration plugins. Plus, it allows for easier maintenance and reuse of methods or functions.
    • When a plugin registers multiple routes or has routes with the request-lifecycle extended, plugin code can get cluttered. Moving method / function logic out of the plugin keeps route logic readable. Lesson8 will explore the request-lifecycle more.
    • There is a limitation to removing route functions from the plugin registering the route. Options passed to the plugin at registration time are not available to functions built in files seperate from the plugin. However, usually this is not an issue. Or, the issue can be by-passed using server.app properties.
  • Create a route methods directory ./lib/route-methods. Methods used in routes will be stored in this directory.
  • Create a version.js file in the route-methods directory ./lib/route-methods/version.js
    Methods used in the /version route will be stored here.
    Move the /version handler function to this file.
  • Note: this is a personal style preferrence.
    Preferrence is to make a split screen view with:
    • the screen on the left
      displaying routes ./lib/version.js
    • the screen on the right
      displaying methods executed in the routes ./lib/route-methods/version.js
  • Run tests. No new tests need to be built. But, need to increment lesson value to 1.0.5. Executing passing tests proves changes did not break the application. Enjoy the benefits of CI Continuous Integration.

Compare Assignment5 Solution to Assignment4

[Assignment6] auth bearer tokens

  • add hapi-auth-bearer-token
    npm install --save hapi-auth-bearer-token
  • Register the authentication strategy in it's own plugin ./lib/authtoken.js.
  • all routes must have valid token to be accessed
    • currently only one route exists: /version.
    • valid token equals 1234574
  • 100% tests coverage.
    Adjust /version tests for token authentication. Test for passing and failing tokens.

Notice we have not created user authentication yet -- users have no way to log in. Tests for the assignment assume a valid auth bearer token for the user already exists. The focus is on getting hapi auth bearer token plugin installed and configured. This lesson does not build a complete authentication system.

Here are resources related to auth bearer tokens. Please share if you know of other links and resources related to the subject.

Compare Assignment6 Solution to Assignment5

Notes on original authentication assignment

This assignment started as assignment4.
It contains good discussion regarding authentication issues. For the original solution see: PR. It used hapi-auth-basic.

[Assignment7] TLS

Credits

Original TLS assignment completed by @rutaihwa.

Compare Assignment7 Solution to Assignment6

[Assignment8] /authenticate route

  • build ./authenticate route.
    This moves us one step closer to completing the authentication system.

  • Build data store database.js to authenticate user records with. User records contain scope values to implement hapi's way of doing RBAC (role based access control). For this project their are two scopes: ['admin', 'member']. admin is administrative user and member is a normal user.

  • methods executed in the /authenticate route are stored in the ./route-methods/authenticate.js file. This seprates logic:

    • ./lib/version.js contains route registration logic.
    • ./route-methods/authenticate.js contains methods executed in the route.
    • The /authenticate route utilizes hapi's prerequisite request-lifecycle extension. The pre method is executed before the handler.
  • Request-lifecycle extensions allows for logic to be split up into multiple functions and be executed at specific times when a request is made to a route.
    In respect to route.options.pre methods,

    These methods allow breaking the handler logic into smaller, reusable components that can be shared across routes, as well as provide a cleaner error handling of prerequisite operations (e.g. load required reference data from a database). Source: route.options.pre

    See other documentation for more about the request lifecycle:

    The request lifecycle is an essential part of the hapi framework. As the documentation says: "Every incoming request passes through the request lifecycle". Therefore, you want to be familiar with it.

  • No authStrategy applied to /authenticate point.

  • generate bearer-token upon successful authentication (cryptiles).

  • Use Boom to return errors.

Compare Assignment8 Solution to Assignment7

Credits

  • Lesson has some influence from assignment4 of earlier version.

[Assignment9] tokens, cache, basic authentication system

This lesson completes a basic token based authentication system. Currently, our server only has two routes: /version and /authenticate. Only users with authentic bearer tokens can access server routes. See token strategy in: ./lib/authtoken.js. The lib/authtoken.js strategy is crude supporting one static token. On the /authenticate route we turn off the requirement for an authentic bearer token with the false option because unauthenticated users do not have bearer tokens yet. The false option exposes routes to public unauthenticated users.

At this point, there is a disconnect in the system. A user can generate a valid auth token on the /authenticate route. But, that token is not stored for future use. As stated earlier, the authentication strategy only considers one token as valid (1234574). To resolve this issue we use redisdb and hapi's caching plugins.

First, configure a bearer token cache. When a user successfully authenticates, the auth-bearer-token generated for the session is stored in the cache catabox-redis. Along with the token, the authenticated user account data is also stored in the cache. This is where a users scopes are stored. Scope values determine which routes a user can access. Second, the validateFunction for the auth-bearer-token strategy is modified to use the bearer token cache to validate received tokens. This solves the above mentioned disconnect in our bearer token system. Third, we create a /private route which requires administrative user privileges (admin scope) to access route data.

  • auth-bearer-token cache
    • install redisdb
    • configure server to use catbox-redis. This is done in the ./lib/tokencache.js plugin.
      See hapi caching and catbox-redis documentation.
    • Upon successfull authentication set the bearer-token in cache along with the user record: ./lib/route-methods/authenticate.js.
    • Expire the token after xxxxx time. Set expiresIn: value with server.options. This allows tests to configure shorter expiration times to avoid sessions created from previous tests colliding.
    • configure scopes ['admin', 'member'] for role based access.
    • configure .travis.yml to use the redis server
  • authentication
    Refactor authentication logic to:
    • pre-empt one user from generating multiple tokens using an active cache. active cache is configured in ./lib/tokencache.js.
    • upon successful authentication set token and user record information in the authtokens cache. authtokens cache configured in ./lib/tokencache.js.
    • The ./lib/route-methods/authenticate.js logic is where new auth-tokens are stored in the cached upon successful authentication. Plus, logic to pre-empt the creation of duplicate tokens is written here too.
  • lib/authtoken.js
    • re-write the defaultValidateFunc to use the catbox-redis cache to authenticate tokens.
  • server configuration options
    Configure the server application Configs to set the tokencache.js plugin options. This allows for test configurations to be modified. Our test configurations modify token expiration times so tokens from different tests do not collide. See: ./lib/start.js const Configs.plugins.tokenCache.expiresIn.
  • create ./private point which requires admin scope for access
    • Apply default authStrategy to ./private point.
  • tests
    • write 100% test coverage
    • Note FYI (For your information), when building tests for hapi-auth-bearer-token may need to add { debug: false } to your server configs. This avoids hapi-auth-bearer-token printing verbose error reports.
  • See relevant documentation below:

Credits

.travis.yml implementing redisdb is from: catbox-redis project.

Lesson9 solution

university's People

Contributors

adrivanhoudt avatar gitter-badger avatar idanwe avatar mikeal avatar zoe-1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

university's Issues

Getting started guide

Write guide that explains to a new comer how to get started with to hapijs / university .
Write better explanation of steps described at #160

Assignment8 Preparations

Considering the following for Assignment8:

Combat Cross-Site Request Forgery (CSRF) attacks:

  • hapijs crumb
  • include crumb values in forms.
  • send crumb through ajax requests.

Server monitoring:

  • good
  • handle various types of logging.
    • normal requests
    • log alert requests - crumb fails error handles etc.
      create unique logging for errors related to security issues.

Review important concepts and find concept examples within the project.

  • internals and global abatement.
  • asynchronus versus synchronus
  • nodejs module singleton design
    • require() and singleton
    • module globals versus node.js globals
    • memory leaks
  • JavaScript closures and variable scope
  • server object
  • requests
    • request lifecyle
  • reply interface
  • plugin management
    • glue
    • associating plugins with correct server connections/labels
    • dependencies
      • ensuring plugin loads after dependencies. (dependency after logic)
      • versus dependencies declared attributes but load order unassurred.
  • style guide and linting
  • testing 100% coverage
    • lab & code
  • restful
  • Add your suggestions to the review list.

Add your comments and suggestions.

upgrade project to use hapi v15

hapijs/hapi#3323

dependencies to update

  • async 1.5.2 -> 2.x.x
  • boom 3.x.x -> 4.x.x
  • glue 3.x.x -> 4.x.x
  • good 6.x.x -> 7.x.x
  • good-console 5.x.x -> 6.x.x
  • added good-squeeze 5.x.x (good v7 requires it)
  • good-file 5.x.x -> 6.x.x
  • hapi 13.x.x -> 15.x.x
  • hoek 3.x.x -> 4.x.x
  • inert 3.x.x -> 4.x.x
  • joi 8.x.x -> 9.x.x

devDependencies to update

  • code 2.x.x -> 4.x.x
  • lab 9.x.x -> 11.x.x

branch update status

  • master
  • assignment8
  • assignment7
  • assignment6
  • assignment5
  • assignment4
  • assignment3
  • assignment2
  • assignment1

Create a basic HTTP server

Let's get started!

First, we need some basic structure: a lib folder, a package.json file, and an initial index.js. Since we will be using hapi, we need to include that in the project dependencies.

Second, create a basic hapi server on port 8000 which responds to /version requests and replies with a simple { "version": "0.0.1" } JSON payload. The version in the response should come from the package.json file.

Assignment due: 3/17

Got questions or need help? Post a comment.

Need new logo

Project needs a logo.
images/logo.png needs to be changed to "hapijs university" from "hueniversity".
Be creative but keep the hapijs space cadet hat in the logo.

Assignment9 and Beyond

Where are we going next? Most of the goals discussed at: #132 have been achieved.

Below is a list of subjects discussed earlier that have not yet been covered or were lightly
covered. @FennNaten made most of the below recommendations in the discussion at: #132.
Read the below and share your thoughts about the direction of the university :-)

  • Caching handling, both client-side with hapi abilities and server-side with catbox.
    Caching correctly is critical to have reactive websites.
  • We have done nothing with caching yet.
  • Role-based authorization. There may be plugins to do that already, or it can be handled by using several auth strategies,
    but it would be cool for everyone to try an implementation, saying e.g. that roles that can access a route should be provided as route configuration,
    and role-check performed at post-authentication. This would drive us into using request lifecycle hooks.
    • This has been explored some with hapi-auth-cookie and scopes but we could go deeper.
  • Maybe having some data exposed using CORS and/or jsonp (let's say our awesome website exposes a little public module
    for people wanting to display our latest news on their own site) Some form of content negociation.
    Let's say e.g. that our nice 'latest news' endpoint can serve the data as xml, json or plain text depending on request headers.
    Routes documentation with lout.
  • Configuration switch tied to environment maybe (e.g. dev/test).
  • Some client-side js loading data from our API via ajax requests ?
    Provide error pages to hook on some http statuses (unauthorized, 404, server errors).
    Would be another opportunity to hook on the request/response lifecycle.
    • Already covered this but we could go deeper.
  • @simon-p-r on gitter mentioned configuring tls options for ciphers and honorCipherOrder which control the protocol level used.
    I have not researched this but it's here for discussion.
  • Making proper use of a database.

    Over the past several months, many expressed the desire to include a database (See #132).
    At this point in the project, it would be reasonable to include a DB. Since hapijs is part of the
    JavaScript and node.js universe, it would be appropriate to use a JSON document database like couchDB or Mongo. Or, perhaps the community wants to keep the university focused on JavaScript and hapijs. What are your thoughts? Personally, I think database support would make the university much more interesting and attractive to people who are considering changing technologies and begin using hapijs.

I have been preparing to use couchdb in a hapijs application by writing logic with 100% test coverage here: sofajs This project is not complete but it illustrates a direction we could head with couchdb (nano and 100% hapijs/lab test coverage)

Other Ideas:

  • image/file uploading
    Most developers would benefit from some file uploading code. Coming from Rails I still appreciate plugins like: paperclip. I have not seen anything like this in the node.js world. Perhaps it exists, but I have not found it yet.
  • Consider contributing an assignment?
    If you see a subject in the above list you have experience with, consider sharing your knowledge by writing an assignment :-) You will learn more by teaching a subject than studying it.

update assignment7

Update assignment7 branch to reflect the fulfillment of assignment7 using:

  • ES6 - must pass current hapi linting standards.
  • current hapi plugins. (hapi v13 etc)

Basic authentication

Using the hapi-auth-basic plugin, add a new /private endpoint protected by a username and password that returns a simple HTML page with a welcome message. The welcome message should include the logged in username. Do not use any templates (views) at this stage. For username/password validation, create a static lib/users.json file (we will replace this in the near future) that contains a few sample users and passwords.

The new endpoint will be contained in its own plugin, similar to how we set up /version, and will require bringing test coverage back to 100%.

Due: 4/27

Starting late

I just found hueniveristy, is it too late to start joining in on the learning?

Validation, Authentication, and Authorization

Objectives

  • Use joi to validate submitted POST data.
  • Gain basic understanding of the hapijs request lifecyle.
  • Understand hapi-auth-cookie authentication and authorization
    • strategies
    • sessions and cookies
    • scopes
  • Implement simple RBAC (role based access controls) using hapi's scopes
    to implement an authorization scheme.
  • Make basic login and logout functionality.
  • Configure application to handle bad route requests.
  • Begin designing an api to support multiple clients.

Study Helps

If you read the assignment requirements and do not know where to start then go to: the study helps. Or, view this sample hapi-auth-cookie project . It is written using ES6 JavasScript and uses hapi v13 so it
is an up-to-date example.

Cookie-based session management.

Configure hapi-auth-cookie for cookie-based session management.
Every route will be black listed requiring authentication and authorization globally.
White list public routes. Make two user roles for basic RBAC authorization:

  • "admin" the super user
  • and "user" basic user

There will be three types of authorization restrictions:

  • "public" routes open to all
  • "user" routes restricted to authenticated users with the role of "user" or "admin".
  • "admin" routes restricted to authenticated users with the role "admin".

Login Process

We created the GET /login route in assignment6. This route is to be open to the public.
When the user clicks the submit button on the HTML form, client side JavaScript should handle the submission and make an AJAX POST request. If the POST request is successful, the login form should disappear and user is presented with links to access restricted content /account or /logout. At this stage the login process is complete, session cookies are set, and authorized users can begin to access restricted content.

If the login AJAX request fails, a red HTML format error message is displayed above the login form.
If the user clicks submit again the error message should disapear.
Bonus: Add clientside logic to avoid duplicate form submissions.

api first steps

Building towards a client-server architecture for an application that serves multiple clients.
Begin building the api:

  • Make an 'api' label along with the web-tls connection.
  • Make a ./lib/api directory.
  • Make a ./lib/api/login.js
    • Make POST ./login route in this directory.
    • configure this plugin to use hapi-auth-cookie and begin the session upon successful login.
    • handle AJAX POST request at ./login route.

Restricted Access Content

The /account route

After a successful login, user sees "My Account" link and "Logout" link.
The "My Account" link goes to the /account route which is restricted to authenticated users with roles of "user" or "admin". The /account route will display a page with the username of the logged in user and the following links: "Logout", "Home", and "Admin Panel" (if user has admin privileges).
Correspondingly, the previous mentioned links point to /logout, /home, and /admin.

The /admin route

The /admin route should display an admin welcome message with the admin's username displayed.
Plus, there should be three links: "My Account", "Logout" , "Home".
Only users with the role of "admin" should be able to access /admin route.

The /home route

If a logged in user goes to /home, "My Account" and "Logout" links are displayed along with the
hapi university image. When a user clicks on the "My Account" link they are taken to the /account route described above. If user is not logged in the login link is displayed.

Logging Out

On /home, /account, and /admin routes there should be a logout button which links to /logout and destroys the session. Plus, the /login POST route should have a "Logged out" message displayed after the logout AJAX request successfully completes.

Other Technical Details and Refactoring:

When configuring the application to use hapi-auth-cookie

  • Remove hapi-auth-basic from the application.
    Remove the private plugin too.
  • Make plugin: ./lib/auth-cookie.js which:
    • Configures hapi-auth-cookie authentication strategy to project.
    • redirects to '/login' route if the user is not logged in.
    • Requires the use of tls.
    • ttl: 60 * 100 or greater.
    • Configure the strategy to use tls.
    • Apply this auth strategy to every route in the application.
      White list the routes that do not require authentication or authorization.
  • When creating the session cookie with hapi-auth-cookie do not put sensitive
    user account data (i.e. passwords) in the session cookie. Before creating a session, use Hoek to clone the account data JSON object then delete passwords from the newly cloned object. Once secure data is removed create the user's session with: request.auth.session.set(account).
  • Use scopes to control which authenticated users are
    authorized to use the specific routes. First steps toward RBAC (role based access controls).
  • Refactor ./lib/users.json to have user records like below.
    Most importantly user records must now have the scope array for RBAC.
 "foo": {
        "id": 1,
        "username": "Foo Foo",
        "password": "foo",
        "email": "[email protected]",
        "scope": ["user", "admin"]
    },
  • Configure restricted routes to redirect to the /home, if the user
    is not authenticated or authorized to view the page.
  • (Optional) When handling /login POST requests use poeticninja 's style of using
    a JavaScript Promise to authenticate users. Important, use bluebird to
    make promises, otherwise, node.js v0.10.0 will fail. It cannot handle plain JavaScript promises.
    • Use boom to return authentication errors.
      Follow poeticninja's way of using boom.
  • Add bad route handling to project.
    Configure a server.ext('onPreResponse') to redirect to /home when routes
    do not exist. {"statusCode":404,"error":"Not Found"}
  • Add unauthorized access attempt handling to the project.
    If a logged in used attempts to view a page not authorized to access, user is
    redirected to /home. Hint: this is the related error info. "statusCode":403,"message" and "Insufficient scope..."
  • joi validation
    All POST request payloads must be validated by joi.
  • Optional: feel free to use JQuery on the client if you want to.
  • Last but not least, 100% test coverage required.

Due Date July 7, 2015

The work required to master the content of this assignment will reap benefits over the long run. hapi's authorization and authentication logic is powerful and beautiful. :-) Let's push each other to work hard and make this assignment a great learning experience!

crumb, good process monitoring, and lout

Configure Crumb

Crumb combats CSRF (Cross Site Request Forgery) using crumb generation and validation. See CSRF Prevention Cheat Sheet for more details about CSRF and tokens.
By default hapijs/crumb adds a crumb token to every view context. This allows for the token to be placed into forms and validated ensuring each request is from the proper user session.

In order to facilitate a "transparent but visible" CSRF solution, developers are encouraged
to adopt the Synchronizer Token Pattern.
The synchronizer token pattern requires the generating of random "challenge" tokens that are
associated with the user's current session. These challenge tokens are then inserted within
the HTML forms and links associated with sensitive server-side operations. When the user
wishes to invoke these sensitive operations, the HTTP request should include this challenge token.
It is then the responsibility of the server application to verify the existence and correctness
of this token.
Source: OWASP Cheat Sheet

  • Configure application to use crumb
  • Ensure all POST requests in the api enforce crumb validation.

Configure Good Hapi Process Monitor

report using:

  • good-console
  • good-file

Generate Documentation Using hapijs/lout

After configuring the application to use lout, route documentation can be viewed at: localhost:8001/docs.

100% test coverage required

Assignment Helps

Most crumb usage modeled after npm/newww

Assignment Due July 29, 2015

upgrade to hapi v16

hapijs/hapi#3323

dependencies to update

  • hapi 15.x.x -> 16.x.x
  • joi 9.x.x -> 10.x.x

branch update status

  • master
  • assignment8
  • assignment7
  • assignment6
  • assignment5
  • assignment4
  • assignment3
  • assignment2
  • assignment1

Beginners Prerequisite exam (puzzle?)

I think it is great if you guys gave some sort of challenge question to help people know what they should know before spending time on this project. I would like to send this to some students of mine but with everyone with varying levels of skill it might not be a good idea. A simple explanation would suffice so I can properly instruct my class on whats expected of them.

Basic Linting / Testing

It is suggested that individuals follow the hapi style guide while working on this project. It was also suggested that we might want to expand upon our projects by doing things such as writing tests.

My current stack involves eslint + jscs + tape. That being said I know that the hapi project uses lab.

Would it make sense to add a basic pass at lab into our first lesson or is this planned to come in as a separate lesson on testing? I mostly don't like writing any code without some sort of sanity check, but don't want to derail a future lesson plan.

rewrite getting started guide

  • Getting started guide needs to be re-written to match
    the method of submitting assignments.
  • Each branch is the solution to an assignment.
    Previously, branches were starting points.

Assignment 7 improvements

I've been working through all the updated assignments. They've all worked pretty well for me up to assignment 7.

In comparison to the others, the scope of assignment 7 seems to be quite large. Not only are there more pieces to the assignment but the pieces themselves seem more complicated. I have looked through the currently accepted solution to try to reverse engineer how it works but I have come across a few main problems with that.

  • It is not very clear what the new tests are trying to accomplish, particularly for auth-cookie. The purpose of generateSession is also not very clear and further complicates understanding the auth-cookie tests.
  • There are some chunks of what appear to be commented out code in generateSession and auth-cookie. It's hard to tell what their purpose once was and why they may have been commented out.
  • It seems hard to test files in isolation. It appears that the tests for auth-cookie need some auth functionality defined in user.js in order to pass and vice versa.

Would it be possible to rework the assignment or at the very least the solution to it a bit in order to try to isolate what exactly needs to be done in order to get the desired auth setup to work?

I would be happy to help contribute to some refactoring. As of right now I am not sure exactly where I would start but I will continue to try to figure out how things work and may do some cleanup on my own if I am able to.

Glue and HTML views

We transitioned to hapijs university.

For details about this change see:

Let's keep our project going! This is community learning which means much of the learning will be
horizontal and not just vertical! Make your contribution, ask questions, give advice (review others code) , share your thoughts about our project's direction and let's push each other to keep growing :-)

The Assignment

  • Refactor the application to use the hapijs server composer hapijs / glue.
    Glue should be used to load "version" and "private" plugins.
    Here is a helpful resource from the Glue project: Sample Manifest JSON object .
  • Create a plugin called "home":
  • This plugin should contain one endpoint called "home".
  • Configure the plugin to use handlebars template rendering engine to render html templates.
  • Configure this plugin to serve html view files and make the home endpoint render an html page/template named home.
  • Configure the home plugin to find view files in a directory named "views" located in
    the root path of the application. For now, just make html pages for view files (no .hbs files).
  • The view directory should contain one html template named home.html.

    When viewed in a browser, the home.html template should display the path to this view file from the root of our project.
  • In the end, the application should have thee endpoints. One called: "home",
    the other called "version", and one called "private". Each point is located in it's own plugin
    which glue composes when the server starts up.
  • Ensure 100% test coverage.
  • Refactor project to meet new requirements outmoded/hapi-contrib#31.
  • Remove Makefile and switch to using npm scripts (see hapi package.json)
  • Remove root index.js (point package.json to lib/index.js)
  • Replace package.json licenses array with single license key and "BSD-3-Clause" value
  • Update code style to stop putting functions on single line (new lab will error on that lint warning)
  • An extra challenge, after doing the above, refactor hapi-auth-basic registration code:
    • Refactor the application to load hapi-auth-basic plugin using glue's manifest file.
    • Remove hapi-auth-basic plugin registration code from the private.js file.
    • private.js plugins' functionality will not change. We are just moving where the
      hapi-auth-basic plugin is registered.
    • Configure Glue to load hapi-auth-basic plugin and make a file dedicated to register the hapi-auth-basic strategy.
      Glue will reference this file in the manifest file to load the plugin.
    • While making the assignment, there was discussion about why not to make this change. See: The Discussion for details.
      But, I encourage everyone to try it. Doing this exercise will help you get to know Glue and hapijs' auth plugin design better ;-)
      If you get stuck here, we will work together to make it work!

Assignment Due May 30th

What is coming next?

  • adding static assets like css, images, js files.
  • validation with joi
  • sessions and authentication with hapi-auth-cookie
  • See "What we are going to build?" section in the README https://github.com/hapijs/university for the big picture plan.
  • If you have suggestions for issues to study please make them!
    Cheers!

new label 'community PR' ?

per @jd73 discussion #200:

If I have my own solution to an assignment that a PR already exists for and has good discussion in,
is it better for me to focus on discussing my ideas in my own PR or in the 'community' PR?

Think through 'communityPR' and explanation. Similar to early days of the university, the first labelling of a PR as 'assignment' signified most discussion related to the assignment occurred there and it would be refactored to be an example PR for the assignment. This would be a 'community PR'. Main comments and discussion for the assignment will occur there. Plus, the code is refactored to be a model for others to study in order to complete there assignments. More advanced developers may compete in order to have their PR accepted as the 'communityPR'.

@todo improve explanation of this ./guides/groupDevelopment.md.

Is everyone OK with the 'communityPR' concept? What are your thoughts?

Update assignment6

Update assignment6 branch to reflect the fulfillment of assignment6 using:

  • ES6 - must pass current hapi linting standards.
  • Uses current hapi plugins. (hapi v13 etc)

Chat forum and repo layout

Hi Eran
What do you think about enabling Gitter for the repo?

It's not Freenode but it does cater to new programmers in its simplicity. (Or is that just because GUI IRC clients have sucked for too long? Which certainly helped drive the uptake of Slack...)

Also. What are your preferences on the layout of the site to enable new people to start from Assignment 1?

Some of the most helpful notes are a couple of pages down a pull request or at the bottom of an Assignment thread. Link to them directly or embed them in the wiki?

And finally, thank you. I just want to let you know how valuable this has been for me.

It's really perfect as an intermediate step between JS fundamentals and the typical advice to just start building something.

This is the HOW to build something that I've always been missing.

Cheers

Proof read new university documentation

Have updated the university, see PR #200 for details about the update.
Would really appreciate some people to look over the new documentations relating to the university
and give feedback / proof read it. The documents most needing attention are:

  • README.md
  • ./guides/contents.md
  • ./guides/getstarted.md
  • ./guides/groupDevelopment.md
  • ./assignments/*
    The links in the contents should all link to the assignments.

Ideally, just start at the README and follow the flow of documentations logic
and give feedback where things are unclear etc.

Don't be bashful if you are new to hapi. Perhaps your perspective is most needed.

Any way to do previous assignments?

I have missed the last two assignments. I can see them in the issues, but is there a way for me to clone the repo in the state it was in for the assignment? Or do I just need to join in on the current assignment?

Static Assets, Partials, and TLS

Static Assets, Partials, and TLS

Configure the application to use TLS/SSL

  • Generate your own TLS/SSL certificate
  • Make "certs" directory in ./lib.
  • Place the certificates you generate into "certs" directory.

Configure two server connections

  • One labelled ['web'] on port 8000 with no TLS configured.
  • The other labelled ['web-tls'] on port 8001 will use TLS.
    Configure this connection to use the ssl certificates you just generated
    and placed in ./lib/certs
    • Example server certificate configuration at npm newww

Use TLS everywhere

Configure the application to always use TLS Transport Layer Security.
Every http request should be redirected to https.
Two references:

Configure the home plugin.

  • Make a new point in the home plugin called: "login"
    • Make login route display view template named login.html.
  • Use partials to display the login form
    • make a directory inside of the ./views called partials
    • configure the home plugin to use the ./views/partials directory to load partials from.
      • In ./views/partials/ directory make a file named form.html.
        • form should have two inputs one type="text" named "username" and the second type="password" named "password".
        • form should have one submission button with text value "Login".
      • Inside login.html template load the partial file named "form.html"

Use Static Assets

  • Make directory in root of project called "assets".
  • Inside the assets directory, make three directories:
    "styles" for css,
    "scripts" for JS scripts,
    "images" for project images.
    • Place Hapi University logo into the images directory
      and display it on the home page (home.html).
      (image is in the repo ./images/logo.png)
    • Place a CSS file in the stylesheets directory (styles).
      Name css file styles.css:
      • Make one simple style:
        h3 { font-size: 24px; font-weight: bold; }
      • Use the stylesheet in home.html. Make a title inside h3 tags.
    • Make a script named login.js and put in ./assets/scripts
      • Make this script print a console message to the browser when the form button is clicked.
    • In the home plugin configure the application to serve these static assets.
    • Make a login link in home.html that links to the login route.

100% test coverage required

Exended Due Date is June 12, 2015

Original due date was June 6, 2015.

Next After This Assignment

  • Make POST request from our form.
  • Validate the post request with Joi.
  • Use hapi-auth-cookie to start session.
  • Successful login goes to restricted access page.
  • Error handling of login failure

Travis build error and npm install failure

After uploading edits to master.
Travis did not pass tests.

The command "eval npm install " failed 3 times.
The command "npm install " failed and exited with 1 during .
Your build has been stopped.

Based on error messages it looks like npm fails to install with iojs.
Looks like iojs is having issues. node.js tests pass.

Convert to a plugin

The right way to work with hapi is to build your application using plugins. Plugins provide a way to organize your code into logical components and then put them together in different combinations or deploy them in different configurations. While some plugins are published as general purpose utilities (e.g. adding authentication), you should think of plugins as a way to break your code into pieces.

Now that we have a basic server with one endpoint, we want to move the creation of the endpoint to a plugin, and then register that plugin with the server. Creating a new file lib/version.js and move the /version endpoint there, wrapped in the plugin register() function.

Then change our current lib/index.js to require the new file and register the version plugin with our server.

Remember to follow the style guide, and ask any questions right here in the comments. If you are not sure how to get your fork back in sync with the current updated code, use the git guide.

Assignment due: 3/24

Re-write the university

Time to re-write the university

2016 has arrived and Node and hapijs have rapidly progressed and the university has become outdated. So, plan to re-write the university.

  • node is v4.3.0 LTS but the university was written when it was v12.
    Nodejs LTS schedule here
  • hapi is at v13 but the university was written using v8.
  • nodejs now supports ECMAScript 2015 (ES6). However, the university has no es6 code in it
    and it would not pass current hapi linting standards.
    • Syntactic sugar which hapi's linting enforces
      • shorthand:
        • () => {} versus function () {}
        • { objectKeys }
      • let and const for performance.
    • See this for more details.

In next version would like to:

  • keep most original assignments.
  • definitely want to add:
    • cors
    • db support
  • considering the addition of:
    • hawk
      with long term goal of using hawk to prepare to do something with OZ.
    • nes - would also like to fit hapiness into the project.
    • a hapi proxy server
  • remove
    • hapi-auth-basic
      Seems most people would be interested in using hapi-auth-cookie or hapi-auth-hawk.
  • rewrite assignments
  • rewrite guides

multiple university repos

In the future, would like the university to have two or three repos named:

  • university:
    • serve traditional web pages.
    • home to web api serving data to various clients: university web pages and university-client.
  • university-client:
    • SPA application or hybrid spa application running on a hapi server.
    • consumes the university api making cors requests.
    • Additionally, would like to use request to consume the university api in the client repository.
      • this mean university-client would consume our api through two methods: one, as a web page
        making CORS requests. The other would be the server using the request library to make requests from the api similar to how someone would use curl to make http requests.
  • (possibly) university-proxy
    Illustrate how to use hapi as a proxy server for an api.

Feedback welcomed :-)

Discrepancies in registering plugins

In /lib/start.js, our manifest sets us up and we register Inert and Vision.

In /lib/home.js, we set server dependencies for Inert and Vision. We wait for them before setting up the home plugin.

However, in /lib/lout.js, we re-register Inert and Vision along with the 'Lout' plugin.

Why does /lib/home.js not register the plugins instead? Why is there a difference between //lib/home.js and /lib/lout.js?

Error: Request interface decoration already defined: cookieAuth

I have followed the Assignments successfully (updating the code to use latest versions) until the one with hapi-auth-cookie. I cannot make it work, because when I start the server (npm start), this error appears:

node lib/start.js

/Users/Miguel/Sites/git/Miguel-Herrero/university/node_modules/hapi/node_modules/hoek/lib/index.js:732
    throw new Error(msgs.join(' ') || 'Unknown error');
    ^

Error: Request interface decoration already defined: cookieAuth
    at Object.exports.contain.exports.reachTemplate.exports.assert.condition [as assert] (/Users/Miguel/Sites/git/Miguel-Herrero/university/node_modules/hapi/node_modules/hoek/lib/index.js:732:11)
    at internals.Generator.decorate (/Users/Miguel/Sites/git/Miguel-Herrero/university/node_modules/hapi/lib/request.js:54:10)
    at module.exports.internals.Plugin.internals.Plugin.register.internals.Plugin.decorate (/Users/Miguel/Sites/git/Miguel-Herrero/university/node_modules/hapi/lib/plugin.js:365:37)
    at Object.internals.implementation.server.ext [as cookie] (/Users/Miguel/Sites/git/Miguel-Herrero/university/node_modules/hapi-auth-cookie/lib/index.js:125:12)
    at internals.Auth.strategy (/Users/Miguel/Sites/git/Miguel-Herrero/university/node_modules/hapi/lib/auth.js:51:43)
    at module.exports.internals.Plugin.internals.Plugin.register.internals.Plugin._applyChild (/Users/Miguel/Sites/git/Miguel-Herrero/university/node_modules/hapi/lib/plugin.js:587:19)
    at Object.auth.default.scheme.strategy (/Users/Miguel/Sites/git/Miguel-Herrero/university/node_modules/hapi/lib/plugin.js:72:18)
    at /Users/Miguel/Sites/git/Miguel-Herrero/university/lib/auth-cookie.js:31:21
    at /Users/Miguel/Sites/git/Miguel-Herrero/university/node_modules/hapi/lib/server.js:357:18
    at iterate (/Users/Miguel/Sites/git/Miguel-Herrero/university/node_modules/hapi/node_modules/items/lib/index.js:36:13)
    at Object.exports.serial (/Users/Miguel/Sites/git/Miguel-Herrero/university/node_modules/hapi/node_modules/items/lib/index.js:39:9)
    at internals.Server.start.internals.Server.initialize.internals.Server._start.internals.Server.stop._invoke.internals.Server._invoke.next [as _invoke] (/Users/Miguel/Sites/git/Miguel-Herrero/university/node_modules/hapi/lib/server.js:354:11)
    at /Users/Miguel/Sites/git/Miguel-Herrero/university/node_modules/hapi/lib/server.js:236:14
    at done (/Users/Miguel/Sites/git/Miguel-Herrero/university/node_modules/hapi/node_modules/items/lib/index.js:63:25)
    at /Users/Miguel/Sites/git/Miguel-Herrero/university/node_modules/hapi/node_modules/hoek/lib/index.js:850:22
    at nextTickCallbackWith0Args (node.js:452:9)

Theoretically I know what it means, but I don't know where I am redecorating the cookieAuth in my code.

I would be very thankful if anybody could review my fork and give me some advice as to where to look…
Thank you in advance.

(Note: previous assignment successfully passed tests with 100 % coverage)

request lifecycle term: "application level extension"

Currently, writing a lesson for hapi university.
The lesson is about the request lifecycle, hooks, and events. We are changing an extension that was "application level extension" to be a "request level" extension.

There are three types of request lifecycle extensions:

When extensions apply to all requests received by the server should we call them "application level" or "server level". Matt Harrison used the term "request level extension" so I want to call them "server level extensions" or "application level extensions". However, I think "server level extensions" is to close to server extension points: function(server, next).
So, I am going to call them "application level extensions"

Is everyone ok with that?

Potential [Assignment 5] Glue and HTML views

@hueniverse and community, below is a potential assignment to keep the project moving.
@hueniverse Hopefully, you will find this acceptable. Your feedback would be appreciated.
This should build off previous assignments and move us one step forward to master the learning objectives described at: https://github.com/zoe-1/hapitimes.

Community your feedback would be appreciated too.

[Assignment 5] Glue and HTML views

  • Refactor the application to use the hapijs server composer hapijs / glue.
    Glue should be used to load all plugins.

    Note about hapi-auth-basic:
  • Refactor the application to load hapi-auth-basic plugin using glue's manifest file.
  • Remove hapi-auth-basic plugin registration code from the private.js file.
  • private.js plugins' functionality will not change. We are just moving where the
    hapi-auth-basic plugin is registered.
  • Place hapi-auth-basic plugin registration code in it's own file dedicated to registering the plugin.
    Glue will reference this file in the manifest file to load the plugin.
  • Create a plugin called "home".
  • This plugin should have one endpoint called "home".
  • Configure the plugin to use handlebars template rendering engine to render html templates.
  • Configure this plugin to serve html view files and make the home endpoint render an html page/template.
  • Configure the home plugin to find view files in a directory named "views" located in
    the root path of the application. For now, just make html pages for view files (no .hbs files).
  • In the end, the application should have thee endpoints. One called: "home",
    the other called "version", and one called "private". Each point is located in it's own plugin
    which glue composes when the server starts up.
  • Ensure 100% test coverage.
Hints:
  • The Glue project on github has a sample manifest file.

    Sample Manifest JSON object
  • Everything in node.js that loads with require() is a singleton object.
  • Get Glue configured and working before adding the new "home" plugin to the project.

Due Date: May 28th 2015.

Moveing to hapijs

I moved the project to the hapijs organization, renamed it university and added Zoe as maintainer. I'll let him take it on from here.

@zoe-1 you might want to add a full name to your profile and to the Readme as I find it makes it easier for people to engage and relate to others.

Go ahead and get another assignment going...!

university-data

preparing to add a database into university project.

sample user couchdb queries ready.
To see the work do the following:

  • git clone https://github.com/sofajs/sample or go to sample.

  • cd sample

  • npm install

  • install couchdb

  • configure sample/lib/sofafest.js to your couchdb admin credentials.

    • db: 'your-db-name'
    • user: 'your-couchdb-username'
    • pw: 'your-pw'
  • npm run load

    • run above command twice. once to create db. next, loads fixtures.
    • after db is created only run once.
  • npm test

    • currently 100% test coverage.
  • read documentation on all couchdb request logic.

    • npm run docos starts documentation server.
    • visit localhost:9000 and read the docs.

    feedback appreciate :-)

Parallel test execution

Shouldn't the parallel option set here be false? Lab's default for parallel execution seems to be false but I think the point was to explicitly mark this one as basically not safe for parallel execution if we change the default for the tests to parallel in the future.

As noted here:

When monkey patching code in a test, mark that test with the { parallel: false } lab option to make it both safe for future parallel testing as well as visual cue.

potential Assignment6

Potential Road Map for Next Assignment.
Please share your thoughts.

Static Assets, Partials, and TLS

Configure the application to use TLS/SSL
  • Generate your own TLS/SSL certificate
  • Make "certs" directory in ./lib.
  • Place the certicate you generate into "certs" directory.
Configure two server connections
  • One labelled ['web'] on port 8000 with no TLS configured.
  • The other labelled ['web-tls'] on port 8001 will use TLS.
    Configure this connection to use the certificates you just generated
    and placed in ./lib/certs
Configure the home plugin to work with both connections 'web', 'web-tls' connections
  • Make a new point in the home plugin called: "login"
    • Make login route display view template named login.html.
  • Use partials to display the login form
    • make a directory inside of the ./views called partials
    • configure the home plugin to use the ./views/partials directory to load partials from.
      • In ./views/partials/ directory make a file named form.html.
        • form should have two inputs one type="text" named "username" and the second type="password" named "password".
        • form should have one submission button with text value "Login".
      • Inside login.html template use load the partial file named "form.html"
Utilize the static assets.
  • Make directory in root of project called "assets".
  • Inside the assets directory, make three directories:
    "styles" for css,
    "scripts" for JS scripts,
    "images" for project images.
    • Place Hapi University logo into the images directory
      and display it on the home page (home.html).
      (image is in the repo ./images/logo.png)
    • Place a CSS file in the stylesheets directory (styles).
      Name css file styles.css:
      • Make one simple style:
        h3 { font-size: 24px; font-weight: bold; }
      • Use the stylesheet in home.html. Make a title inside h3 tags.
    • Make a script named login.js and put in ./assets/scripts
      • Make this script print a console message to the browser when the form button is clicked.
    • In the home plugin configure the application to serve these static assets.
100% test coverage
Issues to discuss
  • Does the community want to enforce every route to utilize tls.
    This seems to have become the standard since this happened:
    Largest DDOS attack in history
  • Do you have a issues to discuss? Please share it.

Next After This Assignment

  • Make POST request from our form.
  • Validate the post request with Joi.
  • Use hapi-auth-cookie to start session.
  • Successful login goes to restricted access page.
  • Error handling of login failure

Note: I really enjoy distributed learning in hapi university. It is a great way to learn. Plus, I consider it a privilege to maintain this project. However, I see many people stopped participating in the university during the last assignment when I began to maintain it. So, if the community finds a better maintainer I would be willing to stop. Whatever is best for the community is what I want to do! Otherwise, I will keep writing assignments and maintaining the project.

100% coverage

Things are getting a bit more interesting...

It's time to add tests, verify coverage, confirm style, and automate all of this with CI. We will be using the lab module to perform all these tasks and automate it with travis.

  1. Add a .travis.yml file, testing our project on node 0.10, 0.12, and io.js (latest).
  2. Add a test folder with two files, version.js and index.js, each testing the corresponding file under /lib.
  3. Modify the package.json file to include the tests, as well as the dev dependency to lab.
  4. Add the standard hapi.js Makefile to make it easy to generate other types of reports (e.g. HTML coverage report). Note: From Assignments5 on this project only uses npm. Between assignments 4 and 5, style rules changed and the Makefile was removed from hapijs projects.
  5. When using lab, enable coverage, require 100% coverage, enable linting with default rules, and use the code assertion library.
  6. Write a basic test to verify our version endpoint in version.js.
  7. Change the init() method to accept a port and a callback. Use the callback to return when the function completes or errors. The init() callback should return any error state as well as a reference to the newly created server. This will allow us to later stop the server when we test it.
  8. Export init() and move the invocation to a new start.js file (which will call the init() function with the 8000 port and a callback the outputs the information to the console when started). Change the package.json file to use the start.js file as the starting place. This file will not be covered by tests.
  9. Write a basic test to verify the init() function in index.js.
  10. Bring coverage to 100% by adding more tests as needed.

Everything up to (10) should be pretty straight forward. If you are not sure on how to use lab and code, look at other hapi.js modules like hoek, qs, items, and boom (e.g. simple modules) to copy their test scripts and setup.

Getting 100% coverage can be tricky sometimes so if you are not sure, get as much coverage as you can, and comment on the lines in your pull request where you are having a hard time reaching and someone will give you a clue.

Remember to properly stop() your servers when calling the init() method in each test.

For now, avoid using any of the before() and after() lab features.

As always, ask for help and help others!

Due: 4/4

ES6 integration?

I'm curious about the conversation around es6 and if we should integrate that into this "tutorial". I understand that the main goal is to learn Hapi but still very interested in a workflow that allows for ES6 either through io.js or a node.js equivalent approach.

update assignment8

Update assignment8 branch fulfill assignment8 requirements using:

  • ES6 - must pass current hapi linting standards.
  • current hapi plugins. (hapi v13 etc)
  • update all dependencies to latest.

potential Assignment7

Below is an overview of assignment7.
Please look it over and give your feed back! Feel free to make suggestions.
After finalizing the general objectives described here, Assignment7 will be written.


## Validation, Authentication, and Authorization

Configure the application to use hapi-auth-cookie for cookie-based session management.
Every route will be black listed requiring authentication and authorization globally.
Routes that do not require authenticated users and have no permissions restrictions will be white listed so anyone can access them. Additionally, the application will utilize two user roles for authorization which are:

  • "admin" the super user
  • and "user" basic user

There will be three types of authorization restrictions:

  • "public" routes open to all
  • "user" routes restricted to authenticated users with the role of "user" or "admin".
  • "admin" routes restricted to authenticated users with the role "admin".

Login Process

Create a login in page that utilizes AJAX to login. This route (/login) is open to the public. If the login AJAX POST request is successful, the login form will disappear and the user will be presented with links to access restricted content /account or /logout. At this stage the login process is complete, session cookies are set, and authorized users can begin to access restricted content. If the login AJAX request fails, an error message is displayed along with the login form.

Restricted Access Content

The /account route

After a successful login, user sees "My Account" link and "Logout" link.
The "My Account" link goes to the /account route which is restricted to authenticated users with roles of "user" or "admin". The /account route will display a welcome message with the user name in it and displays the following links: "Logout", "Home", and "Admin Panel" (if user has admin privileges).
Correspondingly, the previous mentioned links point to /logout, /home, and /admin.

The /admin route

The /admin route should display an admin welcome message with user's username displayed.
Plus, there should be three links: "My Account", "Logout" , "Home".
Only users with the role of "admin" should be able to access /admin route.

The /home route

If a logged in user goes to /home, "My Account" and "Logout" links are displayed along with the
hapi university image. When a user clicks on "My Account" link they are taken to the /account route described above.

Logging Out

On /home, /account, and /admin routes there should be a logout button which links to /logout and destroys the session. Plus, the /login POST route should have a Logout link displayed after the AJAX requests successfully completes.

Technical Details:

Configure Application to Use hapi-auth-cookie

  • Make plugin: ./lib/auth-cookie.js which:
    • Configures hapi-auth-cookie authentication strategy to project.
    • redirects to '/login' route if the user is not logged in.
    • Requires the use of tls.
    • Apply this auth strategy to every route in the application.
      White list the routes that do not require authentication or authorization.
    • When creating the session cookie with hapi-auth-cookie do not put sensitive
      user account data (i.e. passwords) in the session cookie. Before creating a session, use Hoek to clone the account data JSON object then delete passwords from the newly cloned object. Once secure data is removed create the user's session with: request.auth.session.set(account).
  • Use scopes to control which authenticated users are
    authorized to use the specific routes. First steps toward RBAC.
  • Configure restricted routes to redirect to the /home, if the user
    is not authenticated or authorized to view the page.
  • When handling /login POST requests use poeticninja 's style of using
    a JavaScript Promise to authenticate users.
    • Use boom to return authentication errors.
  • Add bad route handling to project.
    Configure a server.ext('onPostHandler') to redirect to /home when routes
    do not exist. {"statusCode":404,"error":"Not Found"}
  • joi validation
    All POST request payloads must be validated by joi.
  • Last but not least, 100% test coverage required

    Questions:

    • Would moving the manifest JSON object to an external file
      complicate things too much? Would like to move the manifest jSON object
      into it's own file, but, concerned it may confuse people.
    • What about adding a HTML form submission requirement in addition to AJAX.
      Make two login routes one would be AJAX the other would be a traditional
      POST from an html form. Then, we could use server.ext(onPostHandler) to catch
      validation errors.

helps for Assignment 7

Assignment7 will cover the important subjects: form submissions, validation, authentication, and authorization. To prepare, work through the below resources:

Knowledge of the above resources will help greatly with the next assignment.
I plan to post a proposal for assignment7 today or tomorrow.
Assignment7 should be posted on Friday June 12 or Saturday June 13th.

Hapi Coding!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.