Skip to content

Commit

Permalink
Igniter Setup
Browse files Browse the repository at this point in the history
  • Loading branch information
maennchen committed Sep 10, 2024
1 parent d353ea2 commit c66fbd3
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 3 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,14 @@ Supervisor.init(
)
```

**using [`igniter`](https://hex.pm/packages/igniter)**

```bash
mix oidcc.gen.provider_configuration_worker \
--name MyApp.OidccConfigProvider \
--issuer https://accounts.google.com
```

## Usage

### Companion libraries
Expand All @@ -213,8 +221,6 @@ Supervisor.init(
- [`oidcc_plug`](https://hex.pm/packages/oidcc_plug) - Integrations for
[`plug`](https://hex.pm/packages/plug) and
[`phoenix`](https://hex.pm/packages/phoenix)
- [`phx_gen_oidcc`](https://hex.pm/packages/phx_gen_oidcc) - Setup Generator for
[`phoenix`](https://hex.pm/packages/phoenix)
- [`ueberauth_oidcc`](https://hex.pm/packages/ueberauth_oidcc) - Integration for
[`ueberauth`](https://hex.pm/packages/ueberauth)

Expand Down
141 changes: 141 additions & 0 deletions lib/mix/tasks/oidcc.gen.provider_configuration_worker.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
defmodule Mix.Tasks.Oidcc.Gen.ProviderConfigurationWorker do
@example "mix oidcc.gen.provider_configuration_worker --name MyApp.OpenIDProvider"

@shortdoc "Generate an OpenID Connect provider configuration worker"
if !Code.ensure_loaded?(Igniter) do
@shortdoc "#{@shortdoc} | Install `igniter` to use"
end

@moduledoc """
#{@shortdoc}
Adds an `Oidcc.ProviderConfiguration.Worker` to your application and
configures it via the `runtime.exs` configuration file.
## Example
```bash
#{@example}
```
## Options
* `--name` or `-n` - The name of the provider configuration worker
* `--issuer` or `-i` - The issuer of the provider
"""

if Code.ensure_loaded?(Igniter) do
use Igniter.Mix.Task

alias Igniter.Code.Module
alias Igniter.Project.Application
alias Igniter.Project.Config

@impl Igniter.Mix.Task
def info(_argv, _composing_task) do
%Igniter.Mix.Task.Info{
# dependencies to add
adds_deps: [],
# dependencies to add and call their associated installers, if they exist
installs: [],
# An example invocation
example: @example,
# Accept additional arguments that are not in your schema
# Does not guarantee that, when composed, the only options you get are the ones you define
extra_args?: false,
# A list of environments that this should be installed in, only relevant if this is an installer.
only: nil,
# a list of positional arguments, i.e `[:file]`
positional: [],
# Other tasks your task composes using `Igniter.compose_task`, passing in the CLI argv
# This ensures your option schema includes options from nested tasks
composes: [],
# `OptionParser` schema
schema: [name: :string, issuer: :string],
# CLI aliases
aliases: [n: :name, i: :issuer]
}
end

@impl Igniter.Mix.Task
def igniter(igniter, argv) do
# extract positional arguments according to `positional` above
{_arguments, argv} = positional_args!(argv)
# extract options according to `schema` and `aliases` above
options = setup_options(argv, igniter)

igniter
|> configure_issuer(options)
|> add_application_worker(options)
end

defp setup_options(argv, igniter) do
argv
|> options!()
|> Keyword.update(
:name,
Module.module_name(igniter, "OpenIDProvider"),
&Module.parse/1
)
|> Keyword.put(:app_name, Igniter.Project.Application.app_name(igniter))
end

defp configure_issuer(igniter, options) do
env_prefix =
options[:name] |> Macro.underscore() |> String.upcase() |> String.replace("/", "_")

config =
case Keyword.fetch(options, :issuer) do
{:ok, issuer} ->
quote do
[issuer: System.get_env(unquote("#{env_prefix}_ISSUER"), unquote(issuer))]
end

:error ->
quote do
[issuer: System.fetch_env!(unquote("#{env_prefix}_ISSUER"))]
end
end

Config.configure_new(
igniter,
"runtime.exs",
options[:app_name],
[options[:name]],
{:code, config}
)
end

defp add_application_worker(igniter, options) do
Application.add_new_child(
igniter,
{Oidcc.ProviderConfiguration.Worker,
{:code,
quote do
%{
name: unquote(options[:name]),
issuer:
Application.fetch_env!(unquote(options[:app_name]), unquote(options[:name]))[
:issuer
]
}
end}}
)
end
else
use Mix.Task

@impl Mix.Task
def run(_argv) do
Mix.shell().error("""
The task 'oidcc.gen.provider_configuration_worker' requires igniter to be run.
Please install igniter and try again.
For more information, see: https://hexdocs.pm/igniter
""")

exit({:shutdown, 1})
end
end
end
3 changes: 2 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ defmodule Oidcc.Mixfile do
{:mock, "~> 0.3.8", only: :test},
{:ex_doc, "~> 0.29", only: :dev, runtime: false},
{:credo, "~> 1.7", only: :dev, runtime: false},
{:dialyxir, "~> 1.4", only: :dev, runtime: false}
{:dialyxir, "~> 1.4", only: :dev, runtime: false},
{:igniter, "~> 0.3.33", optional: true}
]
end

Expand Down
63 changes: 63 additions & 0 deletions test/mix/tasks/oidcc.gen.provider_configuration_worker_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
defmodule Mix.Tasks.Oidcc.Gen.ProviderConfigurationWorkerTest do
use ExUnit.Case, async: true
import Igniter.Test

test "adds configuration if the file doesn't exist yet" do
test_project()
|> Igniter.compose_task("oidcc.gen.provider_configuration_worker", [
"--name",
"Test.Provider",
"--issuer",
"https://accounts.google.com"
])
|> assert_creates("config/runtime.exs", """
import Config
config :test, Test.Provider,
issuer: System.get_env("TEST_PROVIDER_ISSUER", "https://accounts.google.com")
""")
end

test "patches configuration if the file exists" do
test_project(
files: %{
"config/runtime.exs" => """
import Config
config :logger, level: :info
"""
}
)
|> Igniter.compose_task("oidcc.gen.provider_configuration_worker", [])
|> assert_has_patch("config/runtime.exs", """
1 1 |import Config
2 2 |
3 + |config :test, Test.OpenIDProvider, issuer: System.fetch_env!("TEST_OPEN_ID_PROVIDER_ISSUER")
3 4 |config :logger, level: :info
4 5 |
""")
end

test "adds worker to application supervision tree" do
test_project()
|> Igniter.compose_task("oidcc.gen.provider_configuration_worker", ["--name", "Test.Provider"])
|> assert_creates("lib/test/application.ex", """
defmodule Test.Application do
@moduledoc false
use Application
@impl true
def start(_type, _args) do
children = [
{Oidcc.ProviderConfiguration.Worker,
%{name: Test.Provider, issuer: Application.fetch_env!(:test, Test.Provider)[:issuer]}}
]
opts = [strategy: :one_for_one, name: Test.Supervisor]
Supervisor.start_link(children, opts)
end
end
""")
end
end

0 comments on commit c66fbd3

Please sign in to comment.