Usher (Usher v0.2.0)
View SourceUsher is a web framework-agnostic invitation link management library for any Elixir application with Ecto.
Getting Started
To use Usher in your application, you need to:
- Run the migrations
- Configure Usher with your repo
- Use the functions provided to manage invitations
Database Setup
Generate and run the migration:
mix ecto.gen.migration create_usher_tables
Then add the Usher schema to your migration:
defmodule MyApp.Repo.Migrations.CreateUsherTables do
use Ecto.Migration
import Usher.Migration
def change do
migrate_to_latest()
end
end
For existing installations upgrading to a new version, generate a new migration:
mix ecto.gen.migration upgrade_usher_tables
And use the same migrate_to_latest/0
function - it will automatically detect
your current version and apply only the necessary migrations.
Configuration
In your config/config.exs
(or whichever environment you prefer),
set up the Usher configuration:
config :usher,
repo: MyApp.Repo,
token_length: 16,
default_expires_in: {7, :days},
table_name: "myapp_invitations",
validations: %{
invitation: %{
name_required: false
}
}
All the values above have defaults, which you can find in Usher.Config
.
Basic Usage
# Create an invitation
{:ok, invitation} = Usher.create_invitation()
# Create an invitation with a name
{:ok, invitation} = Usher.create_invitation(%{name: "Team Welcome"})
# Get invitation by token
invitation = Usher.get_invitation_by_token("abc123")
# Validate and consume invitation
case Usher.validate_invitation_token("abc123") do
{:ok, invitation} ->
# Proceed with registration
Usher.increment_joined_count(invitation)
{:error, :invalid_token} ->
# Handle invalid token
{:error, :invitation_expired} ->
# Handle expired token
end
Features
- Token generation using cryptographic functions
- Configurable token length and expiration periods
- Optional name field with configurable validation
- Versioned migration system for safe upgrades
- Framework-agnostic design works with any Ecto-based application
Summary
Functions
Returns an %Ecto.Changeset{}
for tracking invitation changes.
Creates a new invitation with a token and default expiration datetime.
Deletes an invitation.
Gets a single invitation by ID. Raises if not found.
Gets an invitation by token.
Increments the joined count for an invitation.
Builds an invitation URL for the given token and base URL.
Retrieves all invitations.
Validates an invitation token exists and returns the invitation if valid.
Functions
Returns an %Ecto.Changeset{}
for tracking invitation changes.
Options
:require_name
- Whether to require the name field (defaults to false)
Examples
iex> Usher.change_invitation(invitation)
%Ecto.Changeset{data: %Usher.Invitation{}}
iex> Usher.change_invitation(invitation, %{name: "Test"})
%Ecto.Changeset{data: %Usher.Invitation{}}
iex> Usher.change_invitation(invitation, %{}, require_name: true)
%Ecto.Changeset{data: %Usher.Invitation{}, errors: [name: {"can't be blank", _}]}
Creates a new invitation with a token and default expiration datetime.
Attributes
:name
- Name for the invitation:expires_at
- Custom expiration datetime (overrides default):token
- Custom token (overrides generated token)
Options
:require_name
- Whether to require the name field (defaults to false)
Examples
iex> Usher.create_invitation()
{:ok, %Usher.Invitation{token: "abc123...", expires_at: ~U[...]}}
iex> Usher.create_invitation(%{name: "Welcome Team"})
{:ok, %Usher.Invitation{name: "Welcome Team"}}
iex> Usher.create_invitation(%{}, require_name: true)
{:error, %Ecto.Changeset{errors: [name: {"can't be blank", _}]}}
Deletes an invitation.
Examples
iex> Usher.delete_invitation(invitation)
{:ok, %Usher.Invitation{}}
iex> Usher.delete_invitation(bad_invitation)
{:error, %Ecto.Changeset{}}
Gets a single invitation by ID. Raises if not found.
Examples
iex> Usher.get_invitation!(id)
%Usher.Invitation{}
iex> Usher.get_invitation!("nonexistent")
** (Ecto.NoResultsError)
Gets an invitation by token.
Examples
iex> Usher.get_invitation_by_token("valid_token")
%Usher.Invitation{}
iex> Usher.get_invitation_by_token("invalid")
nil
Increments the joined count for an invitation.
This is typically called when a user successfully registers using the invitation.
Examples
iex> Usher.increment_joined_count(invitation)
{:ok, %Usher.Invitation{joined_count: 1}}
Builds an invitation URL for the given token and base URL.
Examples
iex> Usher.invitation_url("abc123", "https://example.com/signup")
"https://example.com/signup?invitation_token=abc123"
Retrieves all invitations.
Examples
iex> Usher.list_invitations()
[%Usher.Invitation{}, ...]
Validates an invitation token exists and returns the invitation if valid.
Returns {:ok, invitation}
if the token exists and hasn't expired.
Returns {:error, reason}
if the token is invalid or expired.
Examples
iex> Usher.validate_invitation_token("valid_token")
{:ok, %Usher.Invitation{}}
iex> Usher.validate_invitation_token("expired_token")
{:error, :invitation_expired}
iex> Usher.validate_invitation_token("invalid_token")
{:error, :invalid_token}