Skip to content

Commit

Permalink
Added Github connect implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
snewcomer authored and begedin committed May 26, 2017
1 parent 11b8f2e commit 2c78d03
Show file tree
Hide file tree
Showing 20 changed files with 318 additions and 143 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
34 changes: 30 additions & 4 deletions lib/code_corps/github.ex
Original file line number Diff line number Diff line change
@@ -1,15 +1,41 @@
defmodule CodeCorps.Github do

alias CodeCorps.{User, Repo}

@api Application.get_env(:code_corps, :github_api)

@doc """
Temporary function until the actual behavior is implemented.
Posts code to github to receive an auth token, associates user with that
auth token.
Accepts a third parameter, which is a custom API module, for the purposes of
explicit dependency injection during testing.
Returns one of the following:
- {:ok, %CodeCorps.User{}}
- {:error, %Ecto.Changeset{}}
- {:error, "some_github_error"}
"""
def connect(user, _code), do: {:ok, user}
@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
2 changes: 2 additions & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ defmodule CodeCorps.Mixfile do
:segment,
:sentry,
:stripity_stripe,
:tentacat,
:timber,
:timex_ecto
]
Expand Down Expand Up @@ -96,6 +97,7 @@ defmodule CodeCorps.Mixfile do
{:sentry, "~> 2.0"}, # Sentry error tracking
{:stripity_stripe, git: "https://github.com/code-corps/stripity_stripe.git", branch: "2.0"}, # Stripe
{:sweet_xml, "~> 0.5"},
{:tentacat, "~> 0.5"},
{:timber, "~> 0.4"}, # Logging
{:timex, "~> 3.0"},
{:timex_ecto, "~> 3.0"},
Expand Down
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], []},
"stripity_stripe": {:git, "https://github.com/code-corps/stripity_stripe.git", "1e9b87d73710ef901dd6d735d6f2d0a2cef75d1c", [branch: "2.0"]},
"sweet_xml": {:hex, :sweet_xml, "0.6.5", "dd9cde443212b505d1b5f9758feb2000e66a14d3c449f04c572f3048c66e6697", [:mix], []},
"tentacat": {:hex, :tentacat, "0.6.2", "e5e5ad95d577dd441e4dcfcab259c9d92b0049f0481a4be6453769d61a956a3b", [:mix], [{:exjsx, "~> 3.2", [hex: :exjsx, optional: false]}, {:httpoison, "~> 0.8", [hex: :httpoison, optional: false]}]},
"timber": {:hex, :timber, "0.4.7", "df3fcd79bcb4eb4b53874d906ef5f3a212937b4bc7b7c5b244745202cc389443", [:mix], [{:ecto, "~> 2.0", [hex: :ecto, optional: true]}, {:phoenix, "~> 1.2", [hex: :phoenix, optional: true]}, {:plug, "~> 1.2", [hex: :plug, optional: true]}, {:poison, "~> 2.0 or ~> 3.0", [hex: :poison, optional: false]}]},
"timex": {:hex, :timex, "3.0.8", "71d5ebafcdc557c6c866cdc196c5054f587e7cd1118ad8937e2293d51fc85608", [:mix], [{:combine, "~> 0.7", [hex: :combine, optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5", [hex: :tzdata, optional: false]}]},
"timex_ecto": {:hex, :timex_ecto, "3.1.1", "37d54f6879d96a6789bb497296531cfb853631de78e152969d95cff03c1368dd", [:mix], [{:ecto, "~> 2.1.0", [hex: :ecto, optional: false]}, {:timex, "~> 3.0", [hex: :timex, optional: false]}]},
Expand Down
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

0 comments on commit 2c78d03

Please sign in to comment.