forked from shibao/cannery
		
	improve invites
This commit is contained in:
		@@ -5,7 +5,7 @@ defmodule Lokal.Accounts do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  import Ecto.Query, warn: false
 | 
					  import Ecto.Query, warn: false
 | 
				
			||||||
  alias Lokal.{Mailer, Repo}
 | 
					  alias Lokal.{Mailer, Repo}
 | 
				
			||||||
  alias Lokal.Accounts.{User, UserToken}
 | 
					  alias Lokal.Accounts.{Invite, Invites, User, UserToken}
 | 
				
			||||||
  alias Ecto.{Changeset, Multi}
 | 
					  alias Ecto.{Changeset, Multi}
 | 
				
			||||||
  alias Oban.Job
 | 
					  alias Oban.Job
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,7 +25,9 @@ defmodule Lokal.Accounts do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  """
 | 
					  """
 | 
				
			||||||
  @spec get_user_by_email(email :: String.t()) :: User.t() | nil
 | 
					  @spec get_user_by_email(email :: String.t()) :: User.t() | nil
 | 
				
			||||||
  def get_user_by_email(email) when is_binary(email), do: Repo.get_by(User, email: email)
 | 
					  def get_user_by_email(email) when is_binary(email) do
 | 
				
			||||||
 | 
					    Repo.get_by(User, email: email)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @doc """
 | 
					  @doc """
 | 
				
			||||||
  Gets a user by email and password.
 | 
					  Gets a user by email and password.
 | 
				
			||||||
@@ -64,7 +66,9 @@ defmodule Lokal.Accounts do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  """
 | 
					  """
 | 
				
			||||||
  @spec get_user!(User.t()) :: User.t()
 | 
					  @spec get_user!(User.t()) :: User.t()
 | 
				
			||||||
  def get_user!(id), do: Repo.get!(User, id)
 | 
					  def get_user!(id) do
 | 
				
			||||||
 | 
					    Repo.get!(User, id)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @doc """
 | 
					  @doc """
 | 
				
			||||||
  Returns all users grouped by role.
 | 
					  Returns all users grouped by role.
 | 
				
			||||||
@@ -113,10 +117,18 @@ defmodule Lokal.Accounts do
 | 
				
			|||||||
      :passed
 | 
					      :passed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  """
 | 
					  """
 | 
				
			||||||
  @spec register_user(attrs :: map()) :: {:ok, User.t()} | {:error, User.changeset()}
 | 
					  @spec register_user(attrs :: map(), Invite.token() | nil) ::
 | 
				
			||||||
  def register_user(attrs) do
 | 
					          {:ok, User.t()} | {:error, :invalid_token | User.changeset()}
 | 
				
			||||||
 | 
					  def register_user(attrs, invite_token \\ nil) do
 | 
				
			||||||
    Multi.new()
 | 
					    Multi.new()
 | 
				
			||||||
    |> Multi.one(:users_count, from(u in User, select: count(u.id), distinct: true))
 | 
					    |> Multi.one(:users_count, from(u in User, select: count(u.id), distinct: true))
 | 
				
			||||||
 | 
					    |> Multi.run(:use_invite, fn _changes_so_far, _repo ->
 | 
				
			||||||
 | 
					      if allow_registration?() and invite_token |> is_nil() do
 | 
				
			||||||
 | 
					        {:ok, :invite_not_required}
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        Invites.use_invite(invite_token)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end)
 | 
				
			||||||
    |> Multi.insert(:add_user, fn %{users_count: count} ->
 | 
					    |> Multi.insert(:add_user, fn %{users_count: count} ->
 | 
				
			||||||
      # if no registered users, make first user an admin
 | 
					      # if no registered users, make first user an admin
 | 
				
			||||||
      role = if count == 0, do: :admin, else: :user
 | 
					      role = if count == 0, do: :admin, else: :user
 | 
				
			||||||
@@ -126,6 +138,7 @@ defmodule Lokal.Accounts do
 | 
				
			|||||||
    |> Repo.transaction()
 | 
					    |> Repo.transaction()
 | 
				
			||||||
    |> case do
 | 
					    |> case do
 | 
				
			||||||
      {:ok, %{add_user: user}} -> {:ok, user}
 | 
					      {:ok, %{add_user: user}} -> {:ok, user}
 | 
				
			||||||
 | 
					      {:error, :use_invite, :invalid_token, _changes_so_far} -> {:error, :invalid_token}
 | 
				
			||||||
      {:error, :add_user, changeset, _changes_so_far} -> {:error, changeset}
 | 
					      {:error, :add_user, changeset, _changes_so_far} -> {:error, changeset}
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
@@ -144,8 +157,9 @@ defmodule Lokal.Accounts do
 | 
				
			|||||||
  """
 | 
					  """
 | 
				
			||||||
  @spec change_user_registration() :: User.changeset()
 | 
					  @spec change_user_registration() :: User.changeset()
 | 
				
			||||||
  @spec change_user_registration(attrs :: map()) :: User.changeset()
 | 
					  @spec change_user_registration(attrs :: map()) :: User.changeset()
 | 
				
			||||||
  def change_user_registration(attrs \\ %{}),
 | 
					  def change_user_registration(attrs \\ %{}) do
 | 
				
			||||||
    do: User.registration_changeset(attrs, hash_password: false)
 | 
					    User.registration_changeset(attrs, hash_password: false)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ## Settings
 | 
					  ## Settings
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -160,7 +174,9 @@ defmodule Lokal.Accounts do
 | 
				
			|||||||
  """
 | 
					  """
 | 
				
			||||||
  @spec change_user_email(User.t()) :: User.changeset()
 | 
					  @spec change_user_email(User.t()) :: User.changeset()
 | 
				
			||||||
  @spec change_user_email(User.t(), attrs :: map()) :: User.changeset()
 | 
					  @spec change_user_email(User.t(), attrs :: map()) :: User.changeset()
 | 
				
			||||||
  def change_user_email(user, attrs \\ %{}), do: User.email_changeset(user, attrs)
 | 
					  def change_user_email(user, attrs \\ %{}) do
 | 
				
			||||||
 | 
					    User.email_changeset(user, attrs)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @doc """
 | 
					  @doc """
 | 
				
			||||||
  Returns an `%Changeset{}` for changing the user role.
 | 
					  Returns an `%Changeset{}` for changing the user role.
 | 
				
			||||||
@@ -172,7 +188,9 @@ defmodule Lokal.Accounts do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  """
 | 
					  """
 | 
				
			||||||
  @spec change_user_role(User.t(), User.role()) :: User.changeset()
 | 
					  @spec change_user_role(User.t(), User.role()) :: User.changeset()
 | 
				
			||||||
  def change_user_role(user, role), do: User.role_changeset(user, role)
 | 
					  def change_user_role(user, role) do
 | 
				
			||||||
 | 
					    User.role_changeset(user, role)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @doc """
 | 
					  @doc """
 | 
				
			||||||
  Emulates that the email will change without actually changing
 | 
					  Emulates that the email will change without actually changing
 | 
				
			||||||
@@ -262,8 +280,9 @@ defmodule Lokal.Accounts do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  """
 | 
					  """
 | 
				
			||||||
  @spec change_user_password(User.t(), attrs :: map()) :: User.changeset()
 | 
					  @spec change_user_password(User.t(), attrs :: map()) :: User.changeset()
 | 
				
			||||||
  def change_user_password(user, attrs \\ %{}),
 | 
					  def change_user_password(user, attrs \\ %{}) do
 | 
				
			||||||
    do: User.password_changeset(user, attrs, hash_password: false)
 | 
					    User.password_changeset(user, attrs, hash_password: false)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @doc """
 | 
					  @doc """
 | 
				
			||||||
  Updates the user password.
 | 
					  Updates the user password.
 | 
				
			||||||
@@ -314,7 +333,9 @@ defmodule Lokal.Accounts do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  """
 | 
					  """
 | 
				
			||||||
  @spec change_user_locale(User.t()) :: User.changeset()
 | 
					  @spec change_user_locale(User.t()) :: User.changeset()
 | 
				
			||||||
  def change_user_locale(%{locale: locale} = user), do: User.locale_changeset(user, locale)
 | 
					  def change_user_locale(%{locale: locale} = user) do
 | 
				
			||||||
 | 
					    User.locale_changeset(user, locale)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @doc """
 | 
					  @doc """
 | 
				
			||||||
  Updates the user locale.
 | 
					  Updates the user locale.
 | 
				
			||||||
@@ -328,8 +349,9 @@ defmodule Lokal.Accounts do
 | 
				
			|||||||
  """
 | 
					  """
 | 
				
			||||||
  @spec update_user_locale(User.t(), locale :: String.t()) ::
 | 
					  @spec update_user_locale(User.t(), locale :: String.t()) ::
 | 
				
			||||||
          {:ok, User.t()} | {:error, User.changeset()}
 | 
					          {:ok, User.t()} | {:error, User.changeset()}
 | 
				
			||||||
  def update_user_locale(user, locale),
 | 
					  def update_user_locale(user, locale) do
 | 
				
			||||||
    do: user |> User.locale_changeset(locale) |> Repo.update()
 | 
					    user |> User.locale_changeset(locale) |> Repo.update()
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @doc """
 | 
					  @doc """
 | 
				
			||||||
  Deletes a user. must be performed by an admin or the same user!
 | 
					  Deletes a user. must be performed by an admin or the same user!
 | 
				
			||||||
@@ -346,8 +368,13 @@ defmodule Lokal.Accounts do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  """
 | 
					  """
 | 
				
			||||||
  @spec delete_user!(user_to_delete :: User.t(), User.t()) :: User.t()
 | 
					  @spec delete_user!(user_to_delete :: User.t(), User.t()) :: User.t()
 | 
				
			||||||
  def delete_user!(user, %User{role: :admin}), do: user |> Repo.delete!()
 | 
					  def delete_user!(user, %User{role: :admin}) do
 | 
				
			||||||
  def delete_user!(%User{id: user_id} = user, %User{id: user_id}), do: user |> Repo.delete!()
 | 
					    user |> Repo.delete!()
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def delete_user!(%User{id: user_id} = user, %User{id: user_id}) do
 | 
				
			||||||
 | 
					    user |> Repo.delete!()
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ## Session
 | 
					  ## Session
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -375,7 +402,7 @@ defmodule Lokal.Accounts do
 | 
				
			|||||||
  """
 | 
					  """
 | 
				
			||||||
  @spec delete_session_token(token :: String.t()) :: :ok
 | 
					  @spec delete_session_token(token :: String.t()) :: :ok
 | 
				
			||||||
  def delete_session_token(token) do
 | 
					  def delete_session_token(token) do
 | 
				
			||||||
    Repo.delete_all(UserToken.token_and_context_query(token, "session"))
 | 
					    UserToken.token_and_context_query(token, "session") |> Repo.delete_all()
 | 
				
			||||||
    :ok
 | 
					    :ok
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
defmodule Lokal.Invites.Invite do
 | 
					defmodule Lokal.Accounts.Invite do
 | 
				
			||||||
  @moduledoc """
 | 
					  @moduledoc """
 | 
				
			||||||
  An invite, created by an admin to allow someone to join their instance. An
 | 
					  An invite, created by an admin to allow someone to join their instance. An
 | 
				
			||||||
  invite can be enabled or disabled, and can have an optional number of uses if
 | 
					  invite can be enabled or disabled, and can have an optional number of uses if
 | 
				
			||||||
@@ -8,7 +8,7 @@ defmodule Lokal.Invites.Invite do
 | 
				
			|||||||
  use Ecto.Schema
 | 
					  use Ecto.Schema
 | 
				
			||||||
  import Ecto.Changeset
 | 
					  import Ecto.Changeset
 | 
				
			||||||
  alias Ecto.{Changeset, UUID}
 | 
					  alias Ecto.{Changeset, UUID}
 | 
				
			||||||
  alias Lokal.{Accounts.User, Invites.Invite}
 | 
					  alias Lokal.Accounts.User
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @primary_key {:id, :binary_id, autogenerate: true}
 | 
					  @primary_key {:id, :binary_id, autogenerate: true}
 | 
				
			||||||
  @foreign_key_type :binary_id
 | 
					  @foreign_key_type :binary_id
 | 
				
			||||||
@@ -23,10 +23,10 @@ defmodule Lokal.Invites.Invite do
 | 
				
			|||||||
    timestamps()
 | 
					    timestamps()
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @type t :: %Invite{
 | 
					  @type t :: %__MODULE__{
 | 
				
			||||||
          id: id(),
 | 
					          id: id(),
 | 
				
			||||||
          name: String.t(),
 | 
					          name: String.t(),
 | 
				
			||||||
          token: String.t(),
 | 
					          token: token(),
 | 
				
			||||||
          uses_left: integer() | nil,
 | 
					          uses_left: integer() | nil,
 | 
				
			||||||
          disabled_at: NaiveDateTime.t(),
 | 
					          disabled_at: NaiveDateTime.t(),
 | 
				
			||||||
          user: User.t(),
 | 
					          user: User.t(),
 | 
				
			||||||
@@ -34,24 +34,27 @@ defmodule Lokal.Invites.Invite do
 | 
				
			|||||||
          inserted_at: NaiveDateTime.t(),
 | 
					          inserted_at: NaiveDateTime.t(),
 | 
				
			||||||
          updated_at: NaiveDateTime.t()
 | 
					          updated_at: NaiveDateTime.t()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
  @type new_invite :: %Invite{}
 | 
					  @type new_invite :: %__MODULE__{}
 | 
				
			||||||
  @type id :: UUID.t()
 | 
					  @type id :: UUID.t()
 | 
				
			||||||
 | 
					  @type changeset :: Changeset.t(t() | new_invite())
 | 
				
			||||||
 | 
					  @type token :: String.t()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @doc false
 | 
					  @doc false
 | 
				
			||||||
  @spec create_changeset(new_invite(), attrs :: map()) :: Changeset.t(new_invite())
 | 
					  @spec create_changeset(User.t(), token(), attrs :: map()) :: changeset()
 | 
				
			||||||
  def create_changeset(invite, attrs) do
 | 
					  def create_changeset(%User{id: user_id}, token, attrs) do
 | 
				
			||||||
    invite
 | 
					    %__MODULE__{}
 | 
				
			||||||
    |> cast(attrs, [:name, :token, :uses_left, :disabled_at, :user_id])
 | 
					    |> change(token: token, user_id: user_id)
 | 
				
			||||||
    |> validate_required([:name, :token, :user_id])
 | 
					 | 
				
			||||||
    |> validate_number(:uses_left, greater_than_or_equal_to: 0)
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @doc false
 | 
					 | 
				
			||||||
  @spec update_changeset(t() | new_invite(), attrs :: map()) :: Changeset.t(t() | new_invite())
 | 
					 | 
				
			||||||
  def update_changeset(invite, attrs) do
 | 
					 | 
				
			||||||
    invite
 | 
					 | 
				
			||||||
    |> cast(attrs, [:name, :uses_left, :disabled_at])
 | 
					    |> cast(attrs, [:name, :uses_left, :disabled_at])
 | 
				
			||||||
    |> validate_required([:name, :token, :user_id])
 | 
					    |> validate_required([:name, :token, :user_id])
 | 
				
			||||||
    |> validate_number(:uses_left, greater_than_or_equal_to: 0)
 | 
					    |> validate_number(:uses_left, greater_than_or_equal_to: 0)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @doc false
 | 
				
			||||||
 | 
					  @spec update_changeset(t() | new_invite(), attrs :: map()) :: changeset()
 | 
				
			||||||
 | 
					  def update_changeset(invite, attrs) do
 | 
				
			||||||
 | 
					    invite
 | 
				
			||||||
 | 
					    |> cast(attrs, [:name, :uses_left, :disabled_at])
 | 
				
			||||||
 | 
					    |> validate_required([:name])
 | 
				
			||||||
 | 
					    |> validate_number(:uses_left, greater_than_or_equal_to: 0)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
							
								
								
									
										187
									
								
								lib/lokal/accounts/invites.ex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								lib/lokal/accounts/invites.ex
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,187 @@
 | 
				
			|||||||
 | 
					defmodule Lokal.Accounts.Invites do
 | 
				
			||||||
 | 
					  @moduledoc """
 | 
				
			||||||
 | 
					  The Invites context.
 | 
				
			||||||
 | 
					  """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  import Ecto.Query, warn: false
 | 
				
			||||||
 | 
					  alias Ecto.Multi
 | 
				
			||||||
 | 
					  alias Lokal.Accounts.{Invite, User}
 | 
				
			||||||
 | 
					  alias Lokal.Repo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @invite_token_length 20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @doc """
 | 
				
			||||||
 | 
					  Returns the list of invites.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ## Examples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      iex> list_invites(%User{id: 123, role: :admin})
 | 
				
			||||||
 | 
					      [%Invite{}, ...]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  """
 | 
				
			||||||
 | 
					  @spec list_invites(User.t()) :: [Invite.t()]
 | 
				
			||||||
 | 
					  def list_invites(%User{role: :admin}) do
 | 
				
			||||||
 | 
					    Repo.all(from i in Invite, order_by: i.name)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @doc """
 | 
				
			||||||
 | 
					  Gets a single invite for a user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Raises `Ecto.NoResultsError` if the Invite does not exist.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ## Examples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      iex> get_invite!(123, %User{id: 123, role: :admin})
 | 
				
			||||||
 | 
					      %Invite{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      > get_invite!(456, %User{id: 123, role: :admin})
 | 
				
			||||||
 | 
					      ** (Ecto.NoResultsError)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  """
 | 
				
			||||||
 | 
					  @spec get_invite!(Invite.id(), User.t()) :: Invite.t()
 | 
				
			||||||
 | 
					  def get_invite!(id, %User{role: :admin}) do
 | 
				
			||||||
 | 
					    Repo.get!(Invite, id)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @doc """
 | 
				
			||||||
 | 
					  Returns if an invite token is still valid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ## Examples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      iex> valid_invite_token?("valid_token")
 | 
				
			||||||
 | 
					      %Invite{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      iex> valid_invite_token?("invalid_token")
 | 
				
			||||||
 | 
					      nil
 | 
				
			||||||
 | 
					  """
 | 
				
			||||||
 | 
					  @spec valid_invite_token?(Invite.token() | nil) :: boolean()
 | 
				
			||||||
 | 
					  def valid_invite_token?(token) when token in [nil, ""], do: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def valid_invite_token?(token) do
 | 
				
			||||||
 | 
					    Repo.exists?(
 | 
				
			||||||
 | 
					      from i in Invite,
 | 
				
			||||||
 | 
					        where: i.token == ^token,
 | 
				
			||||||
 | 
					        where: i.disabled_at |> is_nil()
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @doc """
 | 
				
			||||||
 | 
					  Uses invite by decrementing uses_left, or marks invite invalid if it's been
 | 
				
			||||||
 | 
					  completely used.
 | 
				
			||||||
 | 
					  """
 | 
				
			||||||
 | 
					  @spec use_invite(Invite.token()) :: {:ok, Invite.t()} | {:error, :invalid_token}
 | 
				
			||||||
 | 
					  def use_invite(invite_token) do
 | 
				
			||||||
 | 
					    Multi.new()
 | 
				
			||||||
 | 
					    |> Multi.run(:invite, fn _changes_so_far, _repo ->
 | 
				
			||||||
 | 
					      invite_token |> get_invite_by_token()
 | 
				
			||||||
 | 
					    end)
 | 
				
			||||||
 | 
					    |> Multi.update(:decrement_invite, fn %{invite: invite} ->
 | 
				
			||||||
 | 
					      decrement_invite_changeset(invite)
 | 
				
			||||||
 | 
					    end)
 | 
				
			||||||
 | 
					    |> Repo.transaction()
 | 
				
			||||||
 | 
					    |> case do
 | 
				
			||||||
 | 
					      {:ok, %{decrement_invite: invite}} -> {:ok, invite}
 | 
				
			||||||
 | 
					      {:error, :invite, :invalid_token, _changes_so_far} -> {:error, :invalid_token}
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @spec get_invite_by_token(Invite.token()) :: {:ok, Invite.t()} | {:error, :invalid_token}
 | 
				
			||||||
 | 
					  defp get_invite_by_token(token) do
 | 
				
			||||||
 | 
					    Repo.one(
 | 
				
			||||||
 | 
					      from i in Invite,
 | 
				
			||||||
 | 
					        where: i.token == ^token,
 | 
				
			||||||
 | 
					        where: i.disabled_at |> is_nil()
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    |> case do
 | 
				
			||||||
 | 
					      nil -> {:error, :invalid_token}
 | 
				
			||||||
 | 
					      invite -> {:ok, invite}
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @spec decrement_invite_changeset(Invite.t()) :: Invite.changeset()
 | 
				
			||||||
 | 
					  defp decrement_invite_changeset(%Invite{uses_left: nil} = invite) do
 | 
				
			||||||
 | 
					    invite |> Invite.update_changeset(%{})
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  defp decrement_invite_changeset(%Invite{uses_left: 1} = invite) do
 | 
				
			||||||
 | 
					    now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
 | 
				
			||||||
 | 
					    invite |> Invite.update_changeset(%{uses_left: 0, disabled_at: now})
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  defp decrement_invite_changeset(%Invite{uses_left: uses_left} = invite) do
 | 
				
			||||||
 | 
					    invite |> Invite.update_changeset(%{uses_left: uses_left - 1})
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @doc """
 | 
				
			||||||
 | 
					  Creates a invite.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ## Examples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      iex> create_invite(%User{id: 123, role: :admin}, %{field: value})
 | 
				
			||||||
 | 
					      {:ok, %Invite{}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      iex> create_invite(%User{id: 123, role: :admin}, %{field: bad_value})
 | 
				
			||||||
 | 
					      {:error, %Changeset{}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  """
 | 
				
			||||||
 | 
					  @spec create_invite(User.t(), attrs :: map()) ::
 | 
				
			||||||
 | 
					          {:ok, Invite.t()} | {:error, Invite.changeset()}
 | 
				
			||||||
 | 
					  def create_invite(%User{role: :admin} = user, attrs) do
 | 
				
			||||||
 | 
					    token =
 | 
				
			||||||
 | 
					      :crypto.strong_rand_bytes(@invite_token_length)
 | 
				
			||||||
 | 
					      |> Base.url_encode64()
 | 
				
			||||||
 | 
					      |> binary_part(0, @invite_token_length)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Invite.create_changeset(user, token, attrs) |> Repo.insert()
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @doc """
 | 
				
			||||||
 | 
					  Updates a invite.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ## Examples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      iex> update_invite(invite, %{field: new_value}, %User{id: 123, role: :admin})
 | 
				
			||||||
 | 
					      {:ok, %Invite{}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      iex> update_invite(invite, %{field: bad_value}, %User{id: 123, role: :admin})
 | 
				
			||||||
 | 
					      {:error, %Changeset{}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  """
 | 
				
			||||||
 | 
					  @spec update_invite(Invite.t(), attrs :: map(), User.t()) ::
 | 
				
			||||||
 | 
					          {:ok, Invite.t()} | {:error, Invite.changeset()}
 | 
				
			||||||
 | 
					  def update_invite(invite, attrs, %User{role: :admin}) do
 | 
				
			||||||
 | 
					    invite |> Invite.update_changeset(attrs) |> Repo.update()
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @doc """
 | 
				
			||||||
 | 
					  Deletes a invite.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ## Examples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      iex> delete_invite(invite, %User{id: 123, role: :admin})
 | 
				
			||||||
 | 
					      {:ok, %Invite{}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      iex> delete_invite(invite, %User{id: 123, role: :admin})
 | 
				
			||||||
 | 
					      {:error, %Changeset{}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  """
 | 
				
			||||||
 | 
					  @spec delete_invite(Invite.t(), User.t()) ::
 | 
				
			||||||
 | 
					          {:ok, Invite.t()} | {:error, Invite.changeset()}
 | 
				
			||||||
 | 
					  def delete_invite(invite, %User{role: :admin}) do
 | 
				
			||||||
 | 
					    invite |> Repo.delete()
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @doc """
 | 
				
			||||||
 | 
					  Deletes a invite.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ## Examples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      iex> delete_invite(invite, %User{id: 123, role: :admin})
 | 
				
			||||||
 | 
					      %Invite{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  """
 | 
				
			||||||
 | 
					  @spec delete_invite!(Invite.t(), User.t()) :: Invite.t()
 | 
				
			||||||
 | 
					  def delete_invite!(invite, %User{role: :admin}) do
 | 
				
			||||||
 | 
					    invite |> Repo.delete!()
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@@ -7,7 +7,7 @@ defmodule Lokal.Accounts.User do
 | 
				
			|||||||
  import Ecto.Changeset
 | 
					  import Ecto.Changeset
 | 
				
			||||||
  import LokalWeb.Gettext
 | 
					  import LokalWeb.Gettext
 | 
				
			||||||
  alias Ecto.{Changeset, UUID}
 | 
					  alias Ecto.{Changeset, UUID}
 | 
				
			||||||
  alias Lokal.{Accounts.User, Invites.Invite}
 | 
					  alias Lokal.Accounts.{Invite, User}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @derive {Jason.Encoder,
 | 
					  @derive {Jason.Encoder,
 | 
				
			||||||
           only: [
 | 
					           only: [
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,8 @@ defmodule Lokal.Accounts.UserToken do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  use Ecto.Schema
 | 
					  use Ecto.Schema
 | 
				
			||||||
  import Ecto.Query
 | 
					  import Ecto.Query
 | 
				
			||||||
 | 
					  alias Ecto.{Association, UUID}
 | 
				
			||||||
 | 
					  alias Lokal.Accounts.User
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @hash_algorithm :sha256
 | 
					  @hash_algorithm :sha256
 | 
				
			||||||
  @rand_size 32
 | 
					  @rand_size 32
 | 
				
			||||||
@@ -22,11 +24,25 @@ defmodule Lokal.Accounts.UserToken do
 | 
				
			|||||||
    field :token, :binary
 | 
					    field :token, :binary
 | 
				
			||||||
    field :context, :string
 | 
					    field :context, :string
 | 
				
			||||||
    field :sent_to, :string
 | 
					    field :sent_to, :string
 | 
				
			||||||
    belongs_to :user, Lokal.Accounts.User
 | 
					
 | 
				
			||||||
 | 
					    belongs_to :user, User
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    timestamps(updated_at: false)
 | 
					    timestamps(updated_at: false)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @type t :: %__MODULE__{
 | 
				
			||||||
 | 
					          id: id(),
 | 
				
			||||||
 | 
					          token: token(),
 | 
				
			||||||
 | 
					          context: String.t(),
 | 
				
			||||||
 | 
					          sent_to: String.t(),
 | 
				
			||||||
 | 
					          user: User.t() | Association.NotLoaded.t(),
 | 
				
			||||||
 | 
					          user_id: User.id() | nil,
 | 
				
			||||||
 | 
					          inserted_at: NaiveDateTime.t()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					  @type new_user_token :: %__MODULE__{}
 | 
				
			||||||
 | 
					  @type id :: UUID.t()
 | 
				
			||||||
 | 
					  @type token :: binary()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @doc """
 | 
					  @doc """
 | 
				
			||||||
  Generates a token that will be stored in a signed place,
 | 
					  Generates a token that will be stored in a signed place,
 | 
				
			||||||
  such as session or cookie. As they are signed, those
 | 
					  such as session or cookie. As they are signed, those
 | 
				
			||||||
@@ -34,7 +50,7 @@ defmodule Lokal.Accounts.UserToken do
 | 
				
			|||||||
  """
 | 
					  """
 | 
				
			||||||
  def build_session_token(user) do
 | 
					  def build_session_token(user) do
 | 
				
			||||||
    token = :crypto.strong_rand_bytes(@rand_size)
 | 
					    token = :crypto.strong_rand_bytes(@rand_size)
 | 
				
			||||||
    {token, %Lokal.Accounts.UserToken{token: token, context: "session", user_id: user.id}}
 | 
					    {token, %__MODULE__{token: token, context: "session", user_id: user.id}}
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @doc """
 | 
					  @doc """
 | 
				
			||||||
@@ -69,7 +85,7 @@ defmodule Lokal.Accounts.UserToken do
 | 
				
			|||||||
    hashed_token = :crypto.hash(@hash_algorithm, token)
 | 
					    hashed_token = :crypto.hash(@hash_algorithm, token)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {Base.url_encode64(token, padding: false),
 | 
					    {Base.url_encode64(token, padding: false),
 | 
				
			||||||
     %Lokal.Accounts.UserToken{
 | 
					     %__MODULE__{
 | 
				
			||||||
       token: hashed_token,
 | 
					       token: hashed_token,
 | 
				
			||||||
       context: context,
 | 
					       context: context,
 | 
				
			||||||
       sent_to: sent_to,
 | 
					       sent_to: sent_to,
 | 
				
			||||||
@@ -129,17 +145,17 @@ defmodule Lokal.Accounts.UserToken do
 | 
				
			|||||||
  Returns the given token with the given context.
 | 
					  Returns the given token with the given context.
 | 
				
			||||||
  """
 | 
					  """
 | 
				
			||||||
  def token_and_context_query(token, context) do
 | 
					  def token_and_context_query(token, context) do
 | 
				
			||||||
    from Lokal.Accounts.UserToken, where: [token: ^token, context: ^context]
 | 
					    from __MODULE__, where: [token: ^token, context: ^context]
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @doc """
 | 
					  @doc """
 | 
				
			||||||
  Gets all tokens for the given user for the given contexts.
 | 
					  Gets all tokens for the given user for the given contexts.
 | 
				
			||||||
  """
 | 
					  """
 | 
				
			||||||
  def user_and_contexts_query(user, :all) do
 | 
					  def user_and_contexts_query(user, :all) do
 | 
				
			||||||
    from t in Lokal.Accounts.UserToken, where: t.user_id == ^user.id
 | 
					    from t in __MODULE__, where: t.user_id == ^user.id
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def user_and_contexts_query(user, [_ | _] = contexts) do
 | 
					  def user_and_contexts_query(user, [_ | _] = contexts) do
 | 
				
			||||||
    from t in Lokal.Accounts.UserToken, where: t.user_id == ^user.id and t.context in ^contexts
 | 
					    from t in __MODULE__, where: t.user_id == ^user.id and t.context in ^contexts
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,173 +0,0 @@
 | 
				
			|||||||
defmodule Lokal.Invites do
 | 
					 | 
				
			||||||
  @moduledoc """
 | 
					 | 
				
			||||||
  The Invites context.
 | 
					 | 
				
			||||||
  """
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  import Ecto.Query, warn: false
 | 
					 | 
				
			||||||
  alias Ecto.Changeset
 | 
					 | 
				
			||||||
  alias Lokal.{Accounts.User, Invites.Invite, Repo}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @invite_token_length 20
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @doc """
 | 
					 | 
				
			||||||
  Returns the list of invites.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  ## Examples
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      iex> list_invites(%User{id: 123, role: :admin})
 | 
					 | 
				
			||||||
      [%Invite{}, ...]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  """
 | 
					 | 
				
			||||||
  @spec list_invites(User.t()) :: [Invite.t()]
 | 
					 | 
				
			||||||
  def list_invites(%User{role: :admin}) do
 | 
					 | 
				
			||||||
    Repo.all(from i in Invite, order_by: i.name)
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @doc """
 | 
					 | 
				
			||||||
  Gets a single invite.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Raises `Ecto.NoResultsError` if the Invite does not exist.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  ## Examples
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      iex> get_invite!(123, %User{id: 123, role: :admin})
 | 
					 | 
				
			||||||
      %Invite{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      iex> get_invite!(456, %User{id: 123, role: :admin})
 | 
					 | 
				
			||||||
      ** (Ecto.NoResultsError)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  """
 | 
					 | 
				
			||||||
  @spec get_invite!(Invite.id(), User.t()) :: Invite.t()
 | 
					 | 
				
			||||||
  def get_invite!(id, %User{role: :admin}) do
 | 
					 | 
				
			||||||
    Repo.get!(Invite, id)
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @doc """
 | 
					 | 
				
			||||||
  Returns a valid invite or nil based on the attempted token
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  ## Examples
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      iex> get_invite_by_token("valid_token")
 | 
					 | 
				
			||||||
      %Invite{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      iex> get_invite_by_token("invalid_token")
 | 
					 | 
				
			||||||
      nil
 | 
					 | 
				
			||||||
  """
 | 
					 | 
				
			||||||
  @spec get_invite_by_token(token :: String.t() | nil) :: Invite.t() | nil
 | 
					 | 
				
			||||||
  def get_invite_by_token(nil), do: nil
 | 
					 | 
				
			||||||
  def get_invite_by_token(""), do: nil
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def get_invite_by_token(token) do
 | 
					 | 
				
			||||||
    Repo.one(
 | 
					 | 
				
			||||||
      from(i in Invite,
 | 
					 | 
				
			||||||
        where: i.token == ^token and i.disabled_at |> is_nil()
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @doc """
 | 
					 | 
				
			||||||
  Uses invite by decrementing uses_left, or marks invite invalid if it's been
 | 
					 | 
				
			||||||
  completely used.
 | 
					 | 
				
			||||||
  """
 | 
					 | 
				
			||||||
  @spec use_invite!(Invite.t()) :: Invite.t()
 | 
					 | 
				
			||||||
  def use_invite!(%Invite{uses_left: nil} = invite), do: invite
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def use_invite!(%Invite{uses_left: uses_left} = invite) do
 | 
					 | 
				
			||||||
    new_uses_left = uses_left - 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    attrs =
 | 
					 | 
				
			||||||
      if new_uses_left <= 0 do
 | 
					 | 
				
			||||||
        now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
 | 
					 | 
				
			||||||
        %{"uses_left" => 0, "disabled_at" => now}
 | 
					 | 
				
			||||||
      else
 | 
					 | 
				
			||||||
        %{"uses_left" => new_uses_left}
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    invite |> Invite.update_changeset(attrs) |> Repo.update!()
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @doc """
 | 
					 | 
				
			||||||
  Creates a invite.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  ## Examples
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      iex> create_invite(%User{id: 123, role: :admin}, %{field: value})
 | 
					 | 
				
			||||||
      {:ok, %Invite{}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      iex> create_invite(%User{id: 123, role: :admin}, %{field: bad_value})
 | 
					 | 
				
			||||||
      {:error, %Changeset{}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  """
 | 
					 | 
				
			||||||
  @spec create_invite(User.t(), attrs :: map()) ::
 | 
					 | 
				
			||||||
          {:ok, Invite.t()} | {:error, Changeset.t(Invite.new_invite())}
 | 
					 | 
				
			||||||
  def create_invite(%User{id: user_id, role: :admin}, attrs) do
 | 
					 | 
				
			||||||
    token =
 | 
					 | 
				
			||||||
      :crypto.strong_rand_bytes(@invite_token_length)
 | 
					 | 
				
			||||||
      |> Base.url_encode64()
 | 
					 | 
				
			||||||
      |> binary_part(0, @invite_token_length)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    attrs = attrs |> Map.merge(%{"user_id" => user_id, "token" => token})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    %Invite{} |> Invite.create_changeset(attrs) |> Repo.insert()
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @doc """
 | 
					 | 
				
			||||||
  Updates a invite.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  ## Examples
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      iex> update_invite(invite, %{field: new_value}, %User{id: 123, role: :admin})
 | 
					 | 
				
			||||||
      {:ok, %Invite{}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      iex> update_invite(invite, %{field: bad_value}, %User{id: 123, role: :admin})
 | 
					 | 
				
			||||||
      {:error, %Changeset{}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  """
 | 
					 | 
				
			||||||
  @spec update_invite(Invite.t(), attrs :: map(), User.t()) ::
 | 
					 | 
				
			||||||
          {:ok, Invite.t()} | {:error, Changeset.t(Invite.t())}
 | 
					 | 
				
			||||||
  def update_invite(invite, attrs, %User{role: :admin}),
 | 
					 | 
				
			||||||
    do: invite |> Invite.update_changeset(attrs) |> Repo.update()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @doc """
 | 
					 | 
				
			||||||
  Deletes a invite.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  ## Examples
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      iex> delete_invite(invite, %User{id: 123, role: :admin})
 | 
					 | 
				
			||||||
      {:ok, %Invite{}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      iex> delete_invite(invite, %User{id: 123, role: :admin})
 | 
					 | 
				
			||||||
      {:error, %Changeset{}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  """
 | 
					 | 
				
			||||||
  @spec delete_invite(Invite.t(), User.t()) ::
 | 
					 | 
				
			||||||
          {:ok, Invite.t()} | {:error, Changeset.t(Invite.t())}
 | 
					 | 
				
			||||||
  def delete_invite(invite, %User{role: :admin}), do: invite |> Repo.delete()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @doc """
 | 
					 | 
				
			||||||
  Deletes a invite.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  ## Examples
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      iex> delete_invite(invite, %User{id: 123, role: :admin})
 | 
					 | 
				
			||||||
      %Invite{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  """
 | 
					 | 
				
			||||||
  @spec delete_invite!(Invite.t(), User.t()) :: Invite.t()
 | 
					 | 
				
			||||||
  def delete_invite!(invite, %User{role: :admin}), do: invite |> Repo.delete!()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @doc """
 | 
					 | 
				
			||||||
  Returns an `%Changeset{}` for tracking invite changes.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  ## Examples
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      iex> change_invite(invite)
 | 
					 | 
				
			||||||
      %Changeset{data: %Invite{}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  """
 | 
					 | 
				
			||||||
  @spec change_invite(Invite.t() | Invite.new_invite()) ::
 | 
					 | 
				
			||||||
          Changeset.t(Invite.t() | Invite.new_invite())
 | 
					 | 
				
			||||||
  @spec change_invite(Invite.t() | Invite.new_invite(), attrs :: map()) ::
 | 
					 | 
				
			||||||
          Changeset.t(Invite.t() | Invite.new_invite())
 | 
					 | 
				
			||||||
  def change_invite(invite, attrs \\ %{}), do: invite |> Invite.update_changeset(attrs)
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
@@ -1,14 +1,12 @@
 | 
				
			|||||||
defmodule LokalWeb.UserRegistrationController do
 | 
					defmodule LokalWeb.UserRegistrationController do
 | 
				
			||||||
  use LokalWeb, :controller
 | 
					  use LokalWeb, :controller
 | 
				
			||||||
  import LokalWeb.Gettext
 | 
					  import LokalWeb.Gettext
 | 
				
			||||||
  alias Lokal.{Accounts, Invites}
 | 
					  alias Lokal.{Accounts, Accounts.Invites}
 | 
				
			||||||
  alias LokalWeb.{Endpoint, HomeLive}
 | 
					  alias LokalWeb.{Endpoint, HomeLive}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def new(conn, %{"invite" => invite_token}) do
 | 
					  def new(conn, %{"invite" => invite_token}) do
 | 
				
			||||||
    invite = Invites.get_invite_by_token(invite_token)
 | 
					    if Invites.valid_invite_token?(invite_token) do
 | 
				
			||||||
 | 
					      conn |> render_new(invite_token)
 | 
				
			||||||
    if invite do
 | 
					 | 
				
			||||||
      conn |> render_new(invite)
 | 
					 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      conn
 | 
					      conn
 | 
				
			||||||
      |> put_flash(:error, dgettext("errors", "Sorry, this invite was not found or expired"))
 | 
					      |> put_flash(:error, dgettext("errors", "Sorry, this invite was not found or expired"))
 | 
				
			||||||
@@ -27,19 +25,17 @@ defmodule LokalWeb.UserRegistrationController do
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # renders new user registration page
 | 
					  # renders new user registration page
 | 
				
			||||||
  defp render_new(conn, invite \\ nil) do
 | 
					  defp render_new(conn, invite_token \\ nil) do
 | 
				
			||||||
    render(conn, "new.html",
 | 
					    render(conn, "new.html",
 | 
				
			||||||
      changeset: Accounts.change_user_registration(),
 | 
					      changeset: Accounts.change_user_registration(),
 | 
				
			||||||
      invite: invite,
 | 
					      invite_token: invite_token,
 | 
				
			||||||
      page_title: gettext("Register")
 | 
					      page_title: gettext("Register")
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def create(conn, %{"user" => %{"invite_token" => invite_token}} = attrs) do
 | 
					  def create(conn, %{"user" => %{"invite_token" => invite_token}} = attrs) do
 | 
				
			||||||
    invite = Invites.get_invite_by_token(invite_token)
 | 
					    if Invites.valid_invite_token?(invite_token) do
 | 
				
			||||||
 | 
					      conn |> create_user(attrs, invite_token)
 | 
				
			||||||
    if invite do
 | 
					 | 
				
			||||||
      conn |> create_user(attrs, invite)
 | 
					 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      conn
 | 
					      conn
 | 
				
			||||||
      |> put_flash(:error, dgettext("errors", "Sorry, this invite was not found or expired"))
 | 
					      |> put_flash(:error, dgettext("errors", "Sorry, this invite was not found or expired"))
 | 
				
			||||||
@@ -57,13 +53,9 @@ defmodule LokalWeb.UserRegistrationController do
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  defp create_user(conn, %{"user" => user_params}, invite \\ nil) do
 | 
					  defp create_user(conn, %{"user" => user_params}, invite_token \\ nil) do
 | 
				
			||||||
    case Accounts.register_user(user_params) do
 | 
					    case Accounts.register_user(user_params, invite_token) do
 | 
				
			||||||
      {:ok, user} ->
 | 
					      {:ok, user} ->
 | 
				
			||||||
        unless invite |> is_nil() do
 | 
					 | 
				
			||||||
          invite |> Invites.use_invite!()
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Accounts.deliver_user_confirmation_instructions(
 | 
					        Accounts.deliver_user_confirmation_instructions(
 | 
				
			||||||
          user,
 | 
					          user,
 | 
				
			||||||
          &Routes.user_confirmation_url(conn, :confirm, &1)
 | 
					          &Routes.user_confirmation_url(conn, :confirm, &1)
 | 
				
			||||||
@@ -73,8 +65,13 @@ defmodule LokalWeb.UserRegistrationController do
 | 
				
			|||||||
        |> put_flash(:info, dgettext("prompts", "Please check your email to verify your account"))
 | 
					        |> put_flash(:info, dgettext("prompts", "Please check your email to verify your account"))
 | 
				
			||||||
        |> redirect(to: Routes.user_session_path(Endpoint, :new))
 | 
					        |> redirect(to: Routes.user_session_path(Endpoint, :new))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      {:error, :invalid_token} ->
 | 
				
			||||||
 | 
					        conn
 | 
				
			||||||
 | 
					        |> put_flash(:error, dgettext("errors", "Sorry, this invite was not found or expired"))
 | 
				
			||||||
 | 
					        |> redirect(to: Routes.live_path(Endpoint, HomeLive))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      {:error, %Ecto.Changeset{} = changeset} ->
 | 
					      {:error, %Ecto.Changeset{} = changeset} ->
 | 
				
			||||||
        conn |> render("new.html", changeset: changeset, invite: invite)
 | 
					        conn |> render("new.html", changeset: changeset, invite_token: invite_token)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,11 @@
 | 
				
			|||||||
defmodule LokalWeb.InviteLive.FormComponent do
 | 
					defmodule LokalWeb.InviteLive.FormComponent do
 | 
				
			||||||
  @moduledoc """
 | 
					  @moduledoc """
 | 
				
			||||||
  Livecomponent that can update or create an Lokal.Invites.Invite
 | 
					  Livecomponent that can update or create an Lokal.Accounts.Invite
 | 
				
			||||||
  """
 | 
					  """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  use LokalWeb, :live_component
 | 
					  use LokalWeb, :live_component
 | 
				
			||||||
  alias Ecto.Changeset
 | 
					  alias Ecto.Changeset
 | 
				
			||||||
  alias Lokal.{Accounts.User, Invites, Invites.Invite}
 | 
					  alias Lokal.Accounts.{Invite, Invites, User}
 | 
				
			||||||
  alias Phoenix.LiveView.Socket
 | 
					  alias Phoenix.LiveView.Socket
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @impl true
 | 
					  @impl true
 | 
				
			||||||
@@ -13,23 +13,44 @@ defmodule LokalWeb.InviteLive.FormComponent do
 | 
				
			|||||||
          %{:invite => Invite.t(), :current_user => User.t(), optional(any) => any},
 | 
					          %{:invite => Invite.t(), :current_user => User.t(), optional(any) => any},
 | 
				
			||||||
          Socket.t()
 | 
					          Socket.t()
 | 
				
			||||||
        ) :: {:ok, Socket.t()}
 | 
					        ) :: {:ok, Socket.t()}
 | 
				
			||||||
  def update(%{invite: invite} = assigns, socket) do
 | 
					  def update(%{invite: _invite} = assigns, socket) do
 | 
				
			||||||
    {:ok, socket |> assign(assigns) |> assign(:changeset, Invites.change_invite(invite))}
 | 
					    {:ok, socket |> assign(assigns) |> assign_changeset(%{})}
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @impl true
 | 
					  @impl true
 | 
				
			||||||
  def handle_event(
 | 
					  def handle_event("validate", %{"invite" => invite_params}, socket) do
 | 
				
			||||||
        "validate",
 | 
					    {:noreply, socket |> assign_changeset(invite_params)}
 | 
				
			||||||
        %{"invite" => invite_params},
 | 
					 | 
				
			||||||
        %{assigns: %{invite: invite}} = socket
 | 
					 | 
				
			||||||
      ) do
 | 
					 | 
				
			||||||
    {:noreply, socket |> assign(:changeset, invite |> Invites.change_invite(invite_params))}
 | 
					 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def handle_event("save", %{"invite" => invite_params}, %{assigns: %{action: action}} = socket) do
 | 
					  def handle_event("save", %{"invite" => invite_params}, %{assigns: %{action: action}} = socket) do
 | 
				
			||||||
    save_invite(socket, action, invite_params)
 | 
					    save_invite(socket, action, invite_params)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  defp assign_changeset(
 | 
				
			||||||
 | 
					         %{assigns: %{action: action, current_user: user, invite: invite}} = socket,
 | 
				
			||||||
 | 
					         invite_params
 | 
				
			||||||
 | 
					       ) do
 | 
				
			||||||
 | 
					    changeset_action =
 | 
				
			||||||
 | 
					      case action do
 | 
				
			||||||
 | 
					        :new -> :insert
 | 
				
			||||||
 | 
					        :edit -> :update
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    changeset =
 | 
				
			||||||
 | 
					      case action do
 | 
				
			||||||
 | 
					        :new -> Invite.create_changeset(user, "example_token", invite_params)
 | 
				
			||||||
 | 
					        :edit -> invite |> Invite.update_changeset(invite_params)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    changeset =
 | 
				
			||||||
 | 
					      case changeset |> Changeset.apply_action(changeset_action) do
 | 
				
			||||||
 | 
					        {:ok, _data} -> changeset
 | 
				
			||||||
 | 
					        {:error, changeset} -> changeset
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    socket |> assign(:changeset, changeset)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  defp save_invite(
 | 
					  defp save_invite(
 | 
				
			||||||
         %{assigns: %{current_user: current_user, invite: invite, return_to: return_to}} = socket,
 | 
					         %{assigns: %{current_user: current_user, invite: invite, return_to: return_to}} = socket,
 | 
				
			||||||
         :edit,
 | 
					         :edit,
 | 
				
			||||||
@@ -38,10 +59,8 @@ defmodule LokalWeb.InviteLive.FormComponent do
 | 
				
			|||||||
    socket =
 | 
					    socket =
 | 
				
			||||||
      case invite |> Invites.update_invite(invite_params, current_user) do
 | 
					      case invite |> Invites.update_invite(invite_params, current_user) do
 | 
				
			||||||
        {:ok, %{name: invite_name}} ->
 | 
					        {:ok, %{name: invite_name}} ->
 | 
				
			||||||
          prompt =
 | 
					          prompt = dgettext("prompts", "%{name} updated successfully", name: invite_name)
 | 
				
			||||||
            dgettext("prompts", "%{invite_name} updated successfully", invite_name: invite_name)
 | 
					          socket |> put_flash(:info, prompt) |> push_navigate(to: return_to)
 | 
				
			||||||
 | 
					 | 
				
			||||||
          socket |> put_flash(:info, prompt) |> push_redirect(to: return_to)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {:error, %Changeset{} = changeset} ->
 | 
					        {:error, %Changeset{} = changeset} ->
 | 
				
			||||||
          socket |> assign(:changeset, changeset)
 | 
					          socket |> assign(:changeset, changeset)
 | 
				
			||||||
@@ -58,10 +77,8 @@ defmodule LokalWeb.InviteLive.FormComponent do
 | 
				
			|||||||
    socket =
 | 
					    socket =
 | 
				
			||||||
      case current_user |> Invites.create_invite(invite_params) do
 | 
					      case current_user |> Invites.create_invite(invite_params) do
 | 
				
			||||||
        {:ok, %{name: invite_name}} ->
 | 
					        {:ok, %{name: invite_name}} ->
 | 
				
			||||||
          prompt =
 | 
					          prompt = dgettext("prompts", "%{name} created successfully", name: invite_name)
 | 
				
			||||||
            dgettext("prompts", "%{invite_name} created successfully", invite_name: invite_name)
 | 
					          socket |> put_flash(:info, prompt) |> push_navigate(to: return_to)
 | 
				
			||||||
 | 
					 | 
				
			||||||
          socket |> put_flash(:info, prompt) |> push_redirect(to: return_to)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {:error, %Changeset{} = changeset} ->
 | 
					        {:error, %Changeset{} = changeset} ->
 | 
				
			||||||
          socket |> assign(changeset: changeset)
 | 
					          socket |> assign(changeset: changeset)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,12 @@
 | 
				
			|||||||
defmodule LokalWeb.InviteLive.Index do
 | 
					defmodule LokalWeb.InviteLive.Index do
 | 
				
			||||||
  @moduledoc """
 | 
					  @moduledoc """
 | 
				
			||||||
  Liveview to show a Lokal.Invites.Invite index
 | 
					  Liveview to show a Lokal.Accounts.Invite index
 | 
				
			||||||
  """
 | 
					  """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  use LokalWeb, :live_view
 | 
					  use LokalWeb, :live_view
 | 
				
			||||||
  import LokalWeb.Components.{InviteCard, UserCard}
 | 
					  import LokalWeb.Components.{InviteCard, UserCard}
 | 
				
			||||||
  alias Lokal.{Accounts, Invites, Invites.Invite}
 | 
					  alias Lokal.Accounts
 | 
				
			||||||
 | 
					  alias Lokal.Accounts.{Invite, Invites}
 | 
				
			||||||
  alias LokalWeb.{Endpoint, HomeLive}
 | 
					  alias LokalWeb.{Endpoint, HomeLive}
 | 
				
			||||||
  alias Phoenix.LiveView.JS
 | 
					  alias Phoenix.LiveView.JS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,8 +13,8 @@
 | 
				
			|||||||
      <%= dgettext("errors", "Oops, something went wrong! Please check the errors below.") %>
 | 
					      <%= dgettext("errors", "Oops, something went wrong! Please check the errors below.") %>
 | 
				
			||||||
    </p>
 | 
					    </p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <%= if @invite do %>
 | 
					    <%= if @invite_token do %>
 | 
				
			||||||
      <%= hidden_input(f, :invite_token, value: @invite.token) %>
 | 
					      <%= hidden_input(f, :invite_token, value: @invite_token) %>
 | 
				
			||||||
    <% end %>
 | 
					    <% end %>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <%= label(f, :email, class: "title text-lg text-primary-600") %>
 | 
					    <%= label(f, :email, class: "title text-lg text-primary-600") %>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,7 +37,7 @@ msgid "Invite Disabled"
 | 
				
			|||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/components/topbar.ex:61
 | 
					#: lib/lokal_web/components/topbar.ex:61
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:41
 | 
					#: lib/lokal_web/live/invite_live/index.ex:42
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.html.heex:3
 | 
					#: lib/lokal_web/live/invite_live/index.html.heex:3
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Invites"
 | 
					msgid "Invites"
 | 
				
			||||||
@@ -63,7 +63,7 @@ msgstr ""
 | 
				
			|||||||
msgid "Reconnecting..."
 | 
					msgid "Reconnecting..."
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/controllers/user_registration_controller.ex:34
 | 
					#: lib/lokal_web/controllers/user_registration_controller.ex:32
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Register"
 | 
					msgid "Register"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
@@ -94,7 +94,7 @@ msgstr ""
 | 
				
			|||||||
msgid "Disable"
 | 
					msgid "Disable"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:33
 | 
					#: lib/lokal_web/live/invite_live/index.ex:34
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Edit Invite"
 | 
					msgid "Edit Invite"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
@@ -109,7 +109,7 @@ msgstr ""
 | 
				
			|||||||
msgid "Name"
 | 
					msgid "Name"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:37
 | 
					#: lib/lokal_web/live/invite_live/index.ex:38
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "New Invite"
 | 
					msgid "New Invite"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,7 +37,7 @@ msgid "Invite Disabled"
 | 
				
			|||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/components/topbar.ex:61
 | 
					#: lib/lokal_web/components/topbar.ex:61
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:41
 | 
					#: lib/lokal_web/live/invite_live/index.ex:42
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.html.heex:3
 | 
					#: lib/lokal_web/live/invite_live/index.html.heex:3
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Invites"
 | 
					msgid "Invites"
 | 
				
			||||||
@@ -63,7 +63,7 @@ msgstr ""
 | 
				
			|||||||
msgid "Reconnecting..."
 | 
					msgid "Reconnecting..."
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/controllers/user_registration_controller.ex:34
 | 
					#: lib/lokal_web/controllers/user_registration_controller.ex:32
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Register"
 | 
					msgid "Register"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
@@ -94,7 +94,7 @@ msgstr ""
 | 
				
			|||||||
msgid "Disable"
 | 
					msgid "Disable"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:33
 | 
					#: lib/lokal_web/live/invite_live/index.ex:34
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Edit Invite"
 | 
					msgid "Edit Invite"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
@@ -109,7 +109,7 @@ msgstr ""
 | 
				
			|||||||
msgid "Name"
 | 
					msgid "Name"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:37
 | 
					#: lib/lokal_web/live/invite_live/index.ex:38
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "New Invite"
 | 
					msgid "New Invite"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -140,14 +140,15 @@ msgstr ""
 | 
				
			|||||||
msgid "Reset password link is invalid or it has expired."
 | 
					msgid "Reset password link is invalid or it has expired."
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/controllers/user_registration_controller.ex:24
 | 
					#: lib/lokal_web/controllers/user_registration_controller.ex:22
 | 
				
			||||||
#: lib/lokal_web/controllers/user_registration_controller.ex:55
 | 
					#: lib/lokal_web/controllers/user_registration_controller.ex:51
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Sorry, public registration is disabled"
 | 
					msgid "Sorry, public registration is disabled"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/controllers/user_registration_controller.ex:14
 | 
					#: lib/lokal_web/controllers/user_registration_controller.ex:12
 | 
				
			||||||
#: lib/lokal_web/controllers/user_registration_controller.ex:45
 | 
					#: lib/lokal_web/controllers/user_registration_controller.ex:41
 | 
				
			||||||
 | 
					#: lib/lokal_web/controllers/user_registration_controller.ex:70
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Sorry, this invite was not found or expired"
 | 
					msgid "Sorry, this invite was not found or expired"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
@@ -198,7 +199,7 @@ msgstr ""
 | 
				
			|||||||
msgid "must have the @ sign and no spaces"
 | 
					msgid "must have the @ sign and no spaces"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:18
 | 
					#: lib/lokal_web/live/invite_live/index.ex:19
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "You are not authorized to view this page"
 | 
					msgid "You are not authorized to view this page"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -60,7 +60,7 @@ msgstr ""
 | 
				
			|||||||
msgid "Password updated successfully."
 | 
					msgid "Password updated successfully."
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/controllers/user_registration_controller.ex:73
 | 
					#: lib/lokal_web/controllers/user_registration_controller.ex:65
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Please check your email to verify your account"
 | 
					msgid "Please check your email to verify your account"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
@@ -76,7 +76,7 @@ msgstr ""
 | 
				
			|||||||
msgid "Are you sure you want to delete %{email}? This action is permanent!"
 | 
					msgid "Are you sure you want to delete %{email}? This action is permanent!"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:127
 | 
					#: lib/lokal_web/live/invite_live/index.ex:128
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Copied to clipboard"
 | 
					msgid "Copied to clipboard"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
@@ -96,37 +96,27 @@ msgstr ""
 | 
				
			|||||||
msgid "Language updated successfully."
 | 
					msgid "Language updated successfully."
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/form_component.ex:62
 | 
					#: lib/lokal_web/live/invite_live/index.ex:54
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					 | 
				
			||||||
msgid "%{invite_name} created successfully"
 | 
					 | 
				
			||||||
msgstr ""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:53
 | 
					 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "%{invite_name} deleted succesfully"
 | 
					msgid "%{invite_name} deleted succesfully"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:114
 | 
					#: lib/lokal_web/live/invite_live/index.ex:115
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "%{invite_name} disabled succesfully"
 | 
					msgid "%{invite_name} disabled succesfully"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:90
 | 
					#: lib/lokal_web/live/invite_live/index.ex:91
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "%{invite_name} enabled succesfully"
 | 
					msgid "%{invite_name} enabled succesfully"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:68
 | 
					#: lib/lokal_web/live/invite_live/index.ex:69
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "%{invite_name} updated succesfully"
 | 
					msgid "%{invite_name} updated succesfully"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/form_component.ex:42
 | 
					#: lib/lokal_web/live/invite_live/index.ex:140
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					 | 
				
			||||||
msgid "%{invite_name} updated successfully"
 | 
					 | 
				
			||||||
msgstr ""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:139
 | 
					 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "%{user_email} deleted succesfully"
 | 
					msgid "%{user_email} deleted succesfully"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
@@ -145,3 +135,13 @@ msgstr ""
 | 
				
			|||||||
#, elixir-autogen, elixir-format, fuzzy
 | 
					#, elixir-autogen, elixir-format, fuzzy
 | 
				
			||||||
msgid "Register to setup Lokal"
 | 
					msgid "Register to setup Lokal"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: lib/lokal_web/live/invite_live/form_component.ex:80
 | 
				
			||||||
 | 
					#, elixir-autogen, elixir-format, fuzzy
 | 
				
			||||||
 | 
					msgid "%{name} created successfully"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: lib/lokal_web/live/invite_live/form_component.ex:62
 | 
				
			||||||
 | 
					#, elixir-autogen, elixir-format, fuzzy
 | 
				
			||||||
 | 
					msgid "%{name} updated successfully"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -137,14 +137,15 @@ msgstr ""
 | 
				
			|||||||
msgid "Reset password link is invalid or it has expired."
 | 
					msgid "Reset password link is invalid or it has expired."
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/controllers/user_registration_controller.ex:24
 | 
					#: lib/lokal_web/controllers/user_registration_controller.ex:22
 | 
				
			||||||
#: lib/lokal_web/controllers/user_registration_controller.ex:55
 | 
					#: lib/lokal_web/controllers/user_registration_controller.ex:51
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Sorry, public registration is disabled"
 | 
					msgid "Sorry, public registration is disabled"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/controllers/user_registration_controller.ex:14
 | 
					#: lib/lokal_web/controllers/user_registration_controller.ex:12
 | 
				
			||||||
#: lib/lokal_web/controllers/user_registration_controller.ex:45
 | 
					#: lib/lokal_web/controllers/user_registration_controller.ex:41
 | 
				
			||||||
 | 
					#: lib/lokal_web/controllers/user_registration_controller.ex:70
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Sorry, this invite was not found or expired"
 | 
					msgid "Sorry, this invite was not found or expired"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
@@ -195,7 +196,7 @@ msgstr ""
 | 
				
			|||||||
msgid "must have the @ sign and no spaces"
 | 
					msgid "must have the @ sign and no spaces"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:18
 | 
					#: lib/lokal_web/live/invite_live/index.ex:19
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "You are not authorized to view this page"
 | 
					msgid "You are not authorized to view this page"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -60,7 +60,7 @@ msgstr ""
 | 
				
			|||||||
msgid "Password updated successfully."
 | 
					msgid "Password updated successfully."
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/controllers/user_registration_controller.ex:73
 | 
					#: lib/lokal_web/controllers/user_registration_controller.ex:65
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Please check your email to verify your account"
 | 
					msgid "Please check your email to verify your account"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
@@ -76,7 +76,7 @@ msgstr ""
 | 
				
			|||||||
msgid "Are you sure you want to delete %{email}? This action is permanent!"
 | 
					msgid "Are you sure you want to delete %{email}? This action is permanent!"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:127
 | 
					#: lib/lokal_web/live/invite_live/index.ex:128
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Copied to clipboard"
 | 
					msgid "Copied to clipboard"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
@@ -96,37 +96,27 @@ msgstr ""
 | 
				
			|||||||
msgid "Language updated successfully."
 | 
					msgid "Language updated successfully."
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/form_component.ex:62
 | 
					#: lib/lokal_web/live/invite_live/index.ex:54
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					 | 
				
			||||||
msgid "%{invite_name} created successfully"
 | 
					 | 
				
			||||||
msgstr ""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:53
 | 
					 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "%{invite_name} deleted succesfully"
 | 
					msgid "%{invite_name} deleted succesfully"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:114
 | 
					#: lib/lokal_web/live/invite_live/index.ex:115
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "%{invite_name} disabled succesfully"
 | 
					msgid "%{invite_name} disabled succesfully"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:90
 | 
					#: lib/lokal_web/live/invite_live/index.ex:91
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "%{invite_name} enabled succesfully"
 | 
					msgid "%{invite_name} enabled succesfully"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:68
 | 
					#: lib/lokal_web/live/invite_live/index.ex:69
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "%{invite_name} updated succesfully"
 | 
					msgid "%{invite_name} updated succesfully"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/lokal_web/live/invite_live/form_component.ex:42
 | 
					#: lib/lokal_web/live/invite_live/index.ex:140
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					 | 
				
			||||||
msgid "%{invite_name} updated successfully"
 | 
					 | 
				
			||||||
msgstr ""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: lib/lokal_web/live/invite_live/index.ex:139
 | 
					 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "%{user_email} deleted succesfully"
 | 
					msgid "%{user_email} deleted succesfully"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
@@ -145,3 +135,13 @@ msgstr ""
 | 
				
			|||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Register to setup Lokal"
 | 
					msgid "Register to setup Lokal"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: lib/lokal_web/live/invite_live/form_component.ex:80
 | 
				
			||||||
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
 | 
					msgid "%{name} created successfully"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: lib/lokal_web/live/invite_live/form_component.ex:62
 | 
				
			||||||
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
 | 
					msgid "%{name} updated successfully"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										122
									
								
								test/lokal/accounts/invites_test.exs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								test/lokal/accounts/invites_test.exs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,122 @@
 | 
				
			|||||||
 | 
					defmodule Lokal.InvitesTest do
 | 
				
			||||||
 | 
					  @moduledoc """
 | 
				
			||||||
 | 
					  This module tests the Lokal.Accounts.Invites context
 | 
				
			||||||
 | 
					  """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  use Lokal.DataCase
 | 
				
			||||||
 | 
					  alias Ecto.Changeset
 | 
				
			||||||
 | 
					  alias Lokal.Accounts.{Invite, Invites}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @moduletag :invites_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @valid_attrs %{
 | 
				
			||||||
 | 
					    "name" => "some name",
 | 
				
			||||||
 | 
					    "uses_left" => 10
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  @update_attrs %{
 | 
				
			||||||
 | 
					    "name" => "some updated name",
 | 
				
			||||||
 | 
					    "uses_left" => 5
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  @invalid_attrs %{
 | 
				
			||||||
 | 
					    "name" => nil,
 | 
				
			||||||
 | 
					    "token" => nil
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe "invites" do
 | 
				
			||||||
 | 
					    setup do
 | 
				
			||||||
 | 
					      current_user = admin_fixture()
 | 
				
			||||||
 | 
					      {:ok, invite} = Invites.create_invite(current_user, @valid_attrs)
 | 
				
			||||||
 | 
					      [invite: invite, current_user: current_user]
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test "list_invites/0 returns all invites", %{invite: invite, current_user: current_user} do
 | 
				
			||||||
 | 
					      assert Invites.list_invites(current_user) == [invite]
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test "get_invite!/1 returns the invite with given id",
 | 
				
			||||||
 | 
					         %{invite: invite, current_user: current_user} do
 | 
				
			||||||
 | 
					      assert Invites.get_invite!(invite.id, current_user) == invite
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test "valid_invite_token? returns for valid and invalid invite tokens",
 | 
				
			||||||
 | 
					         %{invite: %{token: token}} do
 | 
				
			||||||
 | 
					      refute Invites.valid_invite_token?(nil)
 | 
				
			||||||
 | 
					      refute Invites.valid_invite_token?("")
 | 
				
			||||||
 | 
					      assert Invites.valid_invite_token?(token)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test "valid_invite_token? does not return true for a disabled invite by token",
 | 
				
			||||||
 | 
					         %{invite: %{token: token} = invite, current_user: current_user} do
 | 
				
			||||||
 | 
					      assert Invites.valid_invite_token?(token)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      {:ok, _invite} = Invites.update_invite(invite, %{uses_left: 1}, current_user)
 | 
				
			||||||
 | 
					      {:ok, _invite} = Invites.use_invite(token)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      refute Invites.valid_invite_token?(token)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test "use_invite/1 successfully uses an unlimited invite",
 | 
				
			||||||
 | 
					         %{invite: %{token: token} = invite, current_user: current_user} do
 | 
				
			||||||
 | 
					      {:ok, invite} = Invites.update_invite(invite, %{uses_left: nil}, current_user)
 | 
				
			||||||
 | 
					      assert {:ok, ^invite} = Invites.use_invite(token)
 | 
				
			||||||
 | 
					      assert {:ok, ^invite} = Invites.use_invite(token)
 | 
				
			||||||
 | 
					      assert {:ok, ^invite} = Invites.use_invite(token)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test "use_invite/1 successfully decrements an invite", %{invite: %{token: token}} do
 | 
				
			||||||
 | 
					      assert {:ok, %{uses_left: 9}} = Invites.use_invite(token)
 | 
				
			||||||
 | 
					      assert {:ok, %{uses_left: 8}} = Invites.use_invite(token)
 | 
				
			||||||
 | 
					      assert {:ok, %{uses_left: 7}} = Invites.use_invite(token)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test "use_invite/1 successfully disactivates an invite",
 | 
				
			||||||
 | 
					         %{invite: %{token: token} = invite, current_user: current_user} do
 | 
				
			||||||
 | 
					      {:ok, _invite} = Invites.update_invite(invite, %{uses_left: 1}, current_user)
 | 
				
			||||||
 | 
					      assert {:ok, %{uses_left: 0, disabled_at: disabled_at}} = Invites.use_invite(token)
 | 
				
			||||||
 | 
					      assert not is_nil(disabled_at)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test "use_invite/1 does not work on disactivated invite",
 | 
				
			||||||
 | 
					         %{invite: %{token: token} = invite, current_user: current_user} do
 | 
				
			||||||
 | 
					      {:ok, _invite} = Invites.update_invite(invite, %{uses_left: 1}, current_user)
 | 
				
			||||||
 | 
					      {:ok, _invite} = Invites.use_invite(token)
 | 
				
			||||||
 | 
					      assert {:error, :invalid_token} = Invites.use_invite(token)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test "create_invite/1 with valid data creates a invite",
 | 
				
			||||||
 | 
					         %{current_user: current_user} do
 | 
				
			||||||
 | 
					      assert {:ok, %Invite{} = invite} = Invites.create_invite(current_user, @valid_attrs)
 | 
				
			||||||
 | 
					      assert invite.name == "some name"
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test "create_invite/1 with invalid data returns error changeset",
 | 
				
			||||||
 | 
					         %{current_user: current_user} do
 | 
				
			||||||
 | 
					      assert {:error, %Changeset{}} = Invites.create_invite(current_user, @invalid_attrs)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test "update_invite/2 with valid data updates the invite",
 | 
				
			||||||
 | 
					         %{invite: invite, current_user: current_user} do
 | 
				
			||||||
 | 
					      assert {:ok, %Invite{} = new_invite} =
 | 
				
			||||||
 | 
					               Invites.update_invite(invite, @update_attrs, current_user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert new_invite.name == "some updated name"
 | 
				
			||||||
 | 
					      assert new_invite.uses_left == 5
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test "update_invite/2 with invalid data returns error changeset",
 | 
				
			||||||
 | 
					         %{invite: invite, current_user: current_user} do
 | 
				
			||||||
 | 
					      assert {:error, %Changeset{}} = Invites.update_invite(invite, @invalid_attrs, current_user)
 | 
				
			||||||
 | 
					      assert invite == Invites.get_invite!(invite.id, current_user)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test "delete_invite/1 deletes the invite", %{invite: invite, current_user: current_user} do
 | 
				
			||||||
 | 
					      assert {:ok, %Invite{}} = Invites.delete_invite(invite, current_user)
 | 
				
			||||||
 | 
					      assert_raise Ecto.NoResultsError, fn -> Invites.get_invite!(invite.id, current_user) end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test "delete_invite!/1 deletes the invite", %{invite: invite, current_user: current_user} do
 | 
				
			||||||
 | 
					      assert %Invite{} = Invites.delete_invite!(invite, current_user)
 | 
				
			||||||
 | 
					      assert_raise Ecto.NoResultsError, fn -> Invites.get_invite!(invite.id, current_user) end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@@ -1,76 +0,0 @@
 | 
				
			|||||||
defmodule Lokal.InvitesTest do
 | 
					 | 
				
			||||||
  @moduledoc """
 | 
					 | 
				
			||||||
  This module tests the Invites context
 | 
					 | 
				
			||||||
  """
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  use Lokal.DataCase
 | 
					 | 
				
			||||||
  alias Ecto.Changeset
 | 
					 | 
				
			||||||
  alias Lokal.{Invites, Invites.Invite}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @moduletag :invites_test
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @valid_attrs %{
 | 
					 | 
				
			||||||
    "name" => "some name",
 | 
					 | 
				
			||||||
    "token" => "some token"
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  @update_attrs %{
 | 
					 | 
				
			||||||
    "name" => "some updated name",
 | 
					 | 
				
			||||||
    "token" => "some updated token"
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  @invalid_attrs %{
 | 
					 | 
				
			||||||
    "name" => nil,
 | 
					 | 
				
			||||||
    "token" => nil
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  describe "invites" do
 | 
					 | 
				
			||||||
    setup do
 | 
					 | 
				
			||||||
      current_user = admin_fixture()
 | 
					 | 
				
			||||||
      {:ok, invite} = Invites.create_invite(current_user, @valid_attrs)
 | 
					 | 
				
			||||||
      [invite: invite, current_user: current_user]
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    test "list_invites/0 returns all invites", %{invite: invite, current_user: current_user} do
 | 
					 | 
				
			||||||
      assert Invites.list_invites(current_user) == [invite]
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    test "get_invite!/1 returns the invite with given id",
 | 
					 | 
				
			||||||
         %{invite: invite, current_user: current_user} do
 | 
					 | 
				
			||||||
      assert Invites.get_invite!(invite.id, current_user) == invite
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    test "create_invite/1 with valid data creates a invite",
 | 
					 | 
				
			||||||
         %{current_user: current_user} do
 | 
					 | 
				
			||||||
      assert {:ok, %Invite{} = invite} = Invites.create_invite(current_user, @valid_attrs)
 | 
					 | 
				
			||||||
      assert invite.name == "some name"
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    test "create_invite/1 with invalid data returns error changeset",
 | 
					 | 
				
			||||||
         %{current_user: current_user} do
 | 
					 | 
				
			||||||
      assert {:error, %Changeset{}} = Invites.create_invite(current_user, @invalid_attrs)
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    test "update_invite/2 with valid data updates the invite",
 | 
					 | 
				
			||||||
         %{invite: invite, current_user: current_user} do
 | 
					 | 
				
			||||||
      assert {:ok, %Invite{} = new_invite} =
 | 
					 | 
				
			||||||
               Invites.update_invite(invite, @update_attrs, current_user)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      assert new_invite.name == "some updated name"
 | 
					 | 
				
			||||||
      assert new_invite.token == new_invite.token
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    test "update_invite/2 with invalid data returns error changeset",
 | 
					 | 
				
			||||||
         %{invite: invite, current_user: current_user} do
 | 
					 | 
				
			||||||
      assert {:error, %Changeset{}} = Invites.update_invite(invite, @invalid_attrs, current_user)
 | 
					 | 
				
			||||||
      assert invite == Invites.get_invite!(invite.id, current_user)
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    test "delete_invite/1 deletes the invite", %{invite: invite, current_user: current_user} do
 | 
					 | 
				
			||||||
      assert {:ok, %Invite{}} = Invites.delete_invite(invite, current_user)
 | 
					 | 
				
			||||||
      assert_raise Ecto.NoResultsError, fn -> Invites.get_invite!(invite.id, current_user) end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    test "change_invite/1 returns a invite changeset", %{invite: invite} do
 | 
					 | 
				
			||||||
      assert %Changeset{} = Invites.change_invite(invite)
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
@@ -6,7 +6,7 @@ defmodule LokalWeb.InviteLiveTest do
 | 
				
			|||||||
  use LokalWeb.ConnCase
 | 
					  use LokalWeb.ConnCase
 | 
				
			||||||
  import Phoenix.LiveViewTest
 | 
					  import Phoenix.LiveViewTest
 | 
				
			||||||
  import LokalWeb.Gettext
 | 
					  import LokalWeb.Gettext
 | 
				
			||||||
  alias Lokal.Invites
 | 
					  alias Lokal.Accounts.Invites
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @moduletag :invite_live_test
 | 
					  @moduletag :invite_live_test
 | 
				
			||||||
  @create_attrs %{"name" => "some name"}
 | 
					  @create_attrs %{"name" => "some name"}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user