Skip to content

Instantly share code, notes, and snippets.

@willricketts
Created June 15, 2018 16:56
Show Gist options
  • Save willricketts/4678dcd63606a8599c3a9f587a8f6f36 to your computer and use it in GitHub Desktop.
Save willricketts/4678dcd63606a8599c3a9f587a8f6f36 to your computer and use it in GitHub Desktop.
defmodule MyApp.ActivationToken do
import Ecto.Query
alias MyApp.Accounts.User
alias MyApp.Repo
@moduledoc """
Responsible for generating uniuqe email activation tokens
"""
@length 64
@query_limit 5
@doc """
Generates a unique random string for email activation
"""
def generate(acc \\ 0) do
@length
|> :crypto.strong_rand_bytes
|> Base.url_encode64
|> binary_part(0, @length)
|> enforce_uniqueness(acc)
end
# Passes the generated token down to `is_unique?` and handles
# the result by either returning the token if unique, or calling
# generate again for another attempt at a unique token
defp enforce_uniqueness(token, acc) do
if acc >= @query_limit do
raise "Error. Something has gone terribly wrong in token generation"
end
case is_unique?(token) do
true -> token
_ -> generate(acc + 1)
end
end
# Passes the generated token down to `users_with_token` and
# verifies that the list returned is less than 1, returning
# a boolean
defp is_unique?(token) do
Enum.count(users_with_token(token)) <= 0
end
# Queries the database for users whose activation token matches
# the newly generated one. Returns a list of those users
defp users_with_token(token) do
Repo.all(
from u in User,
where: u.activation_token == ^token
)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment