Repository: phoenixframework/phoenix
Pull request #4279 (2021-03-29 17:18:32)

Bump y18n from 4.0.0 to 4.0.1 in /assets
Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.1.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/yargs/y18n/blob/master/CHANGELOG.md">y18n's changelog</a>.</em></p>
<blockquote>
<h1>Change Log</h1>
<p>All notable changes to this project will be documented in this file. See <a href="https://github.com/conventional-changelog/standard-version">standard-version</a> for commit guidelines.</p>
<h3><a href="https://www.github.com/yargs/y18n/compare/v5.0.4...v5.0.5">5.0.5</a> (2020-10-25)</h3>
<h3>Bug Fixes</h3>
<ul>
<li>address prototype pollution issue (<a href="https://www.github-redirect.dependabot.com/yargs/y18n/issues/108">#108</a>) (<a href="https://www.github.com/yargs/y18n/commit/a9ac604abf756dec9687be3843e2c93bfe581f25">a9ac604</a>)</li>
</ul>
<h3><a href="https://www.github.com/yargs/y18n/compare/v5.0.3...v5.0.4">5.0.4</a> (2020-10-16)</h3>
<h3>Bug Fixes</h3>
<ul>
<li><strong>exports:</strong> node 13.0 and 13.1 require the dotted object form <em>with</em> a string fallback (<a href="https://www.github-redirect.dependabot.com/yargs/y18n/issues/105">#105</a>) (<a href="https://www.github.com/yargs/y18n/commit/4f85d80dbaae6d2c7899ae394f7ad97805df4886">4f85d80</a>)</li>
</ul>
<h3><a href="https://www.github.com/yargs/y18n/compare/v5.0.2...v5.0.3">5.0.3</a> (2020-10-16)</h3>
<h3>Bug Fixes</h3>
<ul>
<li><strong>exports:</strong> node 13.0-13.6 require a string fallback (<a href="https://www.github-redirect.dependabot.com/yargs/y18n/issues/103">#103</a>) (<a href="https://www.github.com/yargs/y18n/commit/e39921e1017f88f5d8ea97ddea854ffe92d68e74">e39921e</a>)</li>
</ul>
<h3><a href="https://www.github.com/yargs/y18n/compare/v5.0.1...v5.0.2">5.0.2</a> (2020-10-01)</h3>
<h3>Bug Fixes</h3>
<ul>
<li><strong>deno:</strong> update types for deno ^1.4.0 (<a href="https://www.github-redirect.dependabot.com/yargs/y18n/issues/100">#100</a>) (<a href="https://www.github.com/yargs/y18n/commit/3834d9ab1332f2937c935ada5e76623290efae81">3834d9a</a>)</li>
</ul>
<h3><a href="https://www.github.com/yargs/y18n/compare/v5.0.0...v5.0.1">5.0.1</a> (2020-09-05)</h3>
<h3>Bug Fixes</h3>
<ul>
<li>main had old index path (<a href="https://www.github-redirect.dependabot.com/yargs/y18n/issues/98">#98</a>) (<a href="https://www.github.com/yargs/y18n/commit/124f7b047ba9596bdbdf64459988304e77f3de1b">124f7b0</a>)</li>
</ul>
<h2><a href="https://www.github.com/yargs/y18n/compare/v4.0.0...v5.0.0">5.0.0</a> (2020-09-05)</h2>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li>exports maps are now used, which modifies import behavior.</li>
<li>drops Node 6 and 4. begin following Node.js LTS schedule (<a href="https://github-redirect.dependabot.com/yargs/y18n/issues/89">#89</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>add support for ESM and Deno <a href="https://www.github-redirect.dependabot.com/yargs/y18n/issues/95">#95</a>) (<a href="https://www.github.com/yargs/y18n/commit/4d7ae94bcb42e84164e2180366474b1cd321ed94">4d7ae94</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a href="https://github.com/yargs/y18n/commits">compare view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by <a href="https://www.npmjs.com/~oss-bot">oss-bot</a>, a new releaser for y18n since your current version.</p>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=y18n&package-manager=npm_and_yarn&previous-version=4.0.0&new-version=4.0.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
- `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language
- `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language
- `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language
- `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language

You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/phoenixframework/phoenix/network/alerts).

</details>


Patch:
diff --git a/RELEASE.md b/RELEASE.md
index bc0dde061..1f9911a49 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -3,8 +3,8 @@
   1. Check related deps for required version bumps and compatibility (`phoenix_ecto`, `phoenix_pubsub_redis`, `phoenix_html`)
   2. Bump version in related files below
   3. Run tests:
-    - `mix test` in the root folder
-    - `mix test` in the `installer/` folder
+      - `mix test` in the root folder
+      - `mix test` in the `installer/` folder
   4. Commit, push code
   5. Publish `phx_new` and `phoenix` packages and docs after pruning any extraneous uncommitted files
   6. Test installer by generating a new app, running `mix deps.get`, and compiling
diff --git a/assets/package-lock.json b/assets/package-lock.json
index 3826b4a2f..2cfb974c8 100644
--- a/assets/package-lock.json
+++ b/assets/package-lock.json
@@ -2665,7 +2665,7 @@
       "dependencies": {
         "acorn": {
           "version": "2.7.0",
-          "resolved": "http://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz",
           "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=",
           "dev": true
         }
@@ -3208,12 +3208,6 @@
           "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
           "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
           "dev": true
-        },
-        "y18n": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
-          "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
-          "dev": true
         }
       }
     },
@@ -6146,7 +6140,7 @@
       "dependencies": {
         "acorn": {
           "version": "2.7.0",
-          "resolved": "http://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz",
           "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=",
           "dev": true
         }
@@ -6880,7 +6874,7 @@
     },
     "minimist": {
       "version": "0.0.8",
-      "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
       "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
       "dev": true
     },
@@ -7145,12 +7139,6 @@
             "strip-ansi": "^5.0.0"
           }
         },
-        "y18n": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
-          "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
-          "dev": true
-        },
         "yargs": {
           "version": "13.3.0",
           "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz",
@@ -10453,12 +10441,6 @@
             "strip-ansi": "^5.0.0"
           }
         },
-        "y18n": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
-          "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
-          "dev": true
-        },
         "yargs": {
           "version": "13.2.4",
           "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz",
@@ -10596,7 +10578,7 @@
     },
     "wrap-ansi": {
       "version": "2.1.0",
-      "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
       "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
       "dev": true,
       "requires": {
@@ -10629,9 +10611,9 @@
       "dev": true
     },
     "y18n": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
-      "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
+      "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
       "dev": true
     },
     "yargs": {
@@ -10881,12 +10863,6 @@
             "strip-ansi": "^5.0.0"
           }
         },
-        "y18n": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
-          "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
-          "dev": true
-        },
         "yargs": {
           "version": "13.3.2",
           "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
diff --git a/guides/authentication/mix_phx_gen_auth.md b/guides/authentication/mix_phx_gen_auth.md
index bf8d8fd2e..a7134fd10 100644
--- a/guides/authentication/mix_phx_gen_auth.md
+++ b/guides/authentication/mix_phx_gen_auth.md
@@ -1,36 +1,46 @@
 # mix phx.gen.auth
 
-The `mix phx.gen.auth` command generates a flexible, pre-built authentication system into your phoenix app. This simple generator allows you to quickly move past the task of adding authentication to your codebase and stay focused on the real-world problem your application is trying to solve.
+The `mix phx.gen.auth` command generates a flexible, pre-built authentication system into your Phoenix app. This simple generator allows you to quickly move past the task of adding authentication to your codebase and stay focused on the real-world problem your application is trying to solve.
 
-## Getting Started
+## Getting started
 
 Let's start by running the following command from the root of our app (or `apps/my_app_web` in an umbrella app):
 
-    $ mix phx.gen.auth Accounts User users
+```console
+$ mix phx.gen.auth Accounts User users
+```
 
 This creates an `Accounts` context with an `Accounts.User` schema module. The final argument is the plural version of the schema module which is used for generating database table names and route helpers. The `mix phx.gen.auth` generator is similar to `mix phx.gen.html` except it does not accept a list of additional fields to add to the schema and it generates many more context functions.
 
-Since this generator installed additional dependencies in `mix.exs`, let's fetch those dependencies:
+Since this generator installed additional dependencies in `mix.exs`, let's fetch those:
 
-    $ mix deps.get
+```console
+$ mix deps.get
+```
 
 Now we need to verify the database connection details for the development and test environments in `config/` so the migrator and tests can run properly. Then run the following to create the database:
 
-    $ mix ecto.setup
+```console
+$ mix ecto.setup
+```
 
 Let's run the tests to make sure our new authentication system works as expected.
 
-    $ mix test
+```console
+$ mix test
+```
 
-And finally, let's start our phoenix server and try it out.
+And finally, let's start our Phoenix server and try it out.
 
-    $ mix phx.server
+```console
+$ mix phx.server
+```
 
-## Developer Responsibilities
+## Developer responsibilities
 
-Since phoenix generates this code into your application instead of building these modules into Phoenix itself, you now have complete freedom to modify the authentication system so it works best with your use case. The one caveat with using a generated authentication system is it will not be updated after it's been generated. Therefore as improvements are made to the output of `mix phx.gen.auth`, it becomes your responsibility to determine if these changes need to be ported into your application. Security-related and other important improvements will be explicitly and clearly marked in CHANGELOG and upgrade notes.
+Since Phoenix generates this code into your application instead of building these modules into Phoenix itself, you now have complete freedom to modify the authentication system so it works best with your use case. The one caveat with using a generated authentication system is it will not be updated after it's been generated. Therefore as improvements are made to the output of `mix phx.gen.auth`, it becomes your responsibility to determine if these changes need to be ported into your application. Security-related and other important improvements will be explicitly and clearly marked in the `CHANGELOG.md` file and upgrade notes.
 
-## Generated Code
+## Generated code
 
 The following are notes about the generated authentication system.
 
@@ -40,7 +50,7 @@ The password hashing mechanism defaults to `bcrypt` for Unix systems and `pbkdf2
 
 ### Forbidding access
 
-The generated code ships with an auth module with a handful of plugs that fetch the current user, require authentication and so on. For instance, in an app named Demo which had `mix phx.gen.auth Accounts User users` run on it, you will find a module named `DemoWeb.UserAuth` with plugs such as:
+The generated code ships with an authentication module with a handful of plugs that fetch the current user, require authentication and so on. For instance, in an app named Demo which had `mix phx.gen.auth Accounts User users` run on it, you will find a module named `DemoWeb.UserAuth` with plugs such as:
 
   * `fetch_current_user` - fetches the current user information if available
   * `require_authenticated_user` - must be invoked after `fetch_current_user` and requires that a current user exists and is authenticated
@@ -60,19 +70,21 @@ All sessions and tokens are tracked in a separate table. This allows you to trac
 
 Note that whenever the password changes (either via reset password or directly), all tokens are deleted and the user has to log in again on all devices.
 
-### Enumeration attacks
+### User Enumeration attacks
 
-An enumeration attack allows an attacker to enumerate all emails registered in the application. The generated authentication code protects against enumeration attacks on all endpoints, except in the registration and update email forms. If your application is really sensitive to enumeration attacks, you need to implement your own registration workflow, which tends to be very different from the workflow for most applications.
+A user enumeration attack allows an attacker to enumerate all emails registered in the application. For example, if trying to log in with a registered email and a wrong password returns a different error than trying to log in with an email that was never registered, an attacker could use this discrepency to find out which emails have accounts.
+
+The generated authentication code protects against enumeration attacks on all endpoints, except in the registration and update email forms. If your application is really sensitive to enumeration attacks, you need to implement your own registration workflow, which tends to be very different from the workflow for most applications.
 
 ### Case sensitiveness
 
 The email lookup is made to be case insensitive. Case insensitive lookups are the default in MySQL and MSSQL but use the [`citext` extension in PostgreSQL](https://www.postgresql.org/docs/current/citext.html).
 
-Note `citext` is part of Postgres itself and is bundled with it in most operating systems and package managers. `mix phx.gen.auth` takes care of creating the extension and no extra work is necessary in the majority of cases. If by any chance your package manager splits `citext` into a separate package, you will get an error while migrating and you can most likely solve it by installing the `postgres-contrib` package.
+Note `citext` is part of PostgreSQL itself and is bundled with it in most operating systems and package managers. `mix phx.gen.auth` takes care of creating the extension and no extra work is necessary in the majority of cases. If by any chance your package manager splits `citext` into a separate package, you will get an error while migrating and you can most likely solve it by installing the `postgres-contrib` package.
 
 ### Concurrent tests
 
-The generated tests run concurrently if you are using a database that supports concurrent tests (Postgres).
+The generated tests run concurrently if you are using a database that supports concurrent tests, which is the case of PostgreSQL.
 
 ## Additional resources
 
@@ -80,8 +92,8 @@ The following links have more information regarding the motivation and design of
 
   * José Valim's blog post - [An upcoming authentication solution for Phoenix](https://dashbit.co/blog/a-new-authentication-solution-for-phoenix)
   * The [original `phx_gen_auth` repo][phx_gen_auth repo] (for Phoenix 1.5 applications) - This is a great resource to see discussions around decisions that have been made in earlier versions of the project.
-  * [Original pull request on bare phoenix app][auth pr]
+  * [Original pull request on bare Phoenix app][auth PR]
   * [Original design spec](https://github.com/dashbitco/mix_phx_gen_auth_demo/blob/auth/README.md)
 
 [phx_gen_auth repo]: https://github.com/aaronrenner/phx_gen_auth
-[auth pr]: https://github.com/dashbitco/mix_phx_gen_auth_demo/pull/1
+[auth PR]: https://github.com/dashbitco/mix_phx_gen_auth_demo/pull/1
diff --git a/guides/contexts.md b/guides/contexts.md
index 52a53fa9e..ebe525317 100644
--- a/guides/contexts.md
+++ b/guides/contexts.md
@@ -378,7 +378,8 @@ Next, let's expose our new feature to the web by adding the credentials input to
 +   <% end %>
 + </div>
 
-  <%= submit "Submit" %>
+  <div>
+    <%= submit "Save" %>
 ```
 
 We used `Phoenix.HTML`'s `inputs_for` function to add an associations nested fields within the parent form. Within the nested inputs, we rendered our credential's email field and included the `label` and `error_tag` helpers just like our other inputs.
diff --git a/guides/deployment/releases.md b/guides/deployment/releases.md
index 94ea183bd..c83643f95 100644
--- a/guides/deployment/releases.md
+++ b/guides/deployment/releases.md
@@ -172,7 +172,7 @@ FROM node:15.7.0-alpine3.10 as assets
 
 # install build dependencies
 RUN --mount=type=cache,sharing=locked,target=/var/cache/apk \
-    apk add build-base python
+    apk add build-base python3
 
 # prepare build dir
 WORKDIR /app
diff --git a/guides/routing.md b/guides/routing.md
index dc44ac545..e29b46a31 100644
--- a/guides/routing.md
+++ b/guides/routing.md
@@ -160,7 +160,7 @@ This is significant because we can use the `page_path` function in a template to
 <%= link "Welcome Page!", to: Routes.page_path(@conn, :index) %>
 ```
 
-The reason we can use `Routes.page_path` instead of the full `HelloWeb.Router.Helpers.page_path` name is because `HelloWeb.Router.Helpers` is aliased as `Routes` by default in the `view/0` block defined inside `lib/hello_web.ex`. This definition is made available to our templates through `use HelloWeb, :view`.
+The reason we can use `Routes.page_path` instead of the full `HelloWeb.Router.Helpers.page_path` name is because `HelloWeb.Router.Helpers` is aliased as `Routes` by default in the `view_helpers/0` block defined inside `lib/hello_web.ex`. This definition is made available to our templates through `use HelloWeb, :view`.
 
 We can, of course, use `HelloWeb.Router.Helpers.page_path(@conn, :index)` instead, but the convention is to use the aliased version for conciseness. Note that the alias is only set automatically for use in views, controllers and templates - outside these you need either the full name, or to alias it yourself inside the module definition with `alias HelloWeb.Router.Helpers, as: Routes`.
 
diff --git a/installer/lib/mix/tasks/phx.new.ex b/installer/lib/mix/tasks/phx.new.ex
index a0af65c4b..bdd04df91 100644
--- a/installer/lib/mix/tasks/phx.new.ex
+++ b/installer/lib/mix/tasks/phx.new.ex
@@ -106,7 +106,8 @@ defmodule Mix.Tasks.Phx.New do
              app: :string, module: :string, web_module: :string,
              database: :string, binary_id: :boolean, html: :boolean,
              gettext: :boolean, umbrella: :boolean, verbose: :boolean,
-             live: :boolean, dashboard: :boolean, install: :boolean]
+             live: :boolean, dashboard: :boolean, install: :boolean,
+             prefix: :string]
 
   @impl true
   def run([version]) when version in ~w(-v --version) do
diff --git a/installer/lib/phx_new/generator.ex b/installer/lib/phx_new/generator.ex
index 420d0a822..49a2fb6d0 100644
--- a/installer/lib/phx_new/generator.ex
+++ b/installer/lib/phx_new/generator.ex
@@ -264,7 +264,8 @@ defmodule Phx.New.Generator do
     config :#{binding[:app_name]}, #{binding[:app_module]}.Repo,
       # ssl: true,
       url: database_url,
-      pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10")
+      pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
+      socket_options: [:inet6]
     """)
   end
 
diff --git a/lib/mix/phoenix/schema.ex b/lib/mix/phoenix/schema.ex
index cadc130e6..775930da6 100644
--- a/lib/mix/phoenix/schema.ex
+++ b/lib/mix/phoenix/schema.ex
@@ -35,7 +35,8 @@ defmodule Mix.Phoenix.Schema do
             route_helper: nil,
             migration_module: nil,
             fixture_unique_functions: %{},
-            fixture_params: %{}
+            fixture_params: %{},
+            prefix: nil
 
   @valid_types [
     :integer,
@@ -136,7 +137,9 @@ defmodule Mix.Phoenix.Schema do
       generate?: generate?,
       migration_module: migration_module(),
       fixture_unique_functions: fixture_unique_functions,
-      fixture_params: fixture_params(attrs, fixture_unique_functions)}
+      fixture_params: fixture_params(attrs, fixture_unique_functions),
+      prefix: opts[:prefix]
+    }
   end
 
   @doc """
diff --git a/lib/mix/tasks/phx.gen.auth.ex b/lib/mix/tasks/phx.gen.auth.ex
index fdb975ee9..c9422ba25 100644
--- a/lib/mix/tasks/phx.gen.auth.ex
+++ b/lib/mix/tasks/phx.gen.auth.ex
@@ -82,7 +82,8 @@ defmodule Mix.Tasks.Phx.Gen.Auth do
   alias Mix.Tasks.Phx.Gen.Auth.{HashingLibrary, Injector, Migration}
 
   @switches [web: :string, binary_id: :boolean, hashing_lib: :string,
-             table: :string, merge_with_existing_context: :boolean]
+             table: :string, merge_with_existing_context: :boolean,
+             prefix: :string]
 
   @doc false
   def run(args, test_opts \\ []) do
diff --git a/lib/mix/tasks/phx.gen.context.ex b/lib/mix/tasks/phx.gen.context.ex
index 839c51dba..2193d6561 100644
--- a/lib/mix/tasks/phx.gen.context.ex
+++ b/lib/mix/tasks/phx.gen.context.ex
@@ -80,7 +80,7 @@ defmodule Mix.Tasks.Phx.Gen.Context do
 
   @switches [binary_id: :boolean, table: :string, web: :string,
              schema: :boolean, context: :boolean, context_app: :string,
-             merge_with_existing_context: :boolean]
+             merge_with_existing_context: :boolean, prefix: :string]
 
   @default_opts [schema: true, context: true]
 
diff --git a/lib/mix/tasks/phx.gen.schema.ex b/lib/mix/tasks/phx.gen.schema.ex
index f3c4ec536..627f7173e 100644
--- a/lib/mix/tasks/phx.gen.schema.ex
+++ b/lib/mix/tasks/phx.gen.schema.ex
@@ -103,7 +103,7 @@ defmodule Mix.Tasks.Phx.Gen.Schema do
   alias Mix.Phoenix.Schema
 
   @switches [migration: :boolean, binary_id: :boolean, table: :string,
-             web: :string, context_app: :string]
+             web: :string, context_app: :string, prefix: :string]
 
   @doc false
   def run(args) do
diff --git a/lib/phoenix/presence.ex b/lib/phoenix/presence.ex
index f9d5a759d..755a58b83 100644
--- a/lib/phoenix/presence.ex
+++ b/lib/phoenix/presence.ex
@@ -63,10 +63,10 @@ defmodule Phoenix.Presence do
         end
       end
 
-  In the example above, the current presence information for
-  the socket's topic is pushed to the client as a `"presence_state"` event.
-  Next, `Presence.track` is used to register this channel's process as a
+  In the example above, `Presence.track` is used to register this channel's process as a
   presence for the socket's user ID, with a map of metadata.
+  Next, the current presence information for
+  the socket's topic is pushed to the client as a `"presence_state"` event.
 
   Finally, a diff of presence join and leave events will be sent to the
   client as they happen in real-time with the "presence_diff" event.
diff --git a/lib/phoenix/router/helpers.ex b/lib/phoenix/router/helpers.ex
index 1fdd30d02..fa3041e01 100644
--- a/lib/phoenix/router/helpers.ex
+++ b/lib/phoenix/router/helpers.ex
@@ -345,7 +345,7 @@ defmodule Phoenix.Router.Helpers do
   """
   def raise_route_error(mod, fun, arity, action, routes, params) do
     cond do
-      not Keyword.has_key?(routes, action) ->
+      is_atom(action) and not Keyword.has_key?(routes, action) ->
         "no action #{inspect action} for #{inspect mod}.#{fun}/#{arity}"
         |> invalid_route_error(fun, routes)
 
diff --git a/priv/templates/phx.gen.auth/confirmation_controller.ex b/priv/templates/phx.gen.auth/confirmation_controller.ex
index ea9728ca2..e7d00ff3e 100644
--- a/priv/templates/phx.gen.auth/confirmation_controller.ex
+++ b/priv/templates/phx.gen.auth/confirmation_controller.ex
@@ -15,7 +15,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
       )
     end
 
-    # Regardless of the outcome, show an impartial success/error message.
+    # In order to prevent user enumeration attacks, regardless of the outcome, show an impartial success/error message.
     conn
     |> put_flash(
       :info,
diff --git a/priv/templates/phx.gen.auth/reset_password_controller.ex b/priv/templates/phx.gen.auth/reset_password_controller.ex
index 74c21497e..9c8fb502d 100644
--- a/priv/templates/phx.gen.auth/reset_password_controller.ex
+++ b/priv/templates/phx.gen.auth/reset_password_controller.ex
@@ -17,7 +17,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
       )
     end
 
-    # Regardless of the outcome, show an impartial success/error message.
+    # In order to prevent user enumeration attacks, regardless of the outcome, show an impartial success/error message.
     conn
     |> put_flash(
       :info,
diff --git a/priv/templates/phx.gen.auth/session_controller.ex b/priv/templates/phx.gen.auth/session_controller.ex
index 84396b103..09264334d 100644
--- a/priv/templates/phx.gen.auth/session_controller.ex
+++ b/priv/templates/phx.gen.auth/session_controller.ex
@@ -14,6 +14,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
     if <%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>_by_email_and_password(email, password) do
       <%= inspect schema.alias %>Auth.log_in_<%= schema.singular %>(conn, <%= schema.singular %>, <%= schema.singular %>_params)
     else
+      # In order to prevent user enumeration attacks, don't disclose whether the email is registered.
       render(conn, "new.html", error_message: "Invalid email or password")
     end
   end
diff --git a/priv/templates/phx.gen.schema/migration.exs b/priv/templates/phx.gen.schema/migration.exs
index 8cdb2630a..34a91963f 100644
--- a/priv/templates/phx.gen.schema/migration.exs
+++ b/priv/templates/phx.gen.schema/migration.exs
@@ -2,7 +2,7 @@ defmodule <%= inspect schema.repo %>.Migrations.Create<%= Macro.camelize(schema.
   use <%= inspect schema.migration_module %>
 
   def change do
-    create table(:<%= schema.table %><%= if schema.binary_id do %>, primary_key: false<% end %>) do
+    create table(:<%= schema.table %><%= if schema.binary_id do %>, primary_key: false<% end %><%= if schema.prefix do %>, prefix: :<%= schema.prefix %><% end %>) do
 <%= if schema.binary_id do %>      add :id, :binary_id, primary_key: true
 <% end %><%= for {k, v} <- schema.attrs do %>      add <%= inspect k %>, <%= inspect Mix.Phoenix.Schema.type_for_migration(v) %><%= schema.migration_defaults[k] %>
 <% end %><%= for {_, i, _, s} <- schema.assocs do %>      add <%= inspect(i) %>, references(<%= inspect(s) %>, on_delete: :nothing<%= if schema.binary_id do %>, type: :binary_id<% end %>)
diff --git a/priv/templates/phx.gen.schema/schema.ex b/priv/templates/phx.gen.schema/schema.ex
index ea7e44f03..63a19d420 100644
--- a/priv/templates/phx.gen.schema/schema.ex
+++ b/priv/templates/phx.gen.schema/schema.ex
@@ -1,7 +1,8 @@
 defmodule <%= inspect schema.module %> do
   use Ecto.Schema
   import Ecto.Changeset
-<%= if schema.binary_id do %>
+<%= if schema.prefix do %>
+  @schema_prefix :<%= schema.prefix %><% end %><%= if schema.binary_id do %>
   @primary_key {:id, :binary_id, autogenerate: true}
   @foreign_key_type :binary_id<% end %>
   schema <%= inspect schema.table %> do


Test patch:
diff --git a/test/mix/tasks/phx.gen.schema_test.exs b/test/mix/tasks/phx.gen.schema_test.exs
index 35598072d..caab17f49 100644
--- a/test/mix/tasks/phx.gen.schema_test.exs
+++ b/test/mix/tasks/phx.gen.schema_test.exs
@@ -258,6 +258,21 @@ defmodule Mix.Tasks.Phx.Gen.SchemaTest do
     end
   end
 
+  test "generates schema and migration with prefix", config do
+    in_tmp_project config.test, fn ->
+      Gen.Schema.run(~w(Blog.Post posts title --prefix cms))
+
+      assert_file "lib/phoenix/blog/post.ex", fn file ->
+        assert file =~ "@schema_prefix :cms"
+      end
+
+      assert [migration] = Path.wildcard("priv/repo/migrations/*_create_posts.exs")
+      assert_file migration, fn file ->
+        assert file =~ "create table(:posts, prefix: :cms) do"
+      end
+    end
+  end
+
   test "skips migration with --no-migration option", config do
     in_tmp_project config.test, fn ->
       Gen.Schema.run(~w(Blog.Post posts --no-migration))