defmodule TarakanWeb.AccountLive.Login do use TarakanWeb, :live_view alias Tarakan.Accounts @impl true def render(assigns) do ~H"""
<.header>

Log in

<:subtitle> <%= if @current_scope && @current_scope.account do %> Confirm it's you, or connect another host. <% else %> One click. No password required. <% end %>
<.icon name="hero-information-circle" class="size-6 shrink-0" />

You are running the local mail adapter.

To see sent emails, visit <.link href="/dev/mailbox" class="underline">the mailbox page.

<.link id="github-login-button" href={~p"/auth/github?#{[return_to: @provider_return_to]}"} class="clip-notch flex h-12 w-full items-center justify-center bg-btn px-4 font-display text-sm uppercase tracking-[0.12em] text-btn-fg transition hover:opacity-90" > Continue with GitHub <.link id="gitlab-login-button" href={~p"/auth/gitlab?#{[return_to: @provider_return_to]}"} class="flex h-12 w-full items-center justify-center border border-strong px-4 font-display text-sm uppercase tracking-[0.12em] text-ink transition hover:bg-panel" > Continue with GitLab
email
<.form :let={f} for={@form} id="login_form_magic" action={~p"/accounts/log-in"} phx-submit="submit_magic" class="space-y-3 border-2 border-strong bg-panel p-6" > <.input readonly={!!(@current_scope && @current_scope.account)} field={f[:email]} type="email" label="Email" autocomplete="username" spellcheck="false" required phx-mounted={JS.focus()} />
Use a password instead <.icon name="hero-chevron-down" class="size-4 transition-transform group-open:rotate-180" /> <.form :let={f} for={@form} id="login_form_password" action={~p"/accounts/log-in"} phx-submit="submit_password" phx-trigger-action={@trigger_submit} class="space-y-3 border-t-2 border-rule bg-panel p-6" > <.input readonly={!!(@current_scope && @current_scope.account)} field={f[:identifier]} type="text" label="Handle or email" autocomplete="username" spellcheck="false" required /> <.input field={@form[:password]} type="password" label="Password" autocomplete="current-password" spellcheck="false" />
""" end @impl true def mount(params, session, socket) do account = get_in(socket.assigns, [:current_scope, Access.key(:account)]) email = Phoenix.Flash.get(socket.assigns.flash, :email) || (account && account.email) identifier = Phoenix.Flash.get(socket.assigns.flash, :identifier) || (account && account.handle) form = to_form(%{"email" => email, "identifier" => identifier}, as: "account") return_to = case params["return_to"] || session["account_return_to"] do path when is_binary(path) -> TarakanWeb.SafeRedirect.local_path(path, nil) _other -> nil end provider_return_to = return_to || if(account, do: ~p"/accounts/settings", else: ~p"/") {:ok, assign(socket, form: form, trigger_submit: false, return_to: return_to, provider_return_to: provider_return_to )} end @impl true def handle_event("submit_password", _params, socket) do {:noreply, assign(socket, :trigger_submit, true)} end def handle_event("submit_magic", %{"account" => %{"email" => email} = params}, socket) do email_key = :crypto.hash(:sha256, email |> String.trim() |> String.downcase()) allowed? = TarakanWeb.BrowserRateLimit.allowed?(:magic_ip, socket.assigns.client_ip) and TarakanWeb.BrowserRateLimit.allowed?(:magic_email, email_key) return_to = case params["return_to"] || socket.assigns.return_to do path when is_binary(path) and path != "" -> TarakanWeb.SafeRedirect.local_path(path, nil) _ -> nil end if allowed? do account = Accounts.get_account_by_email(email) # Delivery runs in the background so response time does not reveal # whether the email is registered. if account && Accounts.access_allowed?(account) do Accounts.deliver_login_instructions_async(account, fn token -> if return_to do url(~p"/accounts/log-in/#{token}?#{[return_to: return_to]}") else url(~p"/accounts/log-in/#{token}") end end) end end info = "If your email is in our system, you will receive instructions for logging in shortly." next = if return_to, do: ~p"/accounts/log-in?#{[return_to: return_to]}", else: ~p"/accounts/log-in" {:noreply, socket |> put_flash(:info, info) |> push_navigate(to: next)} end defp local_mail_adapter? do Application.get_env(:tarakan, Tarakan.Mailer)[:adapter] == Swoosh.Adapters.Local end end