Initial commit on Forgejo
Fresh repository history for elektrine/tarakan hosted at https://git.elektrine.com/elektrine/tarakan.
This commit is contained in:
commit
af6077b9c3
455 changed files with 78366 additions and 0 deletions
189
lib/tarakan_web/live/client_authorization_live.ex
Normal file
189
lib/tarakan_web/live/client_authorization_live.ex
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
defmodule TarakanWeb.ClientAuthorizationLive do
|
||||
use TarakanWeb, :live_view
|
||||
|
||||
alias Tarakan.Accounts.ClientAuthorizations
|
||||
|
||||
@impl true
|
||||
def mount(%{"user_code" => user_code}, _session, socket) do
|
||||
actor_key = socket.assigns.current_scope.account.id
|
||||
|
||||
case ClientAuthorizations.get_for_browser(user_code, actor_key) do
|
||||
{:ok, authorization} ->
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(:authorization, authorization)
|
||||
|> assign(
|
||||
:display_code,
|
||||
ClientAuthorizations.display_user_code(authorization.user_code)
|
||||
)
|
||||
|> assign(:page_title, "Authorize Tarakan Client")}
|
||||
|
||||
# Throttled and missing look the same on purpose: telling a grinder which
|
||||
# of its guesses were merely rate limited would hand back the oracle.
|
||||
{:error, _reason} ->
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(:authorization, nil)
|
||||
|> assign(:display_code, user_code)
|
||||
|> assign(:page_title, "Login request expired")}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event(action, _params, %{assigns: %{authorization: nil}} = socket)
|
||||
when action in ["approve", "deny"] do
|
||||
{:noreply, put_flash(socket, :error, "This login request has expired or was already used.")}
|
||||
end
|
||||
|
||||
def handle_event("approve", _params, socket) do
|
||||
account = socket.assigns.current_scope.account
|
||||
|
||||
case ClientAuthorizations.approve(socket.assigns.authorization, account) do
|
||||
{:ok, authorization} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(:authorization, authorization)
|
||||
|> put_flash(:info, "Connected. You can go back to the terminal.")}
|
||||
|
||||
{:error, _reason} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(:authorization, nil)
|
||||
|> put_flash(:error, "This login request expired or was already used.")}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_event("deny", _params, socket) do
|
||||
account = socket.assigns.current_scope.account
|
||||
|
||||
case ClientAuthorizations.deny(socket.assigns.authorization, account) do
|
||||
{:ok, authorization} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(:authorization, authorization)
|
||||
|> put_flash(:info, "Denied.")}
|
||||
|
||||
{:error, _reason} ->
|
||||
{:noreply, assign(socket, :authorization, nil)}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<Layouts.app flash={@flash} current_scope={@current_scope} current_path={assigns[:current_path]}>
|
||||
<Layouts.page id="client-authorization-page" width={:compact}>
|
||||
<section class={[
|
||||
"border-2 border-strong bg-panel p-6 shadow-[8px_8px_0_0_var(--color-rule)] sm:p-8"
|
||||
]}>
|
||||
<div class={["flex items-start gap-4"]}>
|
||||
<div class={[
|
||||
"flex size-11 shrink-0 items-center justify-center bg-signal text-ground"
|
||||
]}>
|
||||
<.icon name="hero-command-line" class={["size-6"]} />
|
||||
</div>
|
||||
<div class={["min-w-0"]}>
|
||||
<h1 class={[
|
||||
"font-display text-2xl font-medium uppercase tracking-[0.02em] text-ink"
|
||||
]}>
|
||||
Connect your terminal
|
||||
</h1>
|
||||
<p class={["mt-2 text-sm leading-6 text-ink-muted"]}>
|
||||
Approving lets the client claim jobs as @{@current_scope.account.handle}.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= cond do %>
|
||||
<% is_nil(@authorization) -> %>
|
||||
<div id="client-authorization-expired" class={["mt-8 border-2 border-rule p-5"]}>
|
||||
<p class={["text-sm text-ink"]}>
|
||||
That code is invalid or expired. Run <code class="font-mono">tarakan login</code>
|
||||
again.
|
||||
</p>
|
||||
</div>
|
||||
<% @authorization.status == "approved" -> %>
|
||||
<div
|
||||
id="client-authorization-approved"
|
||||
class={["mt-8 border-2 border-phosphor bg-ground p-5"]}
|
||||
>
|
||||
<p class={["text-sm font-semibold text-ink"]}>Connected.</p>
|
||||
<p class={["mt-1 text-sm text-ink-muted"]}>Back to your terminal.</p>
|
||||
</div>
|
||||
<% @authorization.status == "denied" -> %>
|
||||
<div id="client-authorization-denied" class={["mt-8 border-2 border-rule p-5"]}>
|
||||
<p class={["text-sm text-ink"]}>Denied. Nothing was granted.</p>
|
||||
</div>
|
||||
<% true -> %>
|
||||
<div id="client-authorization-pending" class={["mt-8"]}>
|
||||
<p class={["text-xs font-semibold text-ink-muted"]}>
|
||||
Code
|
||||
</p>
|
||||
<%!-- Deliberately outside the two-token tracking scale (0.12em
|
||||
labels / 0.02em display): this is a code the user transcribes
|
||||
by hand, and the wide gaps keep characters from running together. --%>
|
||||
<div
|
||||
id="client-authorization-code"
|
||||
class={[
|
||||
"mt-2 border-2 border-strong bg-ground px-4 py-3 font-mono text-2xl tracking-[0.2em] text-ink sm:text-3xl"
|
||||
]}
|
||||
>
|
||||
{@display_code}
|
||||
</div>
|
||||
|
||||
<%!-- The name comes from whoever started the login, not from
|
||||
Tarakan, so it is attributed rather than asserted: a
|
||||
request that calls itself something official must not read
|
||||
as though this page vouches for it. --%>
|
||||
<p class={["mt-5 text-xs font-semibold text-ink-muted"]}>
|
||||
Calls itself
|
||||
</p>
|
||||
<p
|
||||
id="client-authorization-client-name"
|
||||
class={[
|
||||
"mt-1 border-2 border-rule bg-ground px-3 py-2 font-mono text-sm text-ink"
|
||||
]}
|
||||
>
|
||||
{@authorization.client_name}
|
||||
</p>
|
||||
|
||||
<p class={["mt-4 text-sm text-ink-muted"]}>
|
||||
Approving lets it claim jobs and submit reviews as
|
||||
<span class="font-semibold text-ink">@{@current_scope.account.handle}</span>
|
||||
for about 7 days. Revoke anytime in settings.
|
||||
</p>
|
||||
<p class={["mt-2 text-sm text-ink-muted"]}>
|
||||
Only approve this if you just ran
|
||||
<code class="font-mono text-ink">tarakan login</code>
|
||||
yourself and the code above matches your terminal. Nobody at Tarakan will
|
||||
ever ask you for it.
|
||||
</p>
|
||||
|
||||
<div class={["mt-6 grid gap-3 sm:grid-cols-2"]}>
|
||||
<button
|
||||
id="client-authorization-deny-button"
|
||||
phx-click="deny"
|
||||
class={[
|
||||
"flex h-12 items-center justify-center border border-strong px-4 font-display text-sm uppercase tracking-[0.12em] text-ink transition hover:bg-ground"
|
||||
]}
|
||||
>
|
||||
Deny
|
||||
</button>
|
||||
<button
|
||||
id="client-authorization-approve-button"
|
||||
phx-click="approve"
|
||||
class={[
|
||||
"clip-notch flex h-12 items-center justify-center bg-btn px-4 font-display text-sm uppercase tracking-[0.12em] text-btn-fg transition hover:opacity-90"
|
||||
]}
|
||||
>
|
||||
Approve
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</section>
|
||||
</Layouts.page>
|
||||
</Layouts.app>
|
||||
"""
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue