Hi,
We’re in the process of upgrading from 1.13 to 1.14.
We had various calls to compile_env
to access env variables, and from what the warnings are telling me these should be get_env
.
I’ve replaced these all, going from
@access_key Application.compile_env(:app, key)
to
defp access_key, do: Application.get_env(:app, :key)
This seems to have worked fine and cleared 99% of the errors, however there is one issue with Guardian that I can’t solve:
defmodule App.Auth.Bla do
use Guardian,
otp_app: :app,
allowed_algos: ["HS512"],
issuer: "app",
secret_key: Application.compile_env(:app, __MODULE__)[:secret_key]
end
Because this call happens outside of a function, I cannot replace it with get_env
. But leaving it at compile_env
throws an error. I also can’t move it into a function as the function is not yet defined when the above code is invoked.
How can I access an environment variable and feed it into Guardian as the secret key without calling compile_env? Or is there another approach I’m missing?
Thanks
2 Likes
Can you post the error you get? You should be using compile_env
for compile time set config.
With compile_env
you want to put the complete path into the function call:
Application.compile_env(:app, [__MODULE__, :secret_key])
That allows elixir to track dependencies better.
3 Likes
Sure, it’s:
== Compilation error in file lib/app/auth/bla.ex ==
** (RuntimeError) Application.compile_env/3 cannot be called inside functions, only in the module body
(elixir 1.14.0) lib/application.ex:532: Application."MACRO-compile_env"/4
(elixir 1.14.0) expanding macro: Application.compile_env/2
lib/app/auth/bla.ex:12: App.Auth.Bla.config/0
(elixir 1.14.0) expanding macro: Kernel.|>/2
lib/app/auth/bla.ex:8: App.Auth.Bla.config/
It mentions line 8 and line 12 of the file, which are use Guardian
and secret_key: Application.compile_env(:app, __MODULE__)[:secret_key]
respectively
Seems like guardian
is putting the AST of the call in a function. I’d probably just put assign the secret to a module attribute and give that to guardian
, unless you actually need that to be runtime configurable.
Annoyingly I can’t do that
@secret_key Application.compile_env(:app, [__MODULE__, :secret_key])
Throws an error as this variable is different at compile time vs run time, and I can’t call get_env
here as it’s outside of a function.
I also can’t do
defp secret_key, do: Application.get_env(:app, [__MODULE__, :secret_key])
as this function isn’t defined when Guardian has its secret key assigned
I might be off here, but if guardian indeed puts the AST for fetching the secret in a function for runtime use and also tries to access it at compile time then I think that’s something to fix on guardian’s end. It should be doing either/or, but not both.
You can keep configuration to the minimum in implementation module of the Guardian - move the rest in config files.
# bla.ex
defmodule App.Auth.Bla do
use Guardian, otp_app: :app
end
# sample.config/dev.exs
config :app, App.Auth.Bla,
allowed_algos: ["HS512"],
issuer: "app",
secret_key: "AppBlaSecretKey"
You can read more in config section of Guardian docs
This will be regular configuration loading from environment, once the implementation module is kept minimal.
3 Likes
This actually works too thank you so much
2 Likes