Skip to content
This repository has been archived by the owner on Jan 19, 2022. It is now read-only.

Commit

Permalink
Version 2.8
Browse files Browse the repository at this point in the history
  • Loading branch information
riverrun committed Feb 8, 2017
1 parent 2421872 commit 647ecbe
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 32 deletions.
Binary file added installer/archives/openmaize_phx-2.8.0.ez
Binary file not shown.
Binary file added installer/archives/openmaize_phx.ez
Binary file not shown.
2 changes: 1 addition & 1 deletion installer/phoenix/lib/openmaize_phx.ex
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ defmodule Mix.Tasks.Openmaize.Phx do
We are almost ready!
Now edit the `mix.exs` file, adding `:openmaize` to the list of
`applications` and `{:openmaize, {"~> 2.7"}},` to the deps.
`applications` and `{:openmaize, "~> 2.7"},` to the deps.
Then run `mix deps.get`.
You might also need to edit the database details in the `config`
Expand Down
2 changes: 1 addition & 1 deletion installer/phoenix/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule Openmaize.Phx.Mixfile do

def project do
[app: :openmaize_phx,
version: "2.7.0",
version: "2.8.0",
elixir: "~> 1.3"]
end

Expand Down
5 changes: 2 additions & 3 deletions lib/openmaize/authenticate.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,13 @@ defmodule Openmaize.Authenticate do

@behaviour Plug

@doc false
def init(opts) do
{Keyword.get(opts, :repo, Openmaize.Utils.default_repo),
Keyword.get(opts, :user_model, Openmaize.Utils.default_user_model)}
end

@doc """
Authenticate the current user.
"""
@doc false
def call(conn, {repo, user_model}) do
get_session(conn, :user_id) |> get_user(conn, repo, user_model)
end
Expand Down
2 changes: 2 additions & 0 deletions lib/openmaize/confirm/base.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ defmodule Openmaize.Confirm.Base do

import unquote(__MODULE__)

@doc false
def init(opts) do
{Keyword.get(opts, :repo, Openmaize.Utils.default_repo),
Keyword.get(opts, :user_model, Openmaize.Utils.default_user_model),
{Keyword.get(opts, :key_expires_after, 60),
Keyword.get(opts, :mail_function, &IO.puts/1)}}
end

@doc false
def call(%Plug.Conn{params: params} = conn, opts) do
check_confirm conn, unpack_params(params), opts
end
Expand Down
53 changes: 52 additions & 1 deletion lib/openmaize/login.ex
Original file line number Diff line number Diff line change
@@ -1,19 +1,64 @@
defmodule Openmaize.Login do
@moduledoc """
Module to handle login.
`Openmaize.Login` checks the user's password, making sure that the
account has been confirmed, if necessary, and returns an `openmaize_user`
message if login is successful (unless you are using two-factor authentication)
or an `openmaize_error` message if there is an error.
## Two-factor authentication
If two-factor authentication is enabled and `otp_required` for the
user is true, an `openmaize_otpdata` message is returned. This contains
the user id, which is then used when authenticating the one-time
password.
## Options
There are three options:
* unique_id - the name which is used to identify the user (in the database)
* the default is `:username`
* this can also be a function - see below for an example
* repo - the name of the repo
* the default is MyApp.Repo - using the name of the project
* user_model - the name of the user model
* the default is MyApp.User - using the name of the project
### unique_id option
The `unique_id` option is usually an atom, but it can also be a function
which returns a tuple with the {unique_id (as an atom), user_id, password}.
The following example is a function that takes the user parameters as
input and searches for the user by phone number if the input is all digits,
but username otherwise.
def phone_name(%{"username" => username, "password" => password}) do
{Regex.match?(~r/^[0-9]+$/, username) and :phone || :username, username, password}
end
To use this function, add the following to the session controller:
plug Openmaize.Login, [unique_id: &phone_name/1] when action in [:create]
"""

@behaviour Plug

import Plug.Conn
alias Openmaize.{Config, Logger}

@doc false
def init(opts) do
uniq = Keyword.get(opts, :unique_id, :username)
{uniq, to_string(uniq),
user_params = if is_atom(uniq), do: to_string(uniq), else: "username"
{uniq, user_params,
Keyword.get(opts, :repo, Openmaize.Utils.default_repo),
Keyword.get(opts, :user_model, Openmaize.Utils.default_user_model)}
end

@doc false
def call(%Plug.Conn{params: %{"session" => params}} = conn,
{uniq, user_params, repo, user_model}) when is_atom(uniq) do
%{^user_params => user_id, "password" => password} = params
Expand All @@ -26,6 +71,12 @@ defmodule Openmaize.Login do

@doc """
Check the user's password.
Search for the user in the database and check the password against
the stored password hash.
If no user is found, a dummy hash function is run in order to make
user enumeration more difficult.
"""
def check_user_pass(conn, {uniq, user_id, password}, {repo, user_model}) do
repo.get_by(user_model, [{uniq, user_id}])
Expand Down
8 changes: 2 additions & 6 deletions lib/openmaize/onetime_pass.ex
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,14 @@ defmodule Openmaize.OnetimePass do
alias Openmaize.Database, as: DB
alias Openmaize.Logger

@doc false
def init(opts) do
{Keyword.get(opts, :repo, Openmaize.Utils.default_repo),
Keyword.get(opts, :user_model, Openmaize.Utils.default_user_model),
opts}
end

@doc """
Handle the one-time password POST request.
If the one-time password check is successful, the user will be added
to the session.
"""
@doc false
def call(%Plug.Conn{params: %{"user" => %{"id" => id, "hotp" => hotp}}} = conn,
{repo, user_model, opts}) do
{:ok, result} = repo.transaction(fn ->
Expand Down
18 changes: 8 additions & 10 deletions lib/openmaize/remember.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ defmodule Openmaize.Remember do
access enabled.
This needs to be run after `plug Openmaize.Authenticate`.
This Plug checks for a `remember_me` cookie, and if the current_user
is not set, authenticate the user using this cookie. If the check is
successful, the user will be added to the current session and to
the current_user. If the check is unsuccessful, an error message
will be sent to `conn.private.openmaize_error`.
"""

@behaviour Plug
Expand All @@ -12,21 +18,13 @@ defmodule Openmaize.Remember do
alias Openmaize.Config
alias Plug.Crypto.{KeyGenerator, MessageVerifier}

@doc false
def init(opts) do
{Keyword.get(opts, :repo, Openmaize.Utils.default_repo),
Keyword.get(opts, :user_model, Openmaize.Utils.default_user_model)}
end

@doc """
Check for a `remember_me` cookie, and if the current_user is not set,
authenticate the user using this cookie.
If the check is successful, the user will be added to the current
session and to the current_user.
If the check is unsuccessful, an error message will be sent to
`conn.private.openmaize_error`.
"""
@doc false
def call(%Plug.Conn{req_cookies: %{"remember_me" => remember}} = conn, {repo, user_model}) do
if conn.assigns[:current_user] do
conn
Expand Down
10 changes: 5 additions & 5 deletions mix.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Openmaize.Mixfile do
use Mix.Project

@version "2.8.0-dev"
@version "2.8.0"

@description """
Authentication library for Elixir using Plug
Expand All @@ -23,13 +23,13 @@ defmodule Openmaize.Mixfile do
end

defp deps do
[{:cowboy, "~> 1.0"},
[{:cowboy, "~> 1.1"},
{:plug, "~> 1.3"},
{:comeonin, "~> 3.0"},
{:ecto, "~> 2.0"},
{:postgrex, "~> 0.11", optional: true},
{:ecto, "~> 2.1"},
{:postgrex, "~> 0.13", optional: true},
{:not_qwerty123, "~> 1.2", optional: true},
{:earmark, "~> 1.0", only: :dev},
{:earmark, "~> 1.1", only: :dev},
{:ex_doc, "~> 0.14", only: :dev}]
end

Expand Down
16 changes: 14 additions & 2 deletions test/login_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ defmodule Openmaize.LoginTest do
|> Openmaize.Login.call({uniq, user_params, TestRepo, TestUser})
end

def phone_name(%{"phone" => phone, "password" => password}) do
{Regex.match?(~r/^[0-9]+$/, phone) and :phone || :username, phone, password}
def phone_name(%{"username" => username, "password" => password}) do
{Regex.match?(~r/^[0-9]+$/, username) and :phone || :username, username, password}
end

test "init function" do
Expand Down Expand Up @@ -60,4 +60,16 @@ defmodule Openmaize.LoginTest do
assert conn.private[:openmaize_error] =~ "Invalid credentials"
end

test "function unique_id with username" do
conn = login("ray", "h4rd2gU3$$", &phone_name/1, "username")
%{id: id} = conn.private[:openmaize_user]
assert id == 4
end

test "function unique_id with phone" do
conn = login("081555555", "h4rd2gU3$$", &phone_name/1, "username")
%{id: id} = conn.private[:openmaize_user]
assert id == 4
end

end
6 changes: 3 additions & 3 deletions test/support/ecto_helper.exs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ defmodule UsersMigration do
add :phone, :string
add :password_hash, :string
add :role, :string
add :confirmed_at, :datetime
add :confirmed_at, :utc_datetime
add :confirmation_token, :string
add :confirmation_sent_at, :datetime
add :confirmation_sent_at, :utc_datetime
add :reset_token, :string
add :reset_sent_at, :datetime
add :reset_sent_at, :utc_datetime
add :otp_required, :boolean
add :otp_secret, :string
add :otp_last, :integer
Expand Down

0 comments on commit 647ecbe

Please sign in to comment.