Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dynamic application_id and api_key #99

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,27 @@ defmodule People do
end
```

## Configure Altnertive Credentials

An index might need a different application_id / api_key. To accomplish this you can use the credentials configuration (each entry should be a `{application_id, api_key}` tuple).

```elixir
config :algoliax,
api_key: System.get_env("ALGOLIA_API_KEY"),
application_id: System.get_env("ALGOLIA_APPLICATION_ID)
credentials: %{
custom_1: {"<APPLICATION_ID_1>", "<API_KEY_2>"},
custom_2: {System.get_env("ALGOLIA_APPLICATION_ID_2"), System.get_env("ALGOLIA_API_KEY_2")},
}

defmodule People do
use Algoliax.Indexer,
#....
credentials: :custom_1
end

If you do not specify a credentials key the default api_key / application_id on the `:algoliax` configuration will be used.

## Copyright and License

Copyright (c) 2020 CORUSCANT (welcome to the jungle) - <https://www.welcometothejungle.com>
Expand Down
5 changes: 4 additions & 1 deletion config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ config :algoliax,
application_id: "APPLICATION_ID",
api_key: "api_key",
batch_size: 1,
ecto_repos: [Algoliax.Repo]
ecto_repos: [Algoliax.Repo],
credentials: %{
custom_1: {"APPLICATION_ID_1", "api_key_1"}
}

config :algoliax, Algoliax.Repo,
pool: Ecto.Adapters.SQL.Sandbox,
Expand Down
12 changes: 6 additions & 6 deletions lib/algoliax/client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule Algoliax.Client do

require Logger

alias Algoliax.{Config, Routes}
alias Algoliax.Routes

def request(request, retry \\ 0)

Expand All @@ -17,7 +17,7 @@ defmodule Algoliax.Client do
log(action, method, url, body)

method
|> :hackney.request(url, request_headers(), Jason.encode!(body), [
|> :hackney.request(url, request_headers(request), Jason.encode!(body), [
:with_body,
recv_timeout: recv_timeout()
])
Expand Down Expand Up @@ -50,16 +50,16 @@ defmodule Algoliax.Client do

defp build_response(response, request) do
case Jason.decode(response) do
{:ok, response} -> Algoliax.Response.new(response, request[:url_params])
{:ok, response} -> Algoliax.Response.new(response, request)
error -> error
end
end

defp request_headers do
defp request_headers(request) do
[
{"Content-type", "application/json"},
{"X-Algolia-API-Key", Config.api_key()},
{"X-Algolia-Application-Id", Config.application_id()}
{"X-Algolia-API-Key", request.api_key},
{"X-Algolia-Application-Id", request.application_id}
] ++ x_forwarded_for()
end

Expand Down
20 changes: 20 additions & 0 deletions lib/algoliax/config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,30 @@ defmodule Algoliax.Config do
Application.get_env(:algoliax, :api_key)
end

def api_key(credenital_name) do
:algoliax
|> Application.get_env(:credentials, [])
|> Map.fetch(credenital_name)
|> then(fn
{:ok, {_application_id, api_key}} -> api_key
:error -> raise Algoliax.InvalidAlgoliaCredentialsError, %{name: inspect(credenital_name)}
end)
end

def application_id do
Application.get_env(:algoliax, :application_id)
end

def application_id(credenital_name) do
:algoliax
|> Application.get_env(:credentials, [])
|> Map.fetch(credenital_name)
|> then(fn
{:ok, {application_id, _api_key}} -> application_id
:error -> raise Algoliax.InvalidAlgoliaCredentialsError, %{name: inspect(credenital_name)}
end)
end

def cursor_field do
Application.get_env(:algoliax, :cursor_field)
end
Expand Down
13 changes: 13 additions & 0 deletions lib/algoliax/exceptions.ex
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@ defmodule Algoliax.InvalidAlgoliaSettingsFunctionError do
end
end

defmodule Algoliax.InvalidAlgoliaCredentialsError do
@moduledoc "Raise when `:crendentials` are invalid"

defexception [:message]

@impl true
def exception(%{name: name}) do
%__MODULE__{
message: "Expected #{name} to be configuired in alogila credentials"
}
end
end

defmodule Algoliax.InvalidAlgoliaSettingsConfigurationError do
@moduledoc "Raise when the `:algolia` settings are unsupported"

Expand Down
24 changes: 24 additions & 0 deletions lib/algoliax/indexer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ defmodule Algoliax.Indexer do
- `:schemas`: Specify which schemas used to populate index, Default: `[__CALLER__]`
- `:default_filters`: Specify default filters to be used when reindex without providing a query. Must be a map or a function name (that returns a map). Default: `%{}`.
- `:algolia`: Any valid Algolia settings (using snake case or camel case, ie `attributeForFaceting` can be configured with `:attribute_for_faceting`) or the name of 0-arity function that returns those settings.
- `:credentials`: Specify an alternative application_id / api_key for this index. Default `nil`

On first call to Algolia, we check that the settings on Algolia are up to date.

Expand Down Expand Up @@ -157,6 +158,29 @@ defmodule Algoliax.Indexer do
[attribute_for_faceting: ["age"]]
end
end

### Alternative Credentials

An index might need a different application_id / api_key. To accomplish this you can use the credentials configuration.

```elixir
config :algoliax,
api_key: System.get_env("ALGOLIA_API_KEY"),
application_id: System.get_env("ALGOLIA_APPLICATION_ID)
credentials: %{
custom_1: {"<APPLICATION_ID_1>", "<API_KEY_2>"},
custom_2: {System.get_env("ALGOLIA_APPLICATION_ID_2"), System.get_env("ALGOLIA_API_KEY_2")},
}

defmodule People do
use Algoliax.Indexer,
#....
credentials: :custom_1
end

If you do not specify a credentials key the default api_key / application_id on the `:algoliax` configuration will be used.
```

"""

alias Algoliax.Resources.{Index, Object, Search}
Expand Down
46 changes: 37 additions & 9 deletions lib/algoliax/resources/index.ex
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
defmodule Algoliax.Resources.Index do
@moduledoc false

import Algoliax.Utils, only: [index_name: 2, algolia_settings: 2, render_response: 1]
import Algoliax.Client, only: [request: 1]

import Algoliax.Utils,
only: [
algolia_settings: 2,
api_key: 1,
application_id: 1,
index_name: 2,
render_response: 1
]

alias Algoliax.{Settings, SettingsStore}

def ensure_settings(module, index_name, settings, replica_index) do
case SettingsStore.get_settings(index_name) do
nil ->
request_configure_index(
index_name,
settings,
settings_to_algolia_settings(module, settings, replica_index)
)

algolia_remote_settings = request_get_settings(index_name)
algolia_remote_settings = request_get_settings(index_name, settings)
SettingsStore.set_settings(index_name, algolia_remote_settings)
replicas_names(module, settings, replica_index)

Expand Down Expand Up @@ -94,7 +103,7 @@ defmodule Algoliax.Resources.Index do
def get_settings(module, settings) do
index_name(module, settings)
|> Enum.map(fn index_name ->
algolia_remote_settings = request_get_settings(index_name)
algolia_remote_settings = request_get_settings(index_name, settings)
SettingsStore.set_settings(index_name, algolia_remote_settings)
algolia_remote_settings
end)
Expand All @@ -108,6 +117,7 @@ defmodule Algoliax.Resources.Index do
r =
request_configure_index(
index_name,
settings,
settings_to_algolia_settings(module, settings, replica_index)
)

Expand All @@ -125,25 +135,43 @@ defmodule Algoliax.Resources.Index do
end)
end

defp request_configure_index(index_name, settings) do
defp request_configure_index(index_name, settings, alogolia_settings) do
api_key = api_key(settings)
application_id = application_id(settings)

request(%{
action: :configure_index,
url_params: [index_name: index_name],
body: settings
url_params: [index_name: index_name, application_id: application_id],
body: alogolia_settings,
api_key: api_key,
application_id: application_id
})
end

defp request_get_settings(index_name) do
defp request_get_settings(index_name, settings) do
api_key = api_key(settings)
application_id = application_id(settings)

request(%{
action: :get_settings,
url_params: [index_name: index_name]
url_params: [index_name: index_name, application_id: application_id],
api_key: api_key,
application_id: application_id
})
end

def delete_index(module, settings) do
api_key = api_key(settings)
application_id = application_id(settings)

index_name(module, settings)
|> Enum.map(fn index_name ->
request(%{action: :delete_index, url_params: [index_name: index_name]})
request(%{
action: :delete_index,
url_params: [index_name: index_name, application_id: application_id],
api_key: api_key,
application_id: application_id
})
end)
|> render_response()
end
Expand Down
Loading