Created
September 24, 2017 23:37
-
-
Save romseguy/9eb9802f4f75f99fd4c39c16bd34c87b to your computer and use it in GitHub Desktop.
register
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# it also takes care of translating error messages with Gettext | |
defmodule ApiWeb.Middleware.ChangesetErrorFormatter do | |
import ApiWeb.ErrorHelpers | |
def call(%{errors: []} = res, _), do: res | |
def call(%{errors: errors} = res, _) do | |
formatted_errors = format_changeset_error(errors) | |
%{res | errors: formatted_errors} | |
end | |
def format_changeset_error(errors) when is_list(errors) do | |
cond do | |
Enum.all?(errors, &is_changeset/1) -> Enum.flat_map(errors, &format_changeset_error/1) | |
Enum.all?(errors, &is_bitstring/1) -> Enum.map(errors, &translate_error({&1, []})) | |
Enum.all?(errors, &is_map/1) -> errors | |
true -> Enum.flat_map(errors, &format_changeset_error/1) | |
end | |
end | |
def format_changeset_error(%Ecto.Changeset{} = changeset), do: format_changeset(changeset) | |
def format_changeset_error(error), do: error | |
defp format_changeset(str) when is_bitstring(str), do: str | |
defp format_changeset(changeset) do | |
changeset | |
|> interpolate_errors | |
|> Map.to_list | |
|> Enum.flat_map(fn {field, errors} -> field_errors_to_error(changeset, field, errors) end) | |
end | |
def field_errors_to_error(changeset, field, errors) do | |
field_name = Atom.to_string(field) | |
Enum.map(errors, fn error -> | |
value = error_field_value(changeset, field) | |
%{ | |
field_name: field_name, | |
message: translate_error({error, value: value}), | |
value: value | |
} | |
end) | |
end | |
defp interpolate_errors(changeset) do | |
Ecto.Changeset.traverse_errors(changeset, fn {msg, opts} -> | |
Enum.reduce(opts, msg, fn {key, value}, acc -> | |
String.replace(acc, "%{#{key}}", to_string(value)) | |
end) | |
end) | |
end | |
@spec error_field_value(changeset :: Ecto.Changeset.t, field :: atom) :: any | |
defp error_field_value(changeset, field) do | |
case Ecto.Changeset.fetch_field(changeset, field) do | |
{_, value} -> value | |
:error -> nil | |
end | |
end | |
defp is_changeset(%Ecto.Changeset{} = _), do: true | |
defp is_changeset(_), do: false | |
end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# we use a middleware to handle the case where a changeset with errors is returned from the resolver | |
def middleware(middleware, _field, %Absinthe.Type.Object{identifier: :mutation}) do | |
middleware ++ [ApiWeb.Middleware.ChangesetErrorFormatter] | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@desc "Register with email, username, and password" | |
field :register, type: :session do | |
arg :email, non_null(:string) | |
arg :username, non_null(:string) | |
arg :password, non_null(:string) | |
resolve &Resolvers.register/2 | |
end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def register(attrs, _info) do | |
with {:ok, user} <- Api.Session.register(attrs), | |
{:ok, jwt, _ } <- Guardian.encode_and_sign(user, :access) | |
do | |
{:ok, %{token: jwt}} | |
else | |
{:error, changeset} -> {:error, changeset} | |
end | |
end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Api.Accounts.User do | |
use Ecto.Schema | |
import Ecto.Changeset | |
import Helpers.Validation | |
@doc""" | |
ecto schema/struct for the users table | |
""" | |
schema "users" do | |
field :email, :string | |
field :password, :string, virtual: true | |
field :password_hash, :string | |
field :username, :string | |
timestamps() | |
end | |
def changeset(%User{} = user, attrs) do | |
user | |
|> cast(attrs, [:email, :username]) | |
|> validate_required([:email]) | |
end | |
def create_changeset(%User{} = user, attrs \\ %{}) do | |
user | |
|> update_changeset(attrs) | |
|> cast(attrs, [:password]) | |
|> validate_required([:password]) | |
|> validate_length(:password, min: 6, max: 100) | |
|> put_pass_hash | |
end | |
def update_changeset(%User{} = user, attrs \\ %{}) do | |
user | |
|> cast(attrs, [:email, :username]) | |
|> validate_required([:email]) | |
|> validate_length(:username, min: 1, max: 40) | |
|> validate_length(:email, min: 3) | |
|> unique_constraint(:username, message: "username has already been taken") | |
|> validate_email_format(:email) | |
|> unique_constraint(:email, message: "email has already been taken") | |
|> downcase_user_email | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment