Skip to content

Commit

Permalink
Start playing around with setting up a public v1 API
Browse files Browse the repository at this point in the history
  • Loading branch information
reichert621 committed Nov 23, 2020
1 parent 3f1ac11 commit 0dbcd86
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 0 deletions.
6 changes: 6 additions & 0 deletions lib/chat_api/users.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ defmodule ChatApi.Users do
User |> where(password_reset_token: ^token) |> Repo.one()
end

@spec find_by_api_key(binary()) :: User.t() | nil
def find_by_api_key(_api_key) do
# TODO: implement me!
nil
end

@spec send_password_reset_email(User.t()) ::
ChatApi.Emails.deliver_result() | {:error, Ecto.Changeset.t()}
def send_password_reset_email(user) do
Expand Down
1 change: 1 addition & 0 deletions lib/chat_api_web/api_auth_plug.ex
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ defmodule ChatApiWeb.APIAuthPlug do
defp signing_salt(), do: Atom.to_string(__MODULE__)

defp fetch_auth_token(conn, config) do
# TODO: if token isn't verified, check personal API keys?
with [token | _rest] <- Conn.get_req_header(conn, "authorization"),
{:ok, token} <- Plug.verify_token(conn, signing_salt(), token, config) do
token
Expand Down
85 changes: 85 additions & 0 deletions lib/chat_api_web/public_api_auth_plug.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
defmodule ChatApiWeb.PublicAPIAuthPlug do
@moduledoc false
use Pow.Plug.Base

alias Plug.Conn
alias Pow.{Config, Store.CredentialsCache}

@impl true
@spec fetch(Conn.t(), Config.t()) :: {Conn.t(), map() | nil}
def fetch(conn, config) do
conn
|> fetch_auth_token(config)
|> fetch_user(conn, config)
end

defp fetch_user(nil, conn, _config), do: {conn, nil}

defp fetch_user(token, conn, config) do
case fetch_from_store(token, config) do
nil -> fetch_and_cache_user(token, conn, config)
user -> {conn, user}
end
end

defp fetch_and_cache_user(token, conn, config) do
case ChatApi.Users.find_by_api_key(token) do
nil ->
{conn, nil}

user ->
config
|> store_config()
|> CredentialsCache.put(token, {user, []})

{conn, user}
end
end

defp fetch_from_store(token, config) do
config
|> store_config()
|> CredentialsCache.get(token)
|> case do
:not_found -> nil
{user, _metadata} -> user
end
end

@impl true
@spec create(Conn.t(), map(), Config.t()) :: {Conn.t(), map()}
def create(conn, user, _config) do
{conn, user}
end

@impl true
@spec delete(Conn.t(), Config.t()) :: Conn.t()
def delete(conn, config) do
case fetch_auth_token(conn, config) do
nil ->
:ok

token ->
config
|> store_config()
|> CredentialsCache.delete(token)
end

conn
end

defp fetch_auth_token(conn, _config) do
with [token | _rest] <- Conn.get_req_header(conn, "authorization"),
"bearer " <> token <- String.downcase(token) do
token
else
_any -> nil
end
end

defp store_config(config) do
backend = Config.get(config, :cache_store_backend, Pow.Store.Backend.EtsCache)

[backend: backend]
end
end
12 changes: 12 additions & 0 deletions lib/chat_api_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ defmodule ChatApiWeb.Router do
plug(ChatApiWeb.EnsureUserEnabledPlug)
end

pipeline :public_api do
plug(ChatApiWeb.IPAddressPlug)
plug(:accepts, ["json"])
plug(ChatApiWeb.PublicAPIAuthPlug, otp_app: :chat_api)
end

# Swagger
scope "/api/swagger" do
forward "/", PhoenixSwagger.Plug.SwaggerUI, otp_app: :chat_api, swagger_file: "swagger.json"
Expand Down Expand Up @@ -103,6 +109,12 @@ defmodule ChatApiWeb.Router do
post("/event_subscriptions/verify", EventSubscriptionController, :verify)
end

scope "/api/v1", ChatApiWeb do
pipe_through([:public_api])

get("/me", SessionController, :me)
end

# Enables LiveDashboard only for development
#
# If you want to use the LiveDashboard in production, you should put
Expand Down

0 comments on commit 0dbcd86

Please sign in to comment.