Skip to content

Commit 2c7fc9a

Browse files
committed
Add :otp_app configuration support for extension mix tasks
1 parent f0614c7 commit 2c7fc9a

7 files changed

+177
-57
lines changed

lib/mix/pow/extension.ex

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,27 @@ defmodule Mix.Pow.Extension do
22
@moduledoc """
33
Utilities module for mix extension tasks.
44
"""
5+
alias Pow.Config
56

6-
@spec extensions(map()) :: [atom()]
7-
def extensions(config) do
7+
@spec extensions(map(), atom()) :: [atom()]
8+
def extensions(config, otp_app) do
89
config
910
|> Map.get(:extension, [])
1011
|> List.wrap()
1112
|> Enum.map(&Module.concat(Elixir, &1))
13+
|> maybe_fetch_otp_app_extensions(otp_app)
14+
end
15+
16+
defp maybe_fetch_otp_app_extensions([], otp_app) do
17+
Config.get([otp_app: otp_app], :extensions, [])
18+
end
19+
defp maybe_fetch_otp_app_extensions(extensions, _otp_app), do: extensions
20+
21+
@spec no_extensions_error(atom()) :: :ok
22+
def no_extensions_error(otp_app) do
23+
Mix.shell.error(
24+
"""
25+
No extensions was provided as arguments, or found in `config :#{otp_app}, :pow` configuration.
26+
""")
1227
end
1328
end

lib/mix/tasks/extension/ecto/pow.extension.ecto.gen.migrations.ex

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ defmodule Mix.Tasks.Pow.Extension.Ecto.Gen.Migrations do
44
@moduledoc """
55
Generates a migration files for extensions.
66
7+
## Usage
8+
9+
Install migration files for extensions explicitly:
10+
11+
mix pow.extension.ecto.gen.migrations -r MyApp.Repo --extension PowEmailConfirmation
12+
13+
mix pow.extension.ecto.gen.migrations -r MyApp.Repo Accounts.Organization organizations --extension PowEmailConfirmation
14+
15+
Use the context app configuration environment for extensions:
16+
717
mix pow.extension.ecto.gen.migrations -r MyApp.Repo
818
919
mix pow.extension.ecto.gen.migrations -r MyApp.Repo Accounts.Organization organizations
@@ -24,6 +34,7 @@ defmodule Mix.Tasks.Pow.Extension.Ecto.Gen.Migrations do
2434
|> Pow.parse_options(@switches, @default_opts)
2535
|> parse()
2636
|> create_migrations_files(args)
37+
|> print_shell_instructions()
2738
end
2839

2940
defp parse({config, parsed, _invalid}) do
@@ -37,17 +48,20 @@ defmodule Mix.Tasks.Pow.Extension.Ecto.Gen.Migrations do
3748
end
3849

3950
defp create_migrations_files(config, args) do
51+
context_base = Pow.context_base(Pow.context_app())
52+
otp_app = String.to_atom(Macro.underscore(context_base))
53+
extensions = Extension.extensions(config, otp_app)
54+
4055
args
4156
|> Ecto.parse_repo()
4257
|> Enum.map(&Ecto.ensure_repo(&1, args))
4358
|> Enum.map(&Map.put(config, :repo, &1))
44-
|> Enum.each(&create_extension_migration_files/1)
45-
end
59+
|> Enum.each(&create_extension_migration_files(&1, extensions, context_base))
4660

47-
defp create_extension_migration_files(config) do
48-
extensions = Extension.extensions(config)
49-
context_base = Pow.context_base(Pow.context_app())
61+
%{extensions: extensions, otp_app: otp_app}
62+
end
5063

64+
defp create_extension_migration_files(config, extensions, context_base) do
5165
for extension <- extensions,
5266
do: create_migration_files(config, extension, context_base)
5367
end
@@ -66,4 +80,9 @@ defmodule Mix.Tasks.Pow.Extension.Ecto.Gen.Migrations do
6680
defp empty?(%{assocs: [], attrs: [], indexes: []}),
6781
do: true
6882
defp empty?(_schema), do: false
83+
84+
defp print_shell_instructions(%{extensions: [], otp_app: otp_app}) do
85+
Extension.no_extensions_error(otp_app)
86+
end
87+
defp print_shell_instructions(config), do: config
6988
end

lib/mix/tasks/extension/phoenix/pow.extension.phoenix.gen.templates.ex

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,15 @@ defmodule Mix.Tasks.Pow.Extension.Phoenix.Gen.Templates do
44
@moduledoc """
55
Generates pow extension templates for Phoenix.
66
7-
mix pow.extension.phoenix.gen.templates
7+
## Usage
8+
9+
Install extension templates explicitly:
10+
11+
mix pow.extension.phoenix.gen.templates --extension PowEmailConfirmation
12+
13+
Use the context app configuration environment for extensions:
14+
15+
mix pow.extension.phoenix.gen.templates --context-app my_app
816
"""
917
use Mix.Task
1018

@@ -20,6 +28,7 @@ defmodule Mix.Tasks.Pow.Extension.Phoenix.Gen.Templates do
2028
args
2129
|> Pow.parse_options(@switches, @default_opts)
2230
|> create_template_files()
31+
|> print_shell_instructions()
2332
end
2433

2534
@extension_templates [
@@ -28,12 +37,13 @@ defmodule Mix.Tasks.Pow.Extension.Phoenix.Gen.Templates do
2837
]}
2938
]
3039
defp create_template_files({config, _parsed, _invalid}) do
31-
structure = Phoenix.parse_structure(config)
32-
web_module = structure[:web_module]
33-
web_prefix = structure[:web_prefix]
34-
extensions =
40+
structure = Phoenix.parse_structure(config)
41+
web_module = structure[:web_module]
42+
web_prefix = structure[:web_prefix]
43+
otp_app = String.to_atom(Macro.underscore(structure[:context_base]))
44+
extensions =
3545
config
36-
|> Extension.extensions()
46+
|> Extension.extensions(otp_app)
3747
|> Enum.filter(&Keyword.has_key?(@extension_templates, &1))
3848
|> Enum.map(&{&1, @extension_templates[&1]})
3949

@@ -44,6 +54,11 @@ defmodule Mix.Tasks.Pow.Extension.Phoenix.Gen.Templates do
4454
end)
4555
end)
4656

47-
%{structure: structure}
57+
%{extensions: extensions, otp_app: otp_app, structure: structure}
58+
end
59+
60+
defp print_shell_instructions(%{extensions: [], otp_app: otp_app}) do
61+
Extension.no_extensions_error(otp_app)
4862
end
63+
defp print_shell_instructions(config), do: config
4964
end

lib/mix/tasks/extension/phoenix/pow.extension.phoenix.mailer.gen.templates.ex

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,15 @@ defmodule Mix.Tasks.Pow.Extension.Phoenix.Mailer.Gen.Templates do
44
@moduledoc """
55
Generates Pow mailer extension templates for Phoenix.
66
7-
mix pow.extension.phoenix.mailer.gen.templates
7+
## Usage
8+
9+
Install extension mailer templates explicitly:
10+
11+
mix pow.extension.phoenix.mailer.gen.templates --extension PowEmailConfirmation
12+
13+
Use the context app configuration environment for extensions:
14+
15+
mix pow.extension.phoenix.mailer.gen.templates --context-app my_app
816
"""
917
use Mix.Task
1018

@@ -32,12 +40,13 @@ defmodule Mix.Tasks.Pow.Extension.Phoenix.Mailer.Gen.Templates do
3240
]}
3341
]
3442
defp create_template_files({config, _parsed, _invalid}) do
35-
structure = Phoenix.parse_structure(config)
36-
web_module = structure[:web_module]
37-
web_prefix = structure[:web_prefix]
38-
extensions =
43+
structure = Phoenix.parse_structure(config)
44+
web_module = structure[:web_module]
45+
web_prefix = structure[:web_prefix]
46+
otp_app = String.to_atom(Macro.underscore(structure[:context_base]))
47+
extensions =
3948
config
40-
|> Extension.extensions()
49+
|> Extension.extensions(otp_app)
4150
|> Enum.filter(&Keyword.has_key?(@extension_templates, &1))
4251
|> Enum.map(&{&1, @extension_templates[&1]})
4352

@@ -49,9 +58,12 @@ defmodule Mix.Tasks.Pow.Extension.Phoenix.Mailer.Gen.Templates do
4958
end)
5059
end)
5160

52-
%{structure: structure}
61+
%{extensions: extensions, otp_app: otp_app, structure: structure}
5362
end
5463

64+
defp print_shell_instructions(%{extensions: [], otp_app: otp_app}) do
65+
Extension.no_extensions_error(otp_app)
66+
end
5567
defp print_shell_instructions(%{structure: structure}) do
5668
web_base = structure[:web_module]
5769
web_prefix = structure[:web_prefix]

test/mix/tasks/extension/ecto/pow.extension.ecto.gen.migrations_test.exs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ defmodule Mix.Tasks.Pow.Extension.Ecto.Gen.MigrationsTest do
4747
end)
4848
end
4949

50+
test "warns if no extensions" do
51+
File.cd!(@tmp_path, fn ->
52+
Migrations.run(["-r", inspect(Repo)])
53+
54+
assert_received {:mix_shell, :error, [msg]}
55+
assert msg =~ "No extensions was provided as arguments, or found in `config :pow, :pow` configuration."
56+
end)
57+
end
58+
5059
test "generates with :binary_id" do
5160
options = @options ++ ~w(--binary-id)
5261

@@ -61,6 +70,24 @@ defmodule Mix.Tasks.Pow.Extension.Ecto.Gen.MigrationsTest do
6170
end)
6271
end
6372

73+
describe "with :otp_app configuration" do
74+
setup do
75+
Application.put_env(:pow, :pow, extensions: [__MODULE__])
76+
on_exit(fn ->
77+
Application.delete_env(:pow, :pow)
78+
end)
79+
end
80+
81+
test "generates migrations" do
82+
File.cd!(@tmp_path, fn ->
83+
Application.put_env(:pow, :pow, extensions: [__MODULE__])
84+
Migrations.run(["-r", inspect(Repo)])
85+
86+
assert [_migration_file] = File.ls!(@migrations_path)
87+
end)
88+
end
89+
end
90+
6491
test "doesn't make duplicate migrations" do
6592
options = @options ++ ["--extension", __MODULE__]
6693

test/mix/tasks/extension/phoenix/pow.extension.phoenix.gen.templates_test.exs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,27 +48,43 @@ defmodule Mix.Tasks.Pow.Extension.Phoenix.Gen.TemplatesTest do
4848
end)
4949
end
5050

51-
test "generates with :context_app" do
52-
options = @options ++ ~w(--context-app test)
53-
51+
test "warns if no extensions" do
5452
File.cd!(@tmp_path, fn ->
55-
Templates.run(options)
53+
Templates.run([])
5654

57-
for {module, expected_templates} <- @expected_template_files do
58-
templates_path = Path.join(["lib", "test_web", "templates", Macro.underscore(module)])
59-
dirs = templates_path |> File.ls!() |> Enum.sort()
55+
assert_received {:mix_shell, :error, [msg]}
56+
assert msg =~ "No extensions was provided as arguments, or found in `config :pow, :pow` configuration."
57+
end)
58+
end
6059

61-
assert dirs == Map.keys(expected_templates)
60+
describe "with :context_app configuration" do
61+
setup do
62+
Application.put_env(:test, :pow, extensions: [PowResetPassword, PowEmailConfirmation])
63+
on_exit(fn ->
64+
Application.delete_env(:test, :pow)
65+
end)
66+
end
6267

63-
views_path = Path.join(["lib", "test_web", "views", Macro.underscore(module)])
68+
test "generates templates" do
69+
File.cd!(@tmp_path, fn ->
70+
Templates.run(~w(--context-app test))
6471

65-
[base_name | _rest] = expected_templates |> Map.keys()
66-
view_content = views_path |> Path.join(base_name <> "_view.ex") |> File.read!()
72+
for {module, expected_templates} <- @expected_template_files do
73+
templates_path = Path.join(["lib", "test_web", "templates", Macro.underscore(module)])
74+
dirs = templates_path |> File.ls!() |> Enum.sort()
6775

68-
assert view_content =~ "defmodule TestWeb.#{inspect(module)}.#{Macro.camelize(base_name)}View do"
69-
assert view_content =~ "use TestWeb, :view"
70-
end
71-
end)
76+
assert dirs == Map.keys(expected_templates)
77+
78+
views_path = Path.join(["lib", "test_web", "views", Macro.underscore(module)])
79+
80+
[base_name | _rest] = expected_templates |> Map.keys()
81+
view_content = views_path |> Path.join(base_name <> "_view.ex") |> File.read!()
82+
83+
assert view_content =~ "defmodule TestWeb.#{inspect(module)}.#{Macro.camelize(base_name)}View do"
84+
assert view_content =~ "use TestWeb, :view"
85+
end
86+
end)
87+
end
7288
end
7389

7490
defp ls(path), do: path |> File.ls!() |> Enum.sort()

test/mix/tasks/extension/phoenix/pow.extension.phoenix.mailer.gen.templates_test.exs

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -60,33 +60,49 @@ defmodule Mix.Tasks.Pow.Extension.Phoenix.Mailer.Gen.TemplatesTest do
6060
end)
6161
end
6262

63-
test "generates with :context_app" do
64-
options = @options ++ ~w(--context-app test)
65-
63+
test "warns if no extensions" do
6664
File.cd!(@tmp_path, fn ->
67-
Templates.run(options)
65+
Templates.run([])
6866

69-
for {module, expected_templates} <- @expected_template_files do
70-
templates_path = Path.join(["lib", "test_web", "templates", Macro.underscore(module)])
71-
dirs = templates_path |> File.ls!() |> Enum.sort()
67+
assert_received {:mix_shell, :error, [msg]}
68+
assert msg =~ "No extensions was provided as arguments, or found in `config :pow, :pow` configuration."
69+
end)
70+
end
7271

73-
assert dirs == Map.keys(expected_templates)
72+
describe "with :context_app configuration" do
73+
setup do
74+
Application.put_env(:test, :pow, extensions: [PowResetPassword, PowEmailConfirmation])
75+
on_exit(fn ->
76+
Application.delete_env(:test, :pow)
77+
end)
78+
end
7479

75-
views_path = Path.join(["lib", "test_web", "views", Macro.underscore(module)])
76-
[base_name | _rest] = expected_templates |> Map.keys()
77-
view_content = views_path |> Path.join(base_name <> "_view.ex") |> File.read!()
80+
test "generates mailer templates" do
81+
File.cd!(@tmp_path, fn ->
82+
Templates.run(~w(--context-app test))
7883

79-
assert view_content =~ "defmodule TestWeb.#{inspect(module)}.#{Macro.camelize(base_name)}View do"
80-
assert view_content =~ "use TestWeb, :mailer_view"
81-
end
84+
for {module, expected_templates} <- @expected_template_files do
85+
templates_path = Path.join(["lib", "test_web", "templates", Macro.underscore(module)])
86+
dirs = templates_path |> File.ls!() |> Enum.sort()
8287

83-
for _ <- 1..6, do: assert_received({:mix_shell, :info, [_msg]})
84-
assert_received {:mix_shell, :info, [msg]}
85-
assert msg =~ "lib/test_web.ex"
86-
assert msg =~ ":mailer_view"
87-
assert msg =~ "def mailer_view"
88-
assert msg =~ "use Phoenix.View, root: \"lib/test_web/templates\""
89-
end)
88+
assert dirs == Map.keys(expected_templates)
89+
90+
views_path = Path.join(["lib", "test_web", "views", Macro.underscore(module)])
91+
[base_name | _rest] = expected_templates |> Map.keys()
92+
view_content = views_path |> Path.join(base_name <> "_view.ex") |> File.read!()
93+
94+
assert view_content =~ "defmodule TestWeb.#{inspect(module)}.#{Macro.camelize(base_name)}View do"
95+
assert view_content =~ "use TestWeb, :mailer_view"
96+
end
97+
98+
for _ <- 1..6, do: assert_received({:mix_shell, :info, [_msg]})
99+
assert_received {:mix_shell, :info, [msg]}
100+
assert msg =~ "lib/test_web.ex"
101+
assert msg =~ ":mailer_view"
102+
assert msg =~ "def mailer_view"
103+
assert msg =~ "use Phoenix.View, root: \"lib/test_web/templates\""
104+
end)
105+
end
90106
end
91107

92108
defp ls(path), do: path |> File.ls!() |> Enum.sort()

0 commit comments

Comments
 (0)