Giter Site home page Giter Site logo

danschultzer / pow Goto Github PK

View Code? Open in Web Editor NEW
1.5K 34.0 143.0 2.13 MB

Robust, modular, and extendable user authentication system

Home Page: https://powauth.com

License: MIT License

Elixir 99.98% HTML 0.02%
phoenix authentication authorization user-management elixir

pow's Introduction

Pow

Github CI hexdocs.pm hex.pm

Pow is a robust, modular, and extendable authentication and user management solution for Phoenix and Plug-based apps.

Features

Installation

Add Pow to your list of dependencies in mix.exs:

defp deps do
  [
    # ...
    {:pow, "~> 1.0.37"}
  ]
end

Run mix deps.get to install it.

Getting started

Phoenix app

Umbrella project: Check out the umbrella project guide.

Install the necessary files:

mix pow.install

This will add the following files to your app:

LIB_PATH/users/user.ex
PRIV_PATH/repo/migrations/TIMESTAMP_create_users.ex

And also update the following files:

config/config.exs
WEB_PATH/endpoint.ex
WEB_PATH/router.ex

Run migrations with mix setup, start the server with mix phx.server, and you can now visit http://localhost:4000/registration/new to create a user.

Modify templates

By default, Pow exposes as few files as possible.

If you wish to modify the templates, you can generate them using:

mix pow.phoenix.gen.templates

This will also add web_module: MyAppWeb to the configuration in config/config.exs.

Extensions

Pow is made so it's easy to extend the functionality with your own complimentary library. The following extensions are included in this library:

Check out the "Other libraries" section for other extensions.

Add extensions support

To keep it easy to understand and configure Pow, you'll have to enable the extensions yourself.

Let's install the PowResetPassword and PowEmailConfirmation extensions.

First, install extension migrations by running:

mix pow.extension.ecto.gen.migrations --extension PowResetPassword --extension PowEmailConfirmation

Then run the migrations with mix ecto.migrate. Now, update config/config.ex with the :extensions and :controller_callbacks key:

config :my_app, :pow,
  user: MyApp.Users.User,
  repo: MyApp.Repo,
  extensions: [PowResetPassword, PowEmailConfirmation],
  controller_callbacks: Pow.Extension.Phoenix.ControllerCallbacks

Update LIB_PATH/users/user.ex with the extensions:

defmodule MyApp.Users.User do
  use Ecto.Schema
  use Pow.Ecto.Schema
  use Pow.Extension.Ecto.Schema,
    extensions: [PowResetPassword, PowEmailConfirmation]

  # ...

  def changeset(user_or_changeset, attrs) do
    user_or_changeset
    |> pow_changeset(attrs)
    |> pow_extension_changeset(attrs)
  end
end

Add Pow extension routes to WEB_PATH/router.ex:

defmodule MyAppWeb.Router do
  use MyAppWeb, :router
  use Pow.Phoenix.Router
  use Pow.Extension.Phoenix.Router,
    extensions: [PowResetPassword, PowEmailConfirmation]

  # ...

  scope "/" do
    pipe_through :browser

    pow_routes()
    pow_extension_routes()
  end

  # ...
end

Modify extension templates

Templates for extensions can be generated with:

mix pow.extension.phoenix.gen.templates --extension PowResetPassword --extension PowEmailConfirmation

Please follow the instructions in "Modify templates" to ensure that your custom templates will be used.

Mailer support

Many extensions require a mailer to have been set up. Let's create a mailer mock module in WEB_PATH/mails/pow/mailer.ex:

defmodule MyAppWeb.Pow.Mailer do
  use Pow.Phoenix.Mailer
  require Logger

  def cast(%{user: user, subject: subject, text: text, html: html, assigns: _assigns}) do
    # Build email struct to be used in `process/1`

    %{to: user.email, subject: subject, text: text, html: html}
  end

  def process(email) do
    # Send email

    Logger.debug("E-mail sent: #{inspect email}")
  end
end

Update config/config.ex with :mailer_backend key:

config :my_app, :pow,
  # ...
  mailer_backend: MyAppWeb.Pow.Mailer

This mailer module will only output the mail to your log, so you can e.g. try out the reset password and email confirmation links. You should integrate the Pow mailer with your actual mailer system. For Swoosh or Bamboo integration, check out the Configuring mailer guide.

Modify mailer templates

Generate the template files:

mix pow.extension.phoenix.mailer.gen.templates --extension PowResetPassword --extension PowEmailConfirmation

This will generate template files in the WEB_PATH/mails/ directory. This will also add the necessary mail/0 macro to WEB_PATH/my_app_web.ex and update the pow config with web_mailer_module: MyAppWeb.

Configuration

Pow is built to be modular, and easy to configure. The configuration is passed to function calls as well as plug options, and they will take priority over any environment configuration. It's ideal in case you got an umbrella app with multiple separate user domains.

The easiest way to use Pow with Phoenix is to use a :otp_app in function calls and set the app environment configuration. It will keep a persistent fallback configuration that you configure in one place.

Module groups

Pow has three main groups of modules that each can be used individually, or in conjunction with each other:

Pow.Plug

This group will handle the plug connection. The configuration will be assigned to conn.private[:pow_config] and passed through the controller to the users' context module. The Plug module has functions to authenticate, create, update, and delete users, and will generate/renew the session automatically.

Pow.Ecto

This group contains all modules related to the Ecto based user schema and context. By default, Pow will use the Pow.Ecto.Context module to authenticate, create, update and delete users with lookups to the database. However, it's straightforward to extend or write your custom user context. You can do this by setting the :users_context configuration key.

Pow.Phoenix

This group contains the controllers and templates for Phoenix. You only need to set the (session) plug in endpoint.ex and add the routes to router.ex. Templates are not generated by default, instead, the compiled templates in Pow are used. You can generate the templates used by running mix pow.phoenix.gen.templates. You can also customize flash messages and callback routes by creating your own using :messages_backend and :routes_backend.

The registration and session controllers can be changed with your customized versions too, but since the routes are built on compile time, you'll have to set them up in router.ex with :pow namespace. For minor pre/post-processing of requests, you can use the :controller_callbacks option. It exists to make it easier to modify flow with extensions (e.g., send a confirmation email upon user registration).

Pow.Extension

This module helps build extensions for Pow. There're three extension mix tasks to generate Ecto migrations and phoenix templates.

mix pow.extension.ecto.gen.migrations
mix pow.extension.phoenix.gen.templates
mix pow.extension.phoenix.mailer.gen.templates

Authorization plug

Pow ships with a session plug module. You can easily switch it out with a different one. As an example, here's how you do that with Phoenix.Token:

defmodule MyAppWeb.Pow.Plug do
  use Pow.Plug.Base

  @session_key :pow_user_token
  @salt "user salt"
  @max_age 86400

  def fetch(conn, config) do
    conn  = Plug.Conn.fetch_session(conn)
    token = Plug.Conn.get_session(conn, @session_key)

    MyAppWeb.Endpoint
    |> Phoenix.Token.verify(@salt, token, max_age: @max_age)
    |> maybe_load_user(conn)
  end

  defp maybe_load_user({:ok, user_id}, conn), do: {conn, MyApp.Repo.get(User, user_id)}
  defp maybe_load_user({:error, _any}, conn), do: {conn, nil}

  def create(conn, user, config) do
    token = Phoenix.Token.sign(MyAppWeb.Endpoint, @salt, user.id)
    conn  =
      conn
      |> Plug.Conn.fetch_session()
      |> Plug.Conn.put_session(@session_key, token)

    {conn, user}
  end

  def delete(conn, config) do
    conn
    |> Plug.Conn.fetch_session()
    |> Plug.Conn.delete_session(@session_key)
  end
end

defmodule MyAppWeb.Endpoint do
  # ...

  plug MyAppWeb.Pow.Plug, otp_app: :my_app
end

Ecto changeset

The user module has a fallback changeset/2 function. If you want to add custom validations, you can use the pow_changeset/2 function like so:

defmodule MyApp.Users.User do
  use Ecto.Schema
  use Pow.Ecto.Schema

  schema "users" do
    field :custom, :string

    pow_user_fields()

    timestamps()
  end

  def changeset(user_or_changeset, attrs) do
    user_or_changeset
    |> pow_changeset(attrs)
    |> Ecto.Changeset.cast(attrs, [:custom])
    |> Ecto.Changeset.validate_required([:custom])
  end
end

Phoenix controllers

Controllers in Pow are very slim and consists of just one Pow.Plug function call with response functions. If you wish to change the flow of the Pow.Phoenix.RegistrationController and Pow.Phoenix.SessionController, the best way is to create your own and modify router.ex.

However, to make it easier to integrate extension, you can add callbacks to the controllers that do some light pre/post-processing of the request:

defmodule MyCustomExtension.Phoenix.ControllerCallbacks do
  use Pow.Extension.Phoenix.ControllerCallbacks.Base

  def before_respond(Pow.Phoenix.RegistrationController, :create, {:ok, user, conn}, _config) do
    # send email

    {:ok, user, conn}
  end
end

You can add functions for before_process/4 (before the action happens) and before_respond/4 (before parsing the results from the action).

Testing with authenticated users

To test with authenticated users in your controller tests, you just have to assign the user to the conn in your setup callback:

setup %{conn: conn} do
  user = %User{email: "[email protected]"}
  conn = Pow.Plug.assign_current_user(conn, user, otp_app: :my_app)

  {:ok, conn: conn}
end

I18n

All templates can be generated and modified to use your Gettext module.

For flash messages, you can create the following module:

defmodule MyAppWeb.Pow.Messages do
  use Pow.Phoenix.Messages
  use Pow.Extension.Phoenix.Messages,
    extensions: [PowResetPassword]

  import MyAppWeb.Gettext

  def user_not_authenticated(_conn), do: gettext("You need to sign in to see this page.")

  # Message functions for extensions has to be prepended with the snake cased
  # extension name. So the `email_has_been_sent/1` function from
  # `PowResetPassword` is written as `pow_reset_password_email_has_been_sent/1`
  # in your messages module.
  def pow_reset_password_email_has_been_sent(_conn), do: gettext("An email with reset instructions has been sent to you. Please check your inbox.")
end

Add messages_backend: MyAppWeb.Pow.Messages to your configuration. You can find all the messages in Pow.Phoenix.Messages and [Pow Extension].Phoenix.Messages.

Callback routes

You can customize callback routes by creating the following module:

defmodule MyAppWeb.Pow.Routes do
  use Pow.Phoenix.Routes
  use MyAppWeb, :verified_routes

  def after_sign_in_path(conn), do: ~p"/home"
end

Add routes_backend: MyAppWeb.Pow.Routes to your configuration. You can find all the routes in Pow.Phoenix.Routes.

Password hashing function

Pow.Ecto.Schema.Password is used to hash and verify with Pbkdf2. It's highly recommended to lower the iterations count in your test environment to speed up your tests:

config :pow, Pow.Ecto.Schema.Password, iterations: 1

You can change the password hashing function easily. For example, this is how you use comeonin with Argon2:

defmodule MyApp.Users.User do
  use Ecto.Schema
  use Pow.Ecto.Schema,
    password_hash_verify: {&Argon2.hash_pwd_salt/1,
                           &Argon2.verify_pass/2}

  # ...
end

Current user and sign out link

You can use Pow.Plug.current_user/1 to fetch the current user from the connection.

This can be used to show the sign in or sign out links in your Phoenix template:

<.link :if={Pow.Plug.current_user(@conn)} href={~p"/session"} method="delete">Sign out</.link>
<.link :if={is_nil Pow.Plug.current_user(@conn)} navigate={~p"/registration/new"}>Registration</.link>
<.link :if={is_nil Pow.Plug.current_user(@conn)} navigate={~p"/session/new"}>Sign In</.link>

The current user can also be fetched by using the template assigns set in the configuration with :current_user_assigns_key (defaults to @current_user).

Plugs

Pow.Plug.Session

Enables session-based authorization. The user struct will be collected from a cache store through a GenServer using a unique token generated for the session. The token will be reset every time the authorization level changes (handled by Pow.Plug) or after a certain interval (default 15 minutes).

The user struct fetched can be out of sync with the database if the row in the database is updated by actions outside Pow. In this case, it's recommended to add a plug that reloads the user struct and reassigns it to the connection.

Custom metadata can be set for the session by assigning a private :pow_session_metadata key in the conn. Read the Pow.Plug.Session module docs for more details.

Cache store

By default Pow.Store.Backend.EtsCache is started automatically and can be used in development and test environment.

For a production environment, you should use a distributed, persistent cache store. Pow makes this easy with Pow.Store.Backend.MnesiaCache. To start MnesiaCache in your Phoenix app, add it to your application.ex supervisor:

defmodule MyApp.Application do
  use Application

  def start(_type, _args) do
    children = [
      MyApp.Repo,
      MyAppWeb.Endpoint,
      Pow.Store.Backend.MnesiaCache
      # # Or in a distributed system:
      # {Pow.Store.Backend.MnesiaCache, extra_db_nodes: {Node, :list, []}},
      # Pow.Store.Backend.MnesiaCache.Unsplit # Recover from netsplit
    ]

    opts = [strategy: :one_for_one, name: MyAppWeb.Supervisor]
    Supervisor.start_link(children, opts)
  end

  # ...
end

Update config/config.ex with :cache_store_backend key:

config :my_app, :pow,
  # ...
  cache_store_backend: Pow.Store.Backend.MnesiaCache

Remember to add :mnesia to your :extra_applications so it'll be available for your release build. Mnesia will write files to the current working directory. The path can be changed with config :mnesia, dir: '/path/to/dir'.

The MnesiaCache requires write access. If you've got a read-only file system you should take a look at the Redis cache backend store guide.

Pow.Plug.RequireAuthenticated

Will halt connection if no current user is not present in assigns. Expects an :error_handler option.

Pow.Plug.RequireNotAuthenticated

Will halt connection if a current user is present in assigns. Expects an :error_handler option.

Pow security practices

See security practices.

Other libraries

PowAssent - Multi-provider support for Pow with strategies for Twitter, Github, Google, Facebook and more

Contributing

Please read CONTRIBUTING.md.

LICENSE

(The MIT License)

Copyright (c) 2018-2019 Dan Schultzer & the Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

pow's People

Contributors

abartier avatar adamzapasnik avatar cdvv7788 avatar danschultzer avatar dweremeichik avatar edjroot avatar holsee avatar humancopy avatar immortalin avatar joelbyler avatar joepstender avatar jpinnix avatar jung-hunsoo avatar landonschropp avatar lurnid avatar maartenvanvliet avatar matthewford avatar mreishus avatar popo63301 avatar prehnra avatar rafaeliga avatar ricardotrindade avatar richjdsmith avatar rudolfb avatar ruslanlevond avatar skylerwshaw avatar sltong avatar tomasz-buchta avatar veverkap avatar zackkitzmiller avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pow's Issues

Template generation broken

Running mix pow.phoenix.gen.templates or mix pow.phoenix.gen.templates --context-app Ss gives the error:

* creating lib/ss_web/views/pow/registration_view.ex
** (ArgumentError) argument error
    :erlang.binary_to_existing_atom("edit", :utf8)
    (elixir) lib/string.ex:2089: String.to_existing_atom/1
    (elixir) lib/enum.ex:1294: Enum."-map/2-lists^map/1-0-"/2
    (elixir) lib/enum.ex:1294: Enum."-map/2-lists^map/1-0-"/2
    lib/mix/pow/phoenix.ex:59: Mix.Pow.Phoenix.create_templates/4
    (elixir) lib/enum.ex:737: Enum."-each/2-lists^foreach/1-0-"/2
    (elixir) lib/enum.ex:737: Enum.each/2
    lib/mix/tasks/phoenix/pow.phoenix.gen.templates.ex:41: Mix.Tasks.Pow.Phoenix.Gen.Templates.create_template_files/1

It does generate lib/ss_web/views/pow/registration_view.ex, but that is all.

using custom session and registration controller with extensions

Hi!

I wonder if there are any additional changes required to make custom controllers work with extensions like persistent session plug.

However, to make it easier to integrate extension, you can add callbacks to the controllers that do some light pre/post-processing of the request:

From https://github.com/danschultzer/pow#phoenix-controllers, seems to imply that using custom controllers breaks Pow.Extension.Phoenix.ControllerCallbacks, that is, there are no traces of any function in Pow.Extension.Phoenix.ControllerCallbacks being called during login/logout when using custom controllers.

Replace placeholder in error message

When a user submits a password that does not meet the minimum characters, they currently get the following message: "should be at least %{count} character(s)".

Ecto.Changeset.traverse_errors/2 can be used to insert the count into the error message. The example function in the docs specifically addresses this situation.

I'm not sure where the function to update the error message should be added, but it would improve the error messages to the user.

Override default configuration values; password_min_length

There's a default setting of password_min_length: 10. And I'd like to redefine it to 8 because it's widely accepted. I don't want to bother or enforce the inconveniences to my users.

How can I redefine some default configurations like password_min_length? Adding password_min_length: 8 in the config.exs didn't work.

Add :last_login_at and :last_login_ip to User struct.

Both :last_login_at and :last_login_ip attributes are useful when providing basic security protection.

Maybe :updated_at can be used in replace for :last_login_at though not proper. (for example, when user changed name or password).

Help with email confirmation flow in custom controller

I am fully loving pow so far but I am finding very hard to integrate or use with other libs due to the controller methods. When we try to implement a new flow its never easy because the custom controller methods lack guidance around how to to properly utilise these.

I had to create custom controller since I am using assigns in weird way in which I require them to generate the reg form and sign in forms. This is working, we now have a problem when it comes to email confirmation as this is not functional at all.

We manage to implement this based on a previous issue:

defmodule AppWeb.RegistrationController do
    use AppWeb, :controller
    alias PowEmailConfirmation.Phoenix.ControllerCallbacks, as: PowEmailConfirmationControllerCallbacks

    def new(conn, _params) do
      changeset = Pow.Plug.change_user(conn)
      form = create_form(App.Users.UserType, %App.Users.User{})

      render(conn, "new.html", changeset: changeset, form: form)
    end

    def create(conn, %{"user" => user_params}) do
      conn
      |> Pow.Plug.create_user(user_params)
      |> verify_confirmed()
    end

    defp verify_confirmed({:error, conn}), do: render(conn, "new.html")

    defp verify_confirmed({:ok, conn}) do
      user = Pow.Plug.current_user(conn)
  
      if confirmed?(user) do
        conn
        |> put_flash(:info, "Welcome!")
        |> redirect(to: Routes.page_path(conn, :index))
      else
        PowEmailConfirmationControllerCallbacks.send_confirmation_email(user, conn)
  
       {:ok, conn} = Pow.Plug.clear_authenticated_user(conn)
        # conn session has been reset and error can be returned
        render(conn, "new.html")
      end
    end
  
    defp confirmed?(%{email_confirmed_at: nil, email_confirmation_token: token}) when not is_nil(token), do: false
    defp confirmed?(_user), do: true
end

We mainly seem to be running in to issue around the expected return type. We have had to disable this feature for the time being as we are still in development. If there a better or easier way to pass assigns to Pow controllers ? Can you provide the best method to add or call the extension from here from the reg controller ?

The error we tend to see if the following: no function clause matching in AppWeb.RegistrationController.verify_confirmed/1 and this occurs on the following line: defp verify_confirmed({:error, conn}), do: render(conn, "new.html")

I like the following which is the initial example we went with as it provides a decent place to start building from:

defmodule AppWeb.RegistrationController do
    use AppWeb, :controller

    def new(conn, _params) do
      changeset = Pow.Plug.change_user(conn)
      form = create_form(App.Users.UserType, %App.Users.User{})
      render(conn, "new.html", changeset: changeset, form: form)
    end

    def create(conn, %{"user" => user_params}) do
      conn
      |> Pow.Plug.create_user(user_params)
      |> case do
        {:ok, user, conn} ->
          conn
          |> put_flash(:info, "Welcome!")
          |> redirect(to: Routes.page_path(conn, :index))

        {:error, changeset, conn} ->
          render(conn, "new.html", changeset: changeset)
      end
    end
end

Roadmap for 1.0

What are the goals for 1.0? What will it take to move from rc to 1.0?

mix pow.install Match Error - Pow phoenix 1.4 branch

Hello,

I'm trying to test pow in a new phoenix 1.4 app.
The mix task pow.install return this:


mix pow.install -r Powtest.Repo Accounts.User users
** (MatchError) no match of right hand side value: :undefined
    lib/pow.ex:9: Pow.dependency_vsn_match?/2
    lib/mix/pow/ecto/migration.ex:69: Mix.Pow.Ecto.Migration.source_repo_priv/1
    lib/mix/pow/ecto/migration.ex:15: Mix.Pow.Ecto.Migration.create_migration_files/3
    (elixir) lib/enum.ex:765: Enum."-each/2-lists^foreach/1-0-"/2
    (elixir) lib/enum.ex:765: Enum.each/2
    lib/mix/tasks/ecto/pow.ecto.install.ex:49: Mix.Tasks.Pow.Ecto.Install.maybe_run_gen_migration/2
    lib/mix/tasks/ecto/pow.ecto.install.ex:41: Mix.Tasks.Pow.Ecto.Install.run/1
    lib/mix/tasks/pow.install.ex:38: Mix.Tasks.Pow.Install.run_ecto_install/2
    lib/mix/tasks/pow.install.ex:31: Mix.Tasks.Pow.Install.run/1
    (mix) lib/mix/task.ex:316: Mix.Task.run_task/3
    (mix) lib/mix/cli.ex:79: Mix.CLI.run_task/2
    (elixir) lib/code.ex:767: Code.require_file/2

Can you provide a user.ex file and the typical migration pow required ?

Mnesia :bad_type error

Recently I changed the credential config from default ets to mnesia explained in the readme guide.

It has worked in dev, but error is popped out in prod. (Release made via Distillery and :mnesia is included in :extra_applications.

Any clue?

console

 9์›” 24 09:29:11 nohogu1 nohogu[4506]: Loading nohogu...
 9์›” 24 09:29:11 nohogu1 nohogu[4506]: Starting dependencies..
 9์›” 24 09:29:11 nohogu1 nohogu[4506]: Creating database if not exists...
 9์›” 24 09:29:11 nohogu1 nohogu[4506]: Running migrations...
 9์›” 24 09:29:12 nohogu1 nohogu[4506]: Success!
 9์›” 24 09:29:12 nohogu1 nohogu[4506]: 09:29:12.159 [info] Already up
 9์›” 24 09:29:14 nohogu1 nohogu[4506]: 09:29:14.948 [info] Running NohoguWeb.Endpoint with Cowboy using http://0.0.0.0:4000
 9์›” 24 09:29:14 nohogu1 nohogu[4506]: 09:29:14.994 [info] Application nohogu exited: Nohogu.Application.start(:normal, []) returned an error: shutdown: failed to start c
 9์›” 24 09:29:14 nohogu1 nohogu[4506]:     ** (EXIT) an exception was raised:
 9์›” 24 09:29:14 nohogu1 nohogu[4506]:         ** (CaseClauseError) no case clause matching: {:aborted, {:bad_type, Pow.Store.Backend.MnesiaCache, :disc_copies, :"nohogu@
 9์›” 24 09:29:14 nohogu1 nohogu[4506]:             (pow) lib/pow/store/backend/mnesia_cache.ex:144: Pow.Store.Backend.MnesiaCache.table_init/1
 9์›” 24 09:29:14 nohogu1 nohogu[4506]:             (pow) lib/pow/store/backend/mnesia_cache.ex:54: Pow.Store.Backend.MnesiaCache.init/1
 9์›” 24 09:29:14 nohogu1 nohogu[4506]:             (stdlib) gen_server.erl:374: :gen_server.init_it/2
 9์›” 24 09:29:14 nohogu1 nohogu[4506]:             (stdlib) gen_server.erl:342: :gen_server.init_it/6
 9์›” 24 09:29:14 nohogu1 nohogu[4506]:             (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
 9์›” 24 09:29:16 nohogu1 nohogu[4506]: {"Kernel pid terminated",application_controller,"{application_start_failure,nohogu,{{shutdown,{failed_to_start_child,'Elixir.Pow.St
 9์›” 24 09:29:16 nohogu1 nohogu[4506]: Kernel pid terminated (application_controller) ({application_start_failure,nohogu,{{shutdown,{failed_to_start_child,'Elixir.Pow.Sto
 9์›” 24 09:29:16 nohogu1 nohogu[4506]: [1B blob data]
 9์›” 24 09:29:16 nohogu1 nohogu[4506]: Crash dump is being written to: erl_crash.dump...done

config.ex

# Authentication
config :nohogu, :pow,
  user: Nohogu.Users.User,
  repo: Nohogu.Repo,
  web_module: NohoguWeb,
  web_mailer_module: NohoguWeb,
  mailer_backend: NohoguWeb.PowMailer,
	messages_backend: NohoguWeb.Pow.Messages,
	routes_backend: NohoguWeb.Pow.Routes,
	cache_store_backend: Pow.Store.Backend.MnesiaCache,
	session_store: {Pow.Store.CredentialsCache, ttl: :timer.minutes(60), namespace: "credentials"},
	session_ttl_renewal: :timer.minutes(30),
  extensions: [PowResetPassword, PowEmailConfirmation, PowPersistentSession],
  controller_callbacks: Pow.Extension.Phoenix.ControllerCallbacks

endpoint

  plug Plug.Session,
    store: :cookie,
    key: "_nohogu_key",
    signing_salt: "SOME_KEY"

  plug Pow.Plug.Session, otp_app: :nohogu

Use Redis for session cache?

We are deploying to Heroku which as I understand doesn't support mnesia?
Can you use redis with pow for session storage?

no route found for GET /registration/new error after Pow installation

I made a fresh phoenix 1.4 install and followed steps in readme file of Pow to install it:

  1. Added it as a dependency and made deps.get
  2. Modifies config file
  3. Modified Endpoint file
  4. Modified Router file

Tried to go to the localhost:4000/registration/new in the browser but got the error:
no route found for GET /registration/new (HelloWeb.Router)

If I make a command mix phx.routes in the console it gives me:

     pow_session_path  GET     /session/new        Pow.Phoenix.SessionController :new
     pow_session_path  POST    /session            Pow.Phoenix.SessionController :create
     pow_session_path  DELETE  /session            Pow.Phoenix.SessionController :delete
pow_registration_path  GET     /registration/edit  Pow.Phoenix.RegistrationController :edit
pow_registration_path  GET     /registration/new   Pow.Phoenix.RegistrationController :new
pow_registration_path  POST    /registration       Pow.Phoenix.RegistrationController :create
pow_registration_path  PATCH   /registration       Pow.Phoenix.RegistrationController :update
                       PUT     /registration       Pow.Phoenix.RegistrationController :update
pow_registration_path  DELETE  /registration       Pow.Phoenix.RegistrationController :delete
            page_path  GET     /                   HelloWeb.PageController :card_index: 

I also tried to access /session/new in the browser but got the same error.
What is wrong with my install?

My router file looks like this:

defmodule HelloWeb.Router do
  use HelloWeb, :router
  use Pow.Phoenix.Router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/" do
    pipe_through :browser

    pow_routes()
  end

  scope "/", HelloWeb do
    pipe_through :browser

    get "/", PageController, :index
  end

end

Override flash messages for email confirmation not working.

I'm trying to i18n the flash messages in PowEmailConfirmation, by adding custom functions in messages backend module NohoguWeb.Pow.Message and add messages_backend: NohoguWeb.Pow.Messages, in config.exs.

But it looks not working well.

Here's the codes:

defmodule NohoguWeb.Pow.Messages do
  use Pow.Phoenix.Messages
  use Pow.Extension.Phoenix.Messages,
    extensions: [PowResetPassword, PowEmailConfirmation, PowPersistentSession]

  import NohoguWeb.Gettext

  def user_not_authenticated(_conn), do: gettext("You need to sign in to see this page.")

  def pow_reset_password_email_has_been_sent(_conn), do: IO.inspect dgettext("pow", "An email with reset instructions has been sent to you. Please check your inbox.")

  def email_has_been_confirmed(_conn), do: IO.inspect dgettext("pow", "The email address has been confirmed.")
  def email_confirmation_failed(_conn), do: dgettext("pow", "The email address couldn't be confirmed.")
  def email_confirmation_required(_conn), do: IO.inspect dgettext("pow", "You'll need to confirm your e-mail before you can sign in. An e-mail confirmation link has been sent to you.")
end

IO.inspect is to leave the logs, but they didn't appear in the console log.

Any idea?

A detail guide of Controller callbacks.

My user registration process is register -> confirm email -> Create Userinfo record when confirmed.

To implement Creating Userinfo record when confirmed three approaches were made.

First I tried modifying Ecto changeset. But it didn't work since id is available yet, prepare_changes can't access User's id field.

Next I tried using Callback routes.

def after_registration_path(conn) do
  # This returns nil
  current_user = Pow.Plug.current_user(conn)
  # This didn't work.
  Myapp.Generals.create_userinfo(%{user_id: current_user.id})
  Routes.page_path(conn, :index)
end

It didn't work. Simply because conn doesn't have :current_user as it's not email confirmed yet.

Last, I'm trying ControllerCallbacks now. Since I can access user there, it seems to be working there. But I can't figure out where and how to configure callbacks. So can you explain more in the readme?

At present controller_callbacks: Pow.Extension.Phoenix.ControllerCallbacks is set in config. But it won't touch my custom callbacks. I can't sure that it can be replaced with my custom callbacks.

Disable registration routes

Hi!

I'm looking for a way to disable registration routes, as the app I'm building won't need them. I couldn't find any configuration option, so what's the suggested approach for this?

I tried changing pow_routes() in my router to this:

    scope "/", Pow.Phoenix, as: "pow" do
      resources "/session", SessionController, singleton: true, only: [:new, :create, :delete]
    end

But it forces me to import the session templates and overwrite them, as they use the registration path (which doesn't exist now).

Is there a better way to achieve this?

Thanks! ๐Ÿ˜„

Error generating extension templates

I was going through the readme trying things out and got the following error when I ran the command to generate the extension templates.

$ mix pow.extension.phoenix.gen.templates --extension PowResetPassword --extension PowEmailConfirmation
warning: found quoted keyword "test" but the quotes are not required. Note that keywords are always atoms, even when quoted, and quotes should only be used to introduce keywords with foreign characters in them
  mix.exs:62

* creating lib/my_app_web/views/pow_reset_password/reset_password_view.ex
** (ArgumentError) argument error
    :erlang.binary_to_existing_atom("edit", :utf8)
    (elixir) lib/string.ex:2169: String.to_existing_atom/1
    (elixir) lib/enum.ex:1314: Enum."-map/2-lists^map/1-0-"/2
    (elixir) lib/enum.ex:1314: Enum."-map/2-lists^map/1-0-"/2
    lib/mix/pow/phoenix.ex:59: Mix.Pow.Phoenix.create_templates/4
    (elixir) lib/enum.ex:765: Enum."-each/2-lists^foreach/1-0-"/2
    (elixir) lib/enum.ex:765: Enum.each/2
    (elixir) lib/enum.ex:765: Enum."-each/2-lists^foreach/1-0-"/2

Including user details in email templates

By default, reset_password.html.eex only exposes the @url assigns variable.

How would I go about also having the @user variable exposed so that I can customise my email templates? For example, I want to open my emails with Hi {user}, as opposed to just a generic Hi,?

Guidance appreciated.

Getting current active users.

We can get current active users from several places; phoenix channel, google analytics. But I think the real data can only get from credential store.

There's a similar fn Pow.Store.CredentialsCache.sessions/3, but this shows a list of sessions for a given user.

So, how about support fn which list up current active users? This is a fancy and unique fn, too!

Make confirmation optional?

Can we add a feature so you still get to use the confirmation flow (sends email) but confirmation is not required to proceed after registration?

Cannot confirm email by setting :email_confirmed_at.

In the readme of PowEmailConfirmation, manual email confirmation by setting up :email_confirmed_at is described.

But in my test seed it didn't work. I think :email_confirmed_at field is not casted in the changeset.

Seed codes are like this;

user_params = %{name: "na", email: "na@some_url.com", password: "abcd1234", confirm_password: "abcd1234", email_confirmed_at: DateTime.utc_now()}
{:ok, na_user} = Pow.Operations.create(user_params, otp_app: :myapp)

Fortunately, PowEmailConfirmation.Ecto.Context.confirm_email/2 is working as expected.

allow mapping password_hash to another field?

For those of us migrating from devise, we have encrypted_password as a field.

For most fields, I can do field :email, :string, [source: :other_field].

Think it would be possible to add in a config option for pow_fields() like pow_fields(password_hash: :encrypted_password?

mix pow.extension.ecto.gen.migrations silently fails

When I run mix pow.extension.ecto.gen.migrations --extension PowResetPassword or just mix pow.extension.ecto.gen.migrations with the following in config/config.exs, my project compiles, but then the Ecto migrations aren't generated.

# config/config.exs
...
config :golf, :pow,
  user: Golf.Accounts.User,
  repo: Golf.Repo,
  extensions: [PowResetPassword, PowPersistentSession]

Here is my branch: https://github.com/axelclark/golf/tree/pow

I'm using

{:ecto_sql, "~> 3.0"},
{:pow, "~> 1.0.0"}

WebAuthn and multi factor support

Add two factor support to Pow with at least OTP and FIDO U2F support.

Good primer for ensuring secure and useful two factor setup: https://medium.com/@stuartschechter/before-you-turn-on-two-factor-authentication-27148cc5b9a1

Edit: Here's some security considerations: https://shahmeeramir.com/4-methods-to-bypass-two-factor-authentication-2b0075d9eb5f


MFA auth

  • WebAuthn
  • OTP/TOTP
  • Recovery codes
  • E-mail/magic link
  • Device authorization (in app)

Process

In general the MFA authentication process will go like this:

User ID & password --> MFA authorization --> Signed in

OR as passwordless:

User ID --> MFA authorization --> Signed in

This latter option could also be all on the same page for some of the above methods. The MFA methods can also be used for the registration process.

There should be a controller action for handling 2FA auth, and probably one for handling registration with 2FA. Maybe one for managing 2FA methods.

WebAuthn links

https://webauthn.guide/
https://auth0.com/blog/web-authentication-webauthn-overview-demo-tool/


Suggested Ecto schema

There're two ways to go about this. Embedded or separate table. Separate table may make it easier to not require user id, but it could be that the user id should just be set to generated_id if developers wish to login without user id with a randomly generated id that will be stored with the authenticator.

field :type, :string
field :nickname, :string
field :settings, :map

WebAuthn use case

WebAuthn allows for no user id and can be used for single authentication.

The WebAuthn will store at minimum the following data:

{
  credential_id: "credential_id",
  cose_key: "cose_key"
}

For no user id setup, the user id used for the authenticator could be a randomly generated id that's stored in the authenticator schema.

TOTP use case

TOTP can only be used for 2FA. The data stored would be the following:

{
  issuer: "My Service",
  otp_secret: "secret",
  last_otp_at: "492039"
}

Install POW as Elixir app in Umbrella - not as Phoenix app

Ok forgive me, totally new at Phoenix and app dev in general so the obvious is not very obvious.

I have an Umbrella app with a db elixir app managing my repo.

I do not understand the ELixir/Phoenix relationship well enough yet and suffer major OCD - I am using Phoenix apps in my umbrella for an admin UI and my REST API and understand the sorta the need for 2 folders in a Phoenix app lib for App(business logic) and App_Web (presentation). Where my OCD kicks in overdrive is having to use a Phoenix app in my umbrella for an app that does not require a UI and therefore that App_Web folder Phoenix provides.

In my mind, Auth (POW) supports access through the phoenix rest api app to the business logic in all my umbrella apps and should stand alone. So I am trying to setup POW as an Elixir only app in the umbrella with mix new auth --module Auth --sup. I do not want Auth to be a Phoenix app that requires me to stare at the damn App-Web folder all day.

Maybe (likely) I am just plain wrong and do not get it yet.

In any case, reading what I can find in DuckDuckGo about POW and of course your git repo you mention using a plug instead of Phoenix but sadly only provide a getting started with a Phoenix app.

Can you help a brother out and provide an example of using POW in an umbrella Elixir app using a Plug? I am going to keep digging and will probably hack it out but will likely be wrong, wrong, wrong.

FWIW I am also using Triplex (multi-tenant by schema) in my elixir dbapp and have the following umbrella setup I am reasoning through:

  • accounts: (Elixir app managing business logic for all accounts ie Persons, Companies, Patients, Doctors - Triplex tenant logic lives here)
  • api_rest: (Phoenix app manages api connections)
  • api_graphql (Phoenix/Absinthe app manages gql connections)
  • auth (Elixir app manages all authentication using POW I hope)
  • db (Elixir app managing migrations and schemas for all persisted entities)
  • inventory (Elixir app managing the business logic for inventory control)
  • ... (other Elixir apps managing the different business contexts in my app)

Thanks in advance for any help, updates or references to anything that may help me get on track...

Use Pow.PasswordReset.Plug.create_reset_token without a conn

I have a site (https://github.com/axelclark/golf) that has both an html frontend and a graphql api for a mobile app. I have the ResetPassword extension set up for html. I'm trying to enable a user to send the reset token email from their mobile app using graphql.

I'm trying to figure out which Pow.PasswordReset functions to use in my graphql resolver which acts like a controller. The problem is I don't have a conn with the config in it. I just have the user email from the params.

  def create_reset_token(_parent, %{email: email}, _resolution) do
    # Need to create the token and send the email
  end

Any suggestions on how to do this? I only want to enable the create action through graphql.

Cannot update field without password required.

For operation purpose, some managers can change the user's role. But when I tried using Pow.Operations.update/3, it passes through changeset in pow_changeset/2 which requires :current_password. Since the managers don't know other users' password, it blocks from updating fields like `:role'.

What's the better way to update :role for this situation?

It looks Pow.Operations.update/3 allows updating other users, but can't utilize it practically.

PowPersistentSession doesn't interact with DB storage.

In my website pow is equipped with three included extensions. And whenever I restarted the server, all the sessions are gone away.

I expected that the PowPersistentSession stores credentials into DB layer, but there's no additional migration.

Is this feature intended or under development?

Questions about session cache.

๐Ÿ‘‹

  • The credentials and session are renewed after 15 minutes if any activity is detected
  • The credentials and session are renewed when user updates

Hi! Could you please point me to the code where these happen? I tried making a session cache backend backed by postgres, but it seems neither of the last two points work with it. Updating a user with both pow_user_id_field_changeset/2 and
pow_password_changeset/2 in the changeset doesn't make any calls to the session cache process
, and no matter the activity, the users still get logged out after 30 minutes. I'm tracing the cache process and don't see any put calls to it being made by any pow module after the initial one -- only gets like this:

# 14:40:11 #PID<0.761.0> :cowboy_stream_h.request_process/3
# Demo.Pow.SessionCache.get([ttl: 1800000, namespace: "credentials"], "demo_bbf48417-285a-4a14-bf0d-335e2b0fc657")

Function to return total users count.

I wonder which is the better way to get total registered users count.

How about adding a function to return the count of total users?

  1. Return the max id in users table.
  • Fast but not precise.
  • Not applicable except auto-increment id; ex. UUID.
  1. Return the count of primary key in users table.
  • Rather fast and precise.

Pow.Phoenix.RegistrationController not available?

I've followed the Getting Started (Phoenix) section in the README to the letter but when I 'fire up' the iex -S mix phx.server and try going to localhost:4000/registration/new I'm told that

$ iex -S mix phx.server
Erlang/OTP 21 [erts-10.0.7] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [dtrace]

[info] Running PowwowWeb.Endpoint with Cowboy using http://0.0.0.0:4000
Interactive Elixir (1.7.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> 10:25:47 - info: compiled 6 files into 2 files, copied 3 in 874 ms
[info] GET /registration/new
[info] Sent 500 in 69ms
[error] #PID<0.398.0> running PowwowWeb.Endpoint (cowboy_protocol) terminated
Server: localhost:4000 (http)
Request: GET /registration/new
** (exit) an exception was raised:
    ** (UndefinedFunctionError) function PowwowWeb.Pow.Phoenix.RegistrationController.init/1 is undefined (module PowwowWeb.Pow.Phoenix.RegistrationController is not available)
        PowwowWeb.Pow.Phoenix.RegistrationController.init(:new)
        (powwow) lib/powwow_web/router.ex:1: anonymous fn/1 in PowwowWeb.Router.__match_route__/4
        (phoenix) lib/phoenix/router.ex:278: Phoenix.Router.__call__/1
        (powwow) lib/powwow_web/endpoint.ex:1: PowwowWeb.Endpoint.plug_builder_call/2
        (powwow) lib/plug/debugger.ex:122: PowwowWeb.Endpoint."call (overridable 3)"/2
        (powwow) lib/powwow_web/endpoint.ex:1: PowwowWeb.Endpoint.call/2
        (plug) lib/plug/adapters/cowboy/handler.ex:16: Plug.Adapters.Cowboy.Handler.upgrade/4
        (cowboy) /Users/Walther/tmp/meetup/powwow/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
[info] GET /
[debug] Processing with PowwowWeb.PageController.index/2
  Parameters: %{}
  Pipelines: [:browser]
[info] Sent 200 in 12ms

Any ideas?

password_hash not being generated when testing custom SessionController

Hi, great library!

Thanks to how configurable it is I've been able to use it in my app which is just an API. I'm trying to write tests for my SessionController and when POSTing valid credentials, it seems like the password_hash never gets generated. It works fine outside of the test which leads me to believe it might be a config I need to set somewhere... any idea what I might be missing?

Error encountered when following the getting started guide

Version info:

Windows 10
Erlang/OTP 21 [erts-10.0.1] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1]
Elixir 1.7.3 (compiled with Erlang/OTP 19)
Phoenix v1.3.4

I'm following the getting started guide. Although the code examples look different now (likely due to using newer versions of Elixir and Phoenix), I think I have managed to set it up correctly.

When visiting http://localhost:4000/registration/new, I get the following error:

[error] #PID<0.394.0> running MyAppWeb.Endpoint (cowboy_protocol) terminated
Server: localhost:4000 (http)
Request: GET /registration/new
** (exit) an exception was raised:
    ** (Pow.Config.ConfigError) No :user configuration option found for user schema module.
        (pow) lib/pow/config.ex:55: Pow.Config.raise_error/1
        (pow) lib/pow/operations.ex:18: Pow.Operations.changeset/2
        (pow) lib/pow/phoenix/controllers/registration_controller.ex:15: Pow.Phoenix.RegistrationController.process_new/2
        (pow) lib/pow/phoenix/controllers/controller.ex:87: Pow.Phoenix.Controller.action/3
        (pow) lib/pow/phoenix/controllers/registration_controller.ex:1: Pow.Phoenix.RegistrationController.action/2
        (pow) lib/pow/phoenix/controllers/registration_controller.ex:1: Pow.Phoenix.RegistrationController.phoenix_controller_pipeline/2
        (my_app) lib/my_app_web/endpoint.ex:1: MyAppWeb.Endpoint.instrument/4
        (phoenix) lib/phoenix/router.ex:278: Phoenix.Router.__call__/1
        (my_app) lib/my_app_web/endpoint.ex:1: MyAppWeb.Endpoint.plug_builder_call/2
        (my_app) lib/plug/debugger.ex:122: MyAppWeb.Endpoint."call (overridable 3)"/2
        (my_app) lib/my_app_web/endpoint.ex:1: MyAppWeb.Endpoint.call/2
        (plug) lib/plug/adapters/cowboy/handler.ex:16: Plug.Adapters.Cowboy.Handler.upgrade/4
        (cowboy) c:/Code/my_app/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4

Contents of config.exs:

# This file is responsible for configuring your application
# and its dependencies with the aid of the Mix.Config module.
#
# This configuration file is loaded before any dependency and
# is restricted to this project.
use Mix.Config

# General application configuration
config :my_app, :pow,
  user: MyApp.Users.User,
  ecto_repos: [MyApp.Repo] # Notice that this is different from the getting started guide

# Configures the endpoint
config :my_app, MyAppWeb.Endpoint,
  url: [host: "localhost"],
  secret_key_base: "my_secret",
  render_errors: [view: MyAppWeb.ErrorView, accepts: ~w(html json)],
  pubsub: [name: MyApp.PubSub,
           adapter: Phoenix.PubSub.PG2]

# Configures Elixir's Logger
config :logger, :console,
  format: "$time $metadata[$level] $message\n",
  metadata: [:user_id]

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env}.exs"

Output of mix ecto.setup:

warning: could not find Ecto repos in any of the apps: [:my_app].

You can avoid this warning by passing the -r flag or by setting the
repositories managed by those applications in your config/config.exs:

    config :my_app, ecto_repos: [...]

warning: could not find Ecto repos in any of the apps: [:my_app].

You can avoid this warning by passing the -r flag or by setting the
repositories managed by those applications in your config/config.exs:

    config :my_app, ecto_repos: [...]

I'm investigating this now; trying to find the cause. If/when I figure it out, I will update this issue. Figured I'd post it here, in case other beginners encounter the same issue in the future.

Custom registration/session controller - Doc improvements

Hey Dan,

In the docs you mentioned that "the best way is to create and modify our own controllers". Can you provide some examples?

Should we copy/paste the controllers from pow/phoenix/controllers or import something? Maybe a snippet of custom routes could help too.

Context: I'm trying to implement pow in an app where registration should be closed/protected and users are created by something like an admin or a user already created. I want to document the process of the custom install/configuration of pow then I'll make a PR for the guides.

PowEmailConfirmation controller callbacks with custom SessionController

It seems like when using a custom SessionController with the PowEmailConfirmation extension, the controller callbacks that handle checking whether the email was confirmed aren't run and the connection isn't halted regardless of the email being unconfirmed.

I realized this is because I defined the controller with a custom name instead of Pow.Phoenix.SessionController.

The motivation behind this is using Pow and its extensions in an API which is decoupled from the front end of the app, so all responses should be JSON rather than HTML. Beginning to wonder if it'd be possible to just handle all the responses with controller callbacks instead and maybe it could be useful as an extension.

logo proposal

Hello. A logo is a good idea to improve the project. I can design it voluntarily. What dou you think?

Use configured module name instead of changeset data structure.

Current form template L72 builds form inputs with @changeset.data.__struct__.pow_user_id_field().

This is useful when there're some different types of @changesets are given. (is this intended?)

It can be resolved by replace with Pow.Config.get([otp_app: :my_app], :user, nil) when the template is generated.

Restructuring PowEmailConfirmation IAW Elixir de-facto.

I'm looking over the extension PowEmailConfirmation to find fn confirm! which is required in dev seed and tests.

And I found that this extension has a lot different style than Elixir de-facto standards two mainly;

  1. PowEmailConfirmation.Plug - Plug only and should implement two functions init/1 and call/2. I believe this module is sufficient to be renamed PowEmailConfirmation to avoid conflict and excessive encapsulation. (This is applied to the other modules as well.)
  2. Pow.UUID - I cannot find any reason to replace the Ecto.UUID or elixir_uuid. We don't need to reinvent the wheel.

PowEmailConfirmation extension crashes with UndefinedFunctionError

Hello!

I'm trying to follow the instructions in the README about the e-mail confirmation extension. I updated the config.ex, the user.ex and the router.ex, generated the templates, added the pow_mailer.ex module, added the mailer_backend key to the config.ex, added the mailer_view function, generated the templates and added the web_mailer_module key. Yet after login I get this error message:

[error] #PID<0.417.0> running UserProfileManagerWeb.Endpoint (cowboy_protocol) terminated
Server: localhost:4000 (http)
Request: POST /session?request_path=%2F
** (exit) an exception was raised:
** (UndefinedFunctionError) function UserProfileManagerWeb.Router.Helpers.pow_email_confirmation_confirmation_url/3 is undefined or private
(user_profile_manager) UserProfileManagerWeb.Router.Helpers.pow_email_confirmation_confirmation_url(%Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...}, assigns: %{action: "/session?request_path=%2F", current_user: ...
(pow) lib/extensions/email_confirmation/phoenix/controllers/controller_callbacks.ex:56: PowEmailConfirmation.Phoenix.ControllerCallbacks.send_confirmation_email/2
(pow) lib/extensions/email_confirmation/phoenix/controllers/controller_callbacks.ex:39: PowEmailConfirmation.Phoenix.ControllerCallbacks.halt_unconfirmed/3
(elixir) lib/enum.ex:1925: Enum."-reduce/3-lists^foldl/2-0-"/3
(pow) lib/pow/phoenix/controllers/controller.ex:88: Pow.Phoenix.Controller.action/3
(pow) lib/pow/phoenix/controllers/session_controller.ex:1: Pow.Phoenix.SessionController.action/2
(pow) lib/pow/phoenix/controllers/session_controller.ex:1: Pow.Phoenix.SessionController.phoenix_controller_pipeline/2
(user_profile_manager) lib/user_profile_manager_web/endpoint.ex:1: UserProfileManagerWeb.Endpoint.instrument/4
(phoenix) lib/phoenix/router.ex:278: Phoenix.Router.call/1
(user_profile_manager) lib/user_profile_manager_web/endpoint.ex:1: UserProfileManagerWeb.Endpoint.plug_builder_call/2
(user_profile_manager) lib/plug/debugger.ex:122: UserProfileManagerWeb.Endpoint."call (overridable 3)"/2
(user_profile_manager) lib/user_profile_manager_web/endpoint.ex:1: UserProfileManagerWeb.Endpoint.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:16: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) /home/nar/mena_playground/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4

I see that this pow_email_confirmation_confirmation_url function is called, but I don't see any implementation for it in the 1.0.0-rc4 version and the README doesn't mention that I need to implement it either. I see that the e62374b commit changed this in the extension, but I don't know how to get the latest version. How do I get it? I added {:pow, "~> 1.0.0-rc.4"} to mix.exs.

Multiple User Contexts/Schemas

In my app, I have the need for multiple user tables.

Devise does a killer job (via warden) to authenticate via varying tables & warden scopes.

Is there a good mechanism to do this with this library (without an umbrella)?

Add fn Pow.Operations.current_user(conn)

In my webapp, Bodyguard library is used for simple authorization.

And Bodyguard.Plug.Authorization receives 1-arity fn for user allocation like &get_current_user/1. Docs

Currently there's a helper fn which simply wraps Pow.Operations.current_user(conn, otp_app: :myapp).

I believe almost every users with Bodyguard and Pow would do the same thing, which means it'll be one of the most frequently used fn.

So, how about adding a fn current_user(conn) or current_user(conn, default_options)?

Add function logged_in?(conn)/1

More than often, it's enough to check whether an user session is logged in or not.

But currently I can only check user via current_user/1 which returns a bit heavy user-full struct.

How about add a new function returning lightweight true/false instead? This will make consuming less resource.

mix pow.install doesn't work

Hello!

I tried to follow the installation instructions: added pow to the dependencies, fetched the dependencies using mix deps.get, then executed the mix pow.install command, but got this error:

** (Mix) Could not load UserProfileManager.Repo, error: :nofile. Please configure your app accordingly or pass a repo with the -r option.

What could be the problem? My project is under an umbrella. The output from mix deps.get is this:

Running dependency resolution...
Dependency resolution completed:
cowboy 1.1.2
cowlib 1.0.2
decimal 1.5.0
ecto 2.2.11
file_system 0.2.6
gettext 0.16.0
mime 1.3.0
phoenix 1.3.4
phoenix_ecto 3.5.0
phoenix_html 2.12.0
phoenix_live_reload 1.1.7
phoenix_pubsub 1.1.0
plug 1.6.4
poison 3.1.0
poolboy 1.5.1
pow 1.0.0-rc.4
ranch 1.3.2
All dependencies up to date

Override credential TTL.

There seems two (or more?) places to configure credential TTL; Pow.Plug.Session and Pow.Store.Base.

Where can I set up the credential TTL?

I18n for email.

There are some email templates types of html and text. At first I followed document guide, but it didn't work.

Mine is currently providing both English and Korean and going to add some Asian languages soon.

If you're busy then I can make PR. (I don't fully understand pow yet.)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.