Objective: Implement Angular authentication with Satellizer. Your goal is to have working sign up and log in functionality.
You should be pair programming the entire time you work on these challenges. That means you're using ONE computer at a time, and ONLY the "driver" is allowed to type (you'll switch roles throughout the lab).
-
Whoever is going to be the "driver" first should fork this repo, and clone it into their
developfolder on their local machine. The "navigator" must close their computer. -
Once you're in your app directory, run
npm installto install the requirednode_modules. -
In one Terminal window, run
mongod, and in another, runnodemon. -
Navigate to
localhost:9000in the browser. You should see an empty page and an angry red error message in the Chrome console. -
BEFORE WRITING ANY CODE, open up
models/user.js,resources/auth.js, andserver.js. The driver should go through these files in order and explain what you think each code block and/or function does. -
Now it's the navigator's turn to explain code! Open up
index.hbsandapp.js, and go through the same exercise. -
Next, the driver should add a "dot" file, called
.envto the root directory. Add this line to the file:
TOKEN_SECRET=yoursupersecrettoken
This is the secret your server will use to encode the JWT token for each user.
- Before hooking up the front-end, test your server routes via Postman:
- Send a
GETrequest to/api/me. You should see the message: "Please make sure your request has an Authorization header." - Send a
POSTrequest to/auth/signupwith a testemailandpassword. You should see a token that was generated by the server. (You are simulating a form submission, so make sure to usex-www-form-urlencodedand send your data in thebodyof the request). - Send a
POSTrequest to/auth/loginwith theemailandpasswordyou just used to create a new user. You should again see a token that was generated by the server.
At this point, the "driver" should add the "navigator" as a collaborator on their forked version of the repo. No need to commit anything yet, since you haven't written any code. It's time to switch drivers! The new driver should clone their partner's forked version of the repo into their develop folder. The new navigator must close their computer.
-
Re-add the
.envfile. The.envfile contains secret keys and tokens, that's why we.gitignoreit! We don't ever want our application secrets exposed on github, so you have to setup the file on each machine! -
Now it's time to implement authentication from the client. First, you need to include Satellizer in your Angular app:
- Add the Satellizer CDN to
index.hbs(TODO #1). - Add the Satellizer module to your Angular app in
app.js(TODO #2). - Check that you can navigate between your routes (
/,/signup,/login, and/profile).
-
Follow the instructions to finish implementing
Account.login()(TODO #3, #4, #5). -
Click the "Log Out" link to logout (TODO #6) and make sure it redirects to
/login(TODO #7).Todo #6 Spoiler:
```js return ( $auth .logout() // delete token https://github.com/sahat/satellizer#authlogout .then(function() { self.user = null; }) ) ``` -
The current driver should add and commit their changes, and push their work up to GitHub. Switch drivers.
-
The new driver should pick up where their partner left off by implementing the functionality outlined in
Account.signup()(TODO #8, #9, #10). -
At this point, you should be able to sign up a user, log them in, and view their profile page from the client.
-
It's time to switch drivers again! The current driver should add, commit, and push, and the new driver should pull down the changes.
-
Add a
usernamefield to the Sign Up form, and add theusernameattribute toUsermodel (server-side). Sign up a new user with ausername(TODO #11, #12). -
On the user profile page, make a form to edit the user's details. The form should initially be hidden, and when the user clicks a button or link to "Edit Profile", the form should show (Hint:
ng-show) (TODO #13). -
When the user submits the form, it should call a function in the
ProfileCtrl(Hint:ng-submit). The function should send an$http.putrequest to/api/me. Verify that this works. (TODO #14) -
Bonus: Decouple the edit form from the user's other details. For instance, when I type into the edit form it shouldn't instantly change my email or my username, but it should still change those values on (a successful) submit!
No more TODOs! You're on your own from here on out!
-
Switch drivers - you know the drill - add, commit, and push, then the new driver should pull.
-
Create a form on the homepage for the user to add a blog-post (that's right - you're turning your Angular app into a microblog). The blog-post form should have input (
title) and textarea (content) fields. Hint: Useng-model. -
Only show the form if there is a
currentUserlogged in. -
Use the
ng-submitdirective to run a function calledcreatePostwhen the user submits the form. -
createPostshould make an$http.postrequest to/api/posts(which isn't defined on the server yet!) with thevm.postobject. -
The next step is to implement posts on the server. First, create a Mongoose model
Post(models/post.js). -
A user should have many posts, so add an attribute to the
Usermodel calledpoststhat references thePostmodel:
/*
* models/user.js
*/
var userSchema = new Schema({
...
posts: [{ type: Schema.Types.ObjectId, ref: 'Post' }]
});- In
server.js, define two new API routes:
GET /api/postsshould retrieve all the posts from the database.POST /api/postsshould create a new post that belongs to the current user (Hint: Use theauth.ensureAuthenticatedfunction in the route to find the current user).
- Refresh
localhost:3000in the browser. Make sure you have a user logged in, and try to create a new post. Check the Chrome developer tools to make sure it's working.
Switch drivers one last time:
-
Validate blog-posts! Ensure a user can't submit an empty title or content. (Use both backend AND frontend validations).
-
On the user's profile page, display the number of posts the user has written. Hint: You'll need to add
.populate('posts')to yourGET /api/meroute inserver.js. -
On the user profile page, the "Joined" date isn't formatted very nicely. Use Angular's built-in date filter to display the date in this format:
January 25, 2016.
