Skip to content

Add CodeCorps.Github module with connect/2 function #789

@begedin

Description

@begedin

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.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions