moredip/todo-backend — pull request #5 by dtao (2014-08-06 17:07:53+00:00)
Title: Optional features starting with auth

So, this is pretty dense—I apologize for that. If I were a better citizen I probably would have figured out a way to break this into smaller chunks... but here we are! I'll try to quickly summarize everything in this PR.

Consider this nothing more than a first crack. I'm OK with you saying all of this is totally wrong, or not the way you'd want it to work. But at least it's a starting point for that conversation.

# The main entry form

First, it adds an "Optional features" section to the main form, with a checkbox for authentication (with more optional features presumably to follow):

![form with optional features](https://cloud.githubusercontent.com/assets/409328/3830341/4fb110da-1d89-11e4-8821-580cd227c5ea.png)

If the checkbox is checked, auth-specific specs are loaded along with the standard todo ones. In order to share logic (`get`, `post`, `postJson`, etc.) between the existing specs and the new ones, I've pulled those into a separate file which exposes a `createAPI` method to create an api object, and that object (rather than just the endpoint) is passed into each spec-generation method (the new one is called `defineAuthSpecsFor`).

# The auth specs

The way I've implemented it now assumes your API exposes the following endpoints:

/register
required params: name, password, passwordConfirmation
returns: 200 response
/login
required params: name, password
returns: token

(Ideally this would be configurable. At the moment they're hardcoded.)

After receiving a token from the `/login` endpoint, all additional specs must pass that along in the URL with each request. The object provided by `createAPI` handles this automatically.

# Points of uncertainty

1. I'm not sure about this auth spec. I've never really implemented token-based authentication before, but it feels like that's inevitable since we're defining a CORS-based API here.
2. I'm also not sure how registration should be tested. As you can see from looking at the spec, it actually just creates a user with a random 10-character name for every run (but since this allows for over a hundred trillion possibilities, maybe the extremely low collision probability is acceptable?).
3. For ease of local testing, the specs don't verify that authenticated requests are made over HTTPS; but they probably should.
4. The specs also currently don't actually verify that auth is necessary to get/create/update todos, or that different users have different todo lists. They obviously *should*, but for now I didn't want to make any modifications to the todo specs themselves.
5. I'm not sure how the API endpoints should actually be defined in this scenario. In the case of *just* todos, everything can be defined relative to the "todo root"; but with unrelated functionality like auth in there, it seems multiple roots need to be defined.

On that last point, I'm thinking there are at least three options:

1. Each root has to be supplied as part of the main entry form. I.e., instead of just one URL for todos, you'd need to specify one for todos and one for auth. That seems pretty crappy.
2. You still just declare one root, and then the spec itself declares where todos and auth should be relative to that. E.g., you supply http://example.com, and according to the spec the auth endpoints should be at http://example.com/auth and the todos should be at http://example.com/todos.
3. The API itself exposes what its endpoints are. So, e.g., you specify http://example.com and then the specs hit that root and get something back like `{"auth":"/users","todos":"/todos"}`.

Thoughts?