defmodule ToweropsWeb.UserRegistrationController do @moduledoc false use ToweropsWeb, :controller alias Towerops.Accounts alias Towerops.Accounts.User alias Towerops.Organizations alias Towerops.Workers.WelcomeEmailWorker alias ToweropsWeb.UserAuth def new(conn, params) do # Check if registering via invitation invitation_token = params["invitation_token"] || params["token"] invitation = invitation_token && Organizations.get_invitation_by_token(invitation_token) changeset = Accounts.change_user_registration(%User{}) render(conn, :new, form: Phoenix.Component.to_form(changeset, as: "user"), invitation: invitation, invitation_token: invitation_token ) end def create(conn, %{"user" => user_params}) do invitation_token = user_params["invitation_token"] || conn.params["invitation_token"] if invitation_token do # Registration via invitation - don't create personal org create_via_invitation(conn, user_params, invitation_token) else # Normal registration - create personal org create_with_organization(conn, user_params) end end defp create_with_organization(conn, user_params) do case Accounts.register_user_with_organization(user_params) do {:ok, user} -> WelcomeEmailWorker.enqueue(user.id) conn |> put_flash(:info, t("Account created successfully.")) |> UserAuth.log_in_user(user) {:error, %Ecto.Changeset{} = changeset} -> render(conn, :new, form: Phoenix.Component.to_form(changeset, as: "user"), invitation: nil, invitation_token: nil ) end end defp create_via_invitation(conn, user_params, invitation_token) do with {:ok, invitation} <- get_valid_invitation(invitation_token), {:ok, user} <- Accounts.register_user(user_params), {:ok, _membership} <- Organizations.accept_invitation(invitation, user.id) do WelcomeEmailWorker.enqueue(user.id) conn |> put_flash(:info, t("Account created successfully. Welcome to %{org}!", org: invitation.organization.name)) |> UserAuth.log_in_user(user) else {:error, :invalid_invitation} -> changeset = Accounts.change_user_registration(%User{}, user_params) conn |> put_flash(:error, t("Invalid or expired invitation link.")) |> render(:new, form: Phoenix.Component.to_form(changeset, as: "user"), invitation: nil, invitation_token: nil ) {:error, %Ecto.Changeset{} = changeset} -> render(conn, :new, form: Phoenix.Component.to_form(changeset, as: "user"), invitation_token: invitation_token ) end end defp get_valid_invitation(token) do case Organizations.get_invitation_by_token(token) do nil -> {:error, :invalid_invitation} invitation -> {:ok, invitation} end end end