Add typespecs, remove unneeded documentation

This commit is contained in:
Nikos Papadakis 2023-07-29 14:45:09 +03:00
parent 1a2f7d78e8
commit a9d8786d11
Signed by untrusted user who does not match committer: nikos
GPG key ID: 78871F9905ADFF02
4 changed files with 38 additions and 30 deletions

View file

@ -63,20 +63,21 @@ defmodule Prymn.Accounts do
@spec get_user!(integer()) :: User.t() @spec get_user!(integer()) :: User.t()
def get_user!(id), do: Repo.get!(User, id) def get_user!(id), do: Repo.get!(User, id)
## User registration ## User registration, used by the registration flow
@doc """ @doc """
Registers a user. Registers a user.
## Examples ## Examples
iex> register_user(%{field: value}) iex> register_user(%{email: "email@example.com", password: "examplepassword"})
{:ok, %User{}} {:ok, %User{}}
iex> register_user(%{field: bad_value}) iex> register_user(%{field: "value"})
{:error, %Ecto.Changeset{}} {:error, %Ecto.Changeset{}}
""" """
@spec register_user(map()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
def register_user(attrs) do def register_user(attrs) do
%User{} %User{}
|> User.registration_changeset(attrs) |> User.registration_changeset(attrs)
@ -92,11 +93,12 @@ defmodule Prymn.Accounts do
%Ecto.Changeset{data: %User{}} %Ecto.Changeset{data: %User{}}
""" """
@spec change_user_registration(User.t(), map()) :: Ecto.Changeset.t()
def change_user_registration(%User{} = user, attrs \\ %{}) do def change_user_registration(%User{} = user, attrs \\ %{}) do
User.registration_changeset(user, attrs, hash_password: false, validate_email: false) User.registration_changeset(user, attrs, hash_password: false, validate_email: false)
end end
## Settings ## Settings, used by the account settings flows
@doc """ @doc """
Returns an `%Ecto.Changeset{}` for changing the user email. Returns an `%Ecto.Changeset{}` for changing the user email.
@ -107,6 +109,7 @@ defmodule Prymn.Accounts do
%Ecto.Changeset{data: %User{}} %Ecto.Changeset{data: %User{}}
""" """
@spec change_user_email(User.t(), map()) :: Ecto.Changeset.t()
def change_user_email(user, attrs \\ %{}) do def change_user_email(user, attrs \\ %{}) do
User.email_changeset(user, attrs, validate_email: false) User.email_changeset(user, attrs, validate_email: false)
end end
@ -124,6 +127,8 @@ defmodule Prymn.Accounts do
{:error, %Ecto.Changeset{}} {:error, %Ecto.Changeset{}}
""" """
@spec apply_user_email(User.t(), String.t(), map()) ::
{:ok, User.t()} | {:error, Ecto.Changeset.t()}
def apply_user_email(user, password, attrs) do def apply_user_email(user, password, attrs) do
user user
|> User.email_changeset(attrs) |> User.email_changeset(attrs)
@ -135,8 +140,9 @@ defmodule Prymn.Accounts do
Updates the user email using the given token. Updates the user email using the given token.
If the token matches, the user email is updated and the token is deleted. If the token matches, the user email is updated and the token is deleted.
The confirmed_at date is also updated to the current time. The `confirmed_at` date is also updated to the current time.
""" """
@spec update_user_email(User.t(), binary()) :: :ok | :error
def update_user_email(user, token) do def update_user_email(user, token) do
context = "change:#{user.email}" context = "change:#{user.email}"
@ -169,6 +175,8 @@ defmodule Prymn.Accounts do
{:ok, %{to: ..., body: ...}} {:ok, %{to: ..., body: ...}}
""" """
@spec deliver_user_update_email_instructions(User.t(), String.t(), (... -> String.t())) ::
{:ok, Swoosh.Email.t()}
def deliver_user_update_email_instructions(%User{} = user, current_email, update_email_url_fun) def deliver_user_update_email_instructions(%User{} = user, current_email, update_email_url_fun)
when is_function(update_email_url_fun, 1) do when is_function(update_email_url_fun, 1) do
{encoded_token, user_token} = UserToken.build_email_token(user, "change:#{current_email}") {encoded_token, user_token} = UserToken.build_email_token(user, "change:#{current_email}")
@ -186,6 +194,7 @@ defmodule Prymn.Accounts do
%Ecto.Changeset{data: %User{}} %Ecto.Changeset{data: %User{}}
""" """
@spec change_user_password(User.t(), map()) :: Ecto.Changeset.t()
def change_user_password(user, attrs \\ %{}) do def change_user_password(user, attrs \\ %{}) do
User.password_changeset(user, attrs, hash_password: false) User.password_changeset(user, attrs, hash_password: false)
end end
@ -202,6 +211,8 @@ defmodule Prymn.Accounts do
{:error, %Ecto.Changeset{}} {:error, %Ecto.Changeset{}}
""" """
@spec update_user_password(User.t(), String.t(), map()) ::
{:ok, User.t()} | {:error, Ecto.Changeset.t()}
def update_user_password(user, password, attrs) do def update_user_password(user, password, attrs) do
changeset = changeset =
user user
@ -223,6 +234,7 @@ defmodule Prymn.Accounts do
@doc """ @doc """
Generates a session token. Generates a session token.
""" """
@spec generate_user_session_token(User.t()) :: binary()
def generate_user_session_token(user) do def generate_user_session_token(user) do
{token, user_token} = UserToken.build_session_token(user) {token, user_token} = UserToken.build_session_token(user)
Repo.insert!(user_token) Repo.insert!(user_token)
@ -232,6 +244,7 @@ defmodule Prymn.Accounts do
@doc """ @doc """
Gets the user with the given signed token. Gets the user with the given signed token.
""" """
@spec get_user_by_session_token(binary()) :: User.t()
def get_user_by_session_token(token) do def get_user_by_session_token(token) do
{:ok, query} = UserToken.verify_session_token_query(token) {:ok, query} = UserToken.verify_session_token_query(token)
Repo.one(query) Repo.one(query)
@ -240,6 +253,7 @@ defmodule Prymn.Accounts do
@doc """ @doc """
Deletes the signed token with the given context. Deletes the signed token with the given context.
""" """
@spec delete_user_session_token(binary()) :: :ok
def delete_user_session_token(token) do def delete_user_session_token(token) do
Repo.delete_all(UserToken.token_and_context_query(token, "session")) Repo.delete_all(UserToken.token_and_context_query(token, "session"))
:ok :ok
@ -259,6 +273,8 @@ defmodule Prymn.Accounts do
{:error, :already_confirmed} {:error, :already_confirmed}
""" """
@spec deliver_user_confirmation_instructions(User.t(), (... -> String.t())) ::
{:ok, Swoosh.Email.t()} | {:error, :already_confirmed}
def deliver_user_confirmation_instructions(%User{} = user, confirmation_url_fun) def deliver_user_confirmation_instructions(%User{} = user, confirmation_url_fun)
when is_function(confirmation_url_fun, 1) do when is_function(confirmation_url_fun, 1) do
if user.confirmed_at do if user.confirmed_at do
@ -276,6 +292,7 @@ defmodule Prymn.Accounts do
If the token matches, the user account is marked as confirmed If the token matches, the user account is marked as confirmed
and the token is deleted. and the token is deleted.
""" """
@spec confirm_user(binary()) :: {:ok, User.t()} | :error
def confirm_user(token) do def confirm_user(token) do
with {:ok, query} <- UserToken.verify_email_token_query(token, "confirm"), with {:ok, query} <- UserToken.verify_email_token_query(token, "confirm"),
%User{} = user <- Repo.one(query), %User{} = user <- Repo.one(query),
@ -303,6 +320,8 @@ defmodule Prymn.Accounts do
{:ok, %{to: ..., body: ...}} {:ok, %{to: ..., body: ...}}
""" """
@spec deliver_user_reset_password_instructions(User.t(), (... -> String.t())) ::
{:ok, Swoosh.Email.t()}
def deliver_user_reset_password_instructions(%User{} = user, reset_password_url_fun) def deliver_user_reset_password_instructions(%User{} = user, reset_password_url_fun)
when is_function(reset_password_url_fun, 1) do when is_function(reset_password_url_fun, 1) do
{encoded_token, user_token} = UserToken.build_email_token(user, "reset_password") {encoded_token, user_token} = UserToken.build_email_token(user, "reset_password")
@ -322,6 +341,7 @@ defmodule Prymn.Accounts do
nil nil
""" """
@spec get_user_by_reset_password_token(binary()) :: User.t() | nil
def get_user_by_reset_password_token(token) do def get_user_by_reset_password_token(token) do
with {:ok, query} <- UserToken.verify_email_token_query(token, "reset_password"), with {:ok, query} <- UserToken.verify_email_token_query(token, "reset_password"),
%User{} = user <- Repo.one(query) do %User{} = user <- Repo.one(query) do
@ -343,6 +363,7 @@ defmodule Prymn.Accounts do
{:error, %Ecto.Changeset{}} {:error, %Ecto.Changeset{}}
""" """
@spec reset_user_password(User.t(), map()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
def reset_user_password(user, attrs) do def reset_user_password(user, attrs) do
Ecto.Multi.new() Ecto.Multi.new()
|> Ecto.Multi.update(:user, User.password_changeset(user, attrs)) |> Ecto.Multi.update(:user, User.password_changeset(user, attrs))

View file

@ -12,14 +12,14 @@ defmodule Prymn.Accounts.UserNotifier do
|> subject(subject) |> subject(subject)
|> text_body(body) |> text_body(body)
with {:ok, _metadata} <- Mailer.deliver(email) do {:ok, _metadata} = Mailer.deliver(email)
{:ok, email} {:ok, email}
end
end end
@doc """ @doc """
Deliver instructions to confirm account. Deliver instructions to confirm account.
""" """
@spec deliver_confirmation_instructions(User.t(), String.t()) :: {:ok, Swoosh.Email.t()}
def deliver_confirmation_instructions(user, url) do def deliver_confirmation_instructions(user, url) do
deliver(user.email, "Confirmation instructions", """ deliver(user.email, "Confirmation instructions", """
@ -40,6 +40,7 @@ defmodule Prymn.Accounts.UserNotifier do
@doc """ @doc """
Deliver instructions to reset a user password. Deliver instructions to reset a user password.
""" """
@spec deliver_reset_password_instructions(User.t(), String.t()) :: {:ok, Swoosh.Email.t()}
def deliver_reset_password_instructions(user, url) do def deliver_reset_password_instructions(user, url) do
deliver(user.email, "Reset password instructions", """ deliver(user.email, "Reset password instructions", """
@ -60,6 +61,7 @@ defmodule Prymn.Accounts.UserNotifier do
@doc """ @doc """
Deliver instructions to update a user email. Deliver instructions to update a user email.
""" """
@spec deliver_update_email_instructions(User.t(), String.t()) :: {:ok, Swoosh.Email.t()}
def deliver_update_email_instructions(user, url) do def deliver_update_email_instructions(user, url) do
deliver(user.email, "Update email instructions", """ deliver(user.email, "Update email instructions", """

View file

@ -1,9 +1,12 @@
defmodule PrymnWeb.UserSessionController do defmodule PrymnWeb.UserSessionController do
use PrymnWeb, :controller
alias Prymn.Accounts alias Prymn.Accounts
alias PrymnWeb.UserAuth alias PrymnWeb.UserAuth
use PrymnWeb, :controller
@spec create(Plug.Conn.t(), Phoenix.Param.t()) :: Plug.Conn.t()
@spec delete(Plug.Conn.t(), Phoenix.Param.t()) :: Plug.Conn.t()
def create(conn, %{"_action" => "registered"} = params) do def create(conn, %{"_action" => "registered"} = params) do
create(conn, params, "Account created successfully!") create(conn, params, "Account created successfully!")
end end

View file

@ -1,11 +1,11 @@
defmodule PrymnWeb.UserAuth do defmodule PrymnWeb.UserAuth do
use PrymnWeb, :verified_routes
import Plug.Conn import Plug.Conn
import Phoenix.Controller import Phoenix.Controller
alias Prymn.Accounts alias Prymn.Accounts
use PrymnWeb, :verified_routes
# Make the remember me cookie valid for 60 days. # Make the remember me cookie valid for 60 days.
# If you want bump or reduce this value, also change # If you want bump or reduce this value, also change
# the token expiry itself in UserToken. # the token expiry itself in UserToken.
@ -44,21 +44,6 @@ defmodule PrymnWeb.UserAuth do
conn conn
end end
# This function renews the session ID and erases the whole
# session to avoid fixation attacks. If there is any data
# in the session you may want to preserve after log in/log out,
# you must explicitly fetch the session data before clearing
# and then immediately set it after clearing, for example:
#
# defp renew_session(conn) do
# preferred_locale = get_session(conn, :preferred_locale)
#
# conn
# |> configure_session(renew: true)
# |> clear_session()
# |> put_session(:preferred_locale, preferred_locale)
# end
#
defp renew_session(conn) do defp renew_session(conn) do
conn conn
|> configure_session(renew: true) |> configure_session(renew: true)
@ -190,9 +175,6 @@ defmodule PrymnWeb.UserAuth do
@doc """ @doc """
Used for routes that require the user to be authenticated. Used for routes that require the user to be authenticated.
If you want to enforce the user email is confirmed before
they use the application at all, here would be a good place.
""" """
def require_authenticated_user(conn, _opts) do def require_authenticated_user(conn, _opts) do
if conn.assigns[:current_user] do if conn.assigns[:current_user] do