-
Notifications
You must be signed in to change notification settings - Fork 85
Description
Problem
#788 defines a UserController action which calls CodeCorps.Github.connect/2.
This function should do the following:
Handle the auth token part of the web application flow for github authentication.
The first step is to make a post request to github to get the token. There is the https://github.com/edgurgel/tentacat API wrapper for elixir, which we will very likely end up using.
However, this wrapper has no "friendly" endpoint to just generate a token using a code. Instead, we'd have to use a POST request created manually, something like:
post(@token_url, %{
client_id: @client_id,
client_secret: @client_secret,
code: code,
accept: :json
})The code would be provided as a function argument, while all the other parameters are set in the environment.
This call will return an {:ok, response_struct} or an {:error, error_struct}. We should handle the response and have the private function making the call return the access token. We should also handle a generalized error response by returning a general {:error, error_struct}. We can expand this to handle specific errors at a later time, in separate tasks.
Retrieve a GitHub user
We can use the auth_token to generate a Tentakit.Client and use this client to retrieve user information. We need a github id for the user, in order to associate it with our own user account.
Associate GitHub user with current user
This is blocked until #791 is done. To work on the remainder of this PR, use a virtual github_id field on the User model and simply have the GitHub.associate function set that field on the user struct.
We associate the github user information provided in the previous step with the github user in this step.
Return the updated current user
The previous step should give us an updated CodeCorps.User struct freshly retrieved from the database. We should return this as {:ok, user} from the service.
Testing
Since this will be making web requests to the github API, we should mock the API. We can use dependency injection to do this, or if that seems to complicated, we can fall back to using VCR. Someone will be available to help with this once a partial PR is submitted. The core team is still figuring this thing out just as everyone else, so no need to be apprehensive about asking for help here, or anywhere else.
There are examples of us already using dependency injection in how we use stripity_stripe, for example.
Recap
- service receives
current_user, code - posts code to github
- retrieves github user info from github
- associates github user info with current user
- returns
{:ok, updated_current_user} - if there was an error with github, returns
{:error, "Something went wrong."} - if there was an error with associating the current user, returns
{:error, changeset}
Subtasks
- write service
- write test for correct output on successful scenario
- write test for correct output if github fails on posting
- write test for correct output if github fails on retrieving user
- write test for correct output on db update failure
References
Partially blocked by #791, but can be worked on.