Skip to content

Commit

Permalink
Added tested API call for Github connect
Browse files Browse the repository at this point in the history
  • Loading branch information
begedin committed May 26, 2017
1 parent a8a0fb1 commit 0dc0c24
Show file tree
Hide file tree
Showing 18 changed files with 311 additions and 166 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export CLOUDEX_API_KEY=
export CLOUDEX_CLOUD_NAME=
export CLOUDEX_SECRET=
export CLOUDFRONT_DOMAIN=
export GITHUB_CLIENT_ID=
export GITHUB_CLIENT_SECRET=
export POSTMARK_API_KEY=
export S3_BUCKET=
export SEGMENT_WRITE_KEY=
Expand Down
6 changes: 6 additions & 0 deletions config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ config :guardian, Guardian,

config :code_corps, :analytics, CodeCorps.Analytics.InMemoryAPI

config :code_corps, :github_api, CodeCorps.Github.API

# Configures stripe for dev mode
config :code_corps, :stripe, Stripe
config :code_corps, :stripe_env, :dev
Expand All @@ -70,3 +72,7 @@ if System.get_env("CLOUDEX_API_KEY") == nil do
config :code_corps, :cloudex, CloudexTest
config :cloudex, api_key: "test_key", secret: "test_secret", cloud_name: "test_cloud_name"
end

config :code_corps,
github_client_id: System.get_env("GITHUB_CLIENT_ID"),
github_client_secret: System.get_env("GITHUB_CLIENT_SECRET")
4 changes: 4 additions & 0 deletions config/prod.exs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ config :code_corps,
postmark_project_acceptance_template: "1447041",
postmark_receipt_template: "1255222"

config :code_corps,
github_client_id: System.get_env("GITHUB_CLIENT_ID"),
github_client_secret: System.get_env("GITHUB_CLIENT_SECRET")

# ## SSL Support
#
# To get SSL working, you will need to add the `https` key
Expand Down
4 changes: 4 additions & 0 deletions config/remote-development.exs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ config :code_corps,
postmark_project_acceptance_template: "123",
postmark_receipt_template: "123"

config :code_corps,
github_client_id: System.get_env("GITHUB_CLIENT_ID"),
github_client_secret: System.get_env("GITHUB_CLIENT_SECRET")

# ## SSL Support
#
# To get SSL working, you will need to add the `https` key
Expand Down
4 changes: 4 additions & 0 deletions config/staging.exs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ config :code_corps,
postmark_project_acceptance_template: "1447022",
postmark_receipt_template: "1252361"

config :code_corps,
github_client_id: System.get_env("GITHUB_CLIENT_ID"),
github_client_secret: System.get_env("GITHUB_CLIENT_SECRET")

# ## SSL Support
#
# To get SSL working, you will need to add the `https` key
Expand Down
2 changes: 2 additions & 0 deletions config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ config :guardian, Guardian,

config :code_corps, :analytics, CodeCorps.Analytics.TestAPI

config :code_corps, :github_api, CodeCorps.Github.TestAPI

# Configures stripe for test mode
config :code_corps, :stripe, CodeCorps.StripeTesting
config :code_corps, :stripe_env, :test
Expand Down
53 changes: 26 additions & 27 deletions lib/code_corps/github.ex
Original file line number Diff line number Diff line change
@@ -1,42 +1,41 @@
defmodule CodeCorps.Github do

alias CodeCorps.{User, Repo}

@token_url ""
@client_id ""
@client_secret ""
@api Application.get_env(:code_corps, :github_api)

@doc """
Temporary function until the actual behavior is implemented.
"""
def connect(user, code) do
github_post(code)
|> Tentacat.Client.new
|> Tentacat.Users.me
|> update_user(user)
end
Posts code to github to receive an auth token, associates user with that
auth token.
defp update_user(%{github_id: _github_id} = github_info, user) do
associate(user, github_info)
end
Accepts a third parameter, which is a custom API module, for the purposes of
explicit dependency injection during testing.
Returns one of the following:
defp github_post(code) do
with {:ok, response_struct} <- Tentacat.post(@token_url, %{
client_id: @client_id,
client_secret: @client_secret,
code: code,
accept: :json
})
do
%{access_token: _access_token} = Tentacat.process_response(response_struct)
else
{:error, error_struct} -> error_struct
- {:ok, %CodeCorps.User{}}
- {:error, %Ecto.Changeset{}}
- {:error, "some_github_error"}
"""
@spec connect(User.t, String.t, module) :: {:ok, User.t} | {:error, String.t}
def connect(%User{} = user, code, api \\ @api) do
case code |> api.connect do
{:ok, github_auth_token} -> user |> associate(%{github_auth_token: github_auth_token})
{:error, error} -> {:error, error}
end
end

@doc """
Associates user with an auth token
Returns one of the following:
- {:ok, %CodeCorps.User{}}
- {:error, %Ecto.Changeset{}}
"""
@spec associate(User.t, map) :: {:ok, User.t} | {:error, Ecto.Changeset.t}
def associate(user, params) do
user
|> User.github_associate_changeset(params)
|> User.github_association_changeset(params)
|> Repo.update()
end
end
44 changes: 44 additions & 0 deletions lib/code_corps/github/api.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
defmodule CodeCorps.Github.API do
@moduledoc """
The boundary module which communicates with the Github API using either
direct requests, or through Tentacat
"""
@behaviour CodeCorps.Github.APIContract

@client_secret Application.get_env(:code_corps, :github_client_secret)
@client_id Application.get_env(:code_corps, :github_client_id)

@base_connect_params %{
client_id: @client_id,
client_secret: @client_secret
}

@doc """
Receives a code generated through the client-side github connect process and
posts it to github.
Returns either an {:ok, access_token}, or an {:error, error_message}.
"""
@spec connect(String.t) :: {:ok, String.t} | {:error, String.t}
def connect(code) do
with {:ok, %HTTPoison.Response{body: response}} <- code |> build_connect_params() |> do_connect(),
{:ok, %{"access_token" => access_token}} <- response |> Poison.decode
do
{:ok, access_token}
else
{:ok, %{"error" => error}} -> {:error, error}
end
end

@connect_url "https://github.com/login/oauth/access_token"

@spec do_connect(map) :: {:ok, HTTPoison.Response.t | HTTPoison.AsyncResponse.t} | {:error, HTTPoison.Error.t}
defp do_connect(params) do
HTTPoison.post(@connect_url, "", [{"Accept", "application/json"}], [params: params])
end

@spec build_connect_params(String.t) :: map
defp build_connect_params(code) do
@base_connect_params |> Map.put(:code, code)
end
end
17 changes: 17 additions & 0 deletions lib/code_corps/github/api_contract.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
defmodule CodeCorps.Github.APIContract do
@moduledoc """
Defines a contract for a github API module, listing all functions the module
should implement.
This contract should be specified as behaviour for the default `Github.API`
module, as well as any custom module we inject in tests.
"""

@doc """
Receives a code string, created in the client part of the github connect process,
returns either an :ok tupple indicating a successful connect process, where
the second element is the auth token string, or an :error tuple, where the
second element is an error message, or a struct
"""
@callback connect(code :: String.t) :: {:ok, auth_token :: String.t} | {:error, error :: String.t}
end
13 changes: 13 additions & 0 deletions lib/code_corps/github/test_api.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
defmodule CodeCorps.Github.TestAPI do
@moduledoc """
The most basic implementation of an API module for testing. All functions
here should return successes.
If we want to test the wrapper module, we can specify custom API modules
during function calls.
"""
@behaviour CodeCorps.Github.APIContract

@spec connect(String.t) :: {:ok, String.t}
def connect(code), do: send(self(), {:ok, code})
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule CodeCorps.Repo.Migrations.AddGithubAuthTokenToUsers do
use Ecto.Migration

def change do
alter table(:users) do
add :github_auth_token, :string
end
end
end
Loading

0 comments on commit 0dc0c24

Please sign in to comment.