Packages
guard
0.15.3
0.19.1
0.19.0
0.18.0
0.17.2
0.17.1
0.17.0
0.16.3
0.16.2
0.16.1
0.16.0
0.15.3
0.15.2
0.15.1
0.15.0
0.14.9
0.14.8
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.13.1
0.13.0
0.12.9
0.12.8
0.12.7
0.12.6
0.12.5
0.12.4
0.12.3
0.12.2
0.12.1
0.12.0
0.11.3
0.11.2
0.11.1
0.11.0
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.0
0.8.0
0.7.1
0.7.0
0.6.1
0.6.0
0.5.0
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
Useful package for dealing with user authentication and signup
Current section
Files
Jump to
Current section
Files
lib/guard/controller.ex
defmodule Guard.Controller do
@moduledoc false
require Logger
import Plug.Conn, only: [put_status: 2, put_resp_content_type: 2, send_resp: 3]
defmacro __using__(_opts) do
quote do
use Phoenix.Controller
import Guard.Controller, only: [send_error: 2]
require Logger
def call(conn, opts) do
try do
super(conn, opts)
rescue
error ->
Logger.metadata(stacktrace: __STACKTRACE__)
send_error(conn, error)
end
end
end
end
defmacro resources do
quote do
# Create new account
post("/registration", Guard.Controller.Registration, :create)
# Request a password reset
post("/registration/reset", Guard.Controller.Registration, :send_password_reset)
# Resend confirmation link
post(
"/registration/send_confirmation",
Guard.Controller.Registration,
:send_confirmation_link
)
# Send magic link
post("/registration/link", Guard.Controller.Registration, :send_login_link)
# Check availability
post("/registration/check", Guard.Controller.Registration, :check_account)
# Register for push
post("/registration/device", Guard.Controller.Registration, :register_device)
# Unregister for push
delete(
"/registration/device/:platform/:token",
Guard.Controller.Registration,
:unregister_device
)
# Login
post("/session", Guard.Controller.Session, :create)
# Show current session
get("/session", Guard.Controller.ActiveSession, :show)
# Restore session with given JWT
get("/session/:token", Guard.Controller.Session, :restore)
# Logout
delete("/session", Guard.Controller.Session, :delete)
put("/session/switch/:id", Guard.Controller.Session, :switch_user)
put("/session/switch/username/:username", Guard.Controller.Session, :switch_user)
put("/session/switch/email/:email", Guard.Controller.Session, :switch_user)
put("/session/switch/mobile/:mobile", Guard.Controller.Session, :switch_user)
put("/session/context", Guard.Controller.Session, :set_context)
delete("/session/context", Guard.Controller.Session, :clear_context)
delete("/session/switch", Guard.Controller.Session, :reset_user)
# Update current account
put("/account", Guard.Controller.Account, :update)
# Update attributes for current account
post("/account/attributes", Guard.Controller.Account, :update_attributes)
# Delete account
delete("/account", Guard.Controller.Account, :delete)
# Update password for current account
put("/account/password", Guard.Controller.PasswordReset, :update_password)
# Update password for account by one-time-pin
put("/account/setpassword", Guard.Controller.Registration, :update_password)
end
end
defmacro key_resources do
quote do
get("/keys", Guard.Controller.KeyController, :list_keys)
post("/keys", Guard.Controller.KeyController, :create_key)
delete("/keys/:key", Guard.Controller.KeyController, :revoke_key)
end
end
defmacro admin_resources do
quote do
get("/users/:id", Guard.Controller.UserController, :get_user)
get("/users/username/:username", Guard.Controller.UserController, :get_user)
get("/users/email/:email", Guard.Controller.UserController, :get_user)
get("/users/mobile/:mobile", Guard.Controller.UserController, :get_user)
# Create user
post("/users", Guard.Controller.UserController, :create_user)
# Update given user
put("/users/:id", Guard.Controller.UserController, :update_user)
# Delete given user
delete("/users/:id", Guard.Controller.UserController, :delete_user)
# Show all registered uses
get("/users", Guard.Controller.UserController, :list_all_users)
end
end
def send_error(conn, %{message: message, plug_status: status_code} = _error) do
send_error(conn, message, status_code)
end
def send_error(conn, %Ecto.Changeset{} = cs) do
send_error(conn, Guard.Repo.changeset_errors(cs), :unprocessable_entity)
end
def send_error(conn, %Ecto.Query.CastError{}) do
send_error(conn, :not_found, :not_found)
end
def send_error(conn, {:error, error}) do
send_error(conn, error)
end
def send_error(conn, %Ecto.NoResultsError{}) do
send_error(conn, :not_found, :not_found)
end
def send_error(conn, :no_pin = error) do
send_error(conn, error, :unauthorized)
end
def send_error(conn, :wrong_pin = error) do
send_error(conn, error, :unauthorized)
end
def send_error(conn, :wrong_password = error) do
send_error(conn, error, :unauthorized)
end
def send_error(conn, :bad_claim = error) do
send_error(conn, error, :unauthorized)
end
def send_error(conn, %Plug.Conn.WrapperError{reason: reason}) do
send_error(conn, reason)
end
def send_error(conn, error, status_code \\ :internal_server_error) do
Logger.debug(fn -> "ERROR: #{conn.request_path}\n#{inspect(error)}" end)
Logger.debug(fn -> "#{inspect(Logger.metadata())}" end)
conn
|> put_status(status_code)
|> json(%{error: translate_error(error)})
end
def json(conn, value) do
conn
|> put_resp_content_type("application/json")
|> send_resp(conn.status || :ok, Jason.encode_to_iodata!(value))
end
def translate_error(reason) do
cond do
is_tuple(reason) -> tuple_to_map(%{}, Tuple.to_list(reason))
Exception.exception?(reason) -> translate_error(Exception.message(reason))
true -> reason
end
end
defp tuple_to_map(acc, list) do
if length(list) > 2 do
[k, v | tail] = list
tuple_to_map(Map.put(acc, k, v), tail)
else
acc
end
end
end