make 2fa UI less awful

This commit is contained in:
FloatingGhost 2022-12-16 11:50:25 +00:00
parent ca70d42541
commit 9a320ba814
8 changed files with 163 additions and 100 deletions

3
.gitattributes vendored
View file

@ -7,5 +7,4 @@
*.js.map binary *.js.map binary
*.css binary *.css binary
priv/static/instance/static.css diff=css *.css diff=css
priv/static/static-fe/static-fe.css diff=css

View file

@ -111,8 +111,8 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlug do
["connect-src 'self' blob: ", static_url, ?\s, websocket_url] ["connect-src 'self' blob: ", static_url, ?\s, websocket_url]
end end
style_src = "style-src 'self' '#{nonce_tag}'" style_src = "style-src 'self' 'unsafe-inline'"
font_src = "font-src 'self' '#{nonce_tag}' data:" font_src = "font-src 'self' data:"
script_src = script_src =
if Config.get(:env) == :dev do if Config.get(:env) == :dev do

View file

@ -5,7 +5,7 @@
defmodule Pleroma.Web.Preload do defmodule Pleroma.Web.Preload do
alias Phoenix.HTML alias Phoenix.HTML
def build_tags(_conn, params) do def build_tags(%{assigns: %{csp_nonce: nonce}} = conn, params) do
preload_data = preload_data =
Enum.reduce(Pleroma.Config.get([__MODULE__, :providers], []), %{}, fn parser, acc -> Enum.reduce(Pleroma.Config.get([__MODULE__, :providers], []), %{}, fn parser, acc ->
terms = terms =
@ -20,16 +20,17 @@ defmodule Pleroma.Web.Preload do
rendered_html = rendered_html =
preload_data preload_data
|> Jason.encode!() |> Jason.encode!()
|> build_script_tag() |> build_script_tag(nonce)
|> HTML.safe_to_string() |> HTML.safe_to_string()
rendered_html rendered_html
end end
def build_script_tag(content) do def build_script_tag(content, nonce) do
HTML.Tag.content_tag(:script, HTML.raw(content), HTML.Tag.content_tag(:script, HTML.raw(content),
id: "initial-results", id: "initial-results",
type: "application/json" type: "application/json",
nonce: nonce
) )
end end
end end

View file

@ -1,24 +1,29 @@
<%= if get_flash(@conn, :info) do %> <div>
<p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p> <%= if get_flash(@conn, :info) do %>
<% end %> <p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
<%= if get_flash(@conn, :error) do %> <% end %>
<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p> <%= if get_flash(@conn, :error) do %>
<% end %> <p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
<% end %>
<h2><%= Gettext.dpgettext("static_pages", "mfa recover page title", "Two-factor recovery") %></h2> <div class="panel-heading">
<%= Gettext.dpgettext("static_pages", "mfa recover page title", "Two-factor recovery") %>
<%= form_for @conn, Routes.mfa_verify_path(@conn, :verify), [as: "mfa"], fn f -> %> </div>
<div class="input"> <div class="panel-content">
<%= form_for @conn, Routes.mfa_verify_path(@conn, :verify), [as: "mfa"], fn f -> %>
<div class="input">
<%= label f, :code, Gettext.dpgettext("static_pages", "mfa recover recovery code prompt", "Recovery code") %> <%= label f, :code, Gettext.dpgettext("static_pages", "mfa recover recovery code prompt", "Recovery code") %>
<%= text_input f, :code, [autocomplete: false, autocorrect: "off", autocapitalize: "off", autofocus: true, spellcheck: false] %> <%= text_input f, :code, [autocomplete: false, autocorrect: "off", autocapitalize: "off", autofocus: true, spellcheck: false] %>
<%= hidden_input f, :mfa_token, value: @mfa_token %> <%= hidden_input f, :mfa_token, value: @mfa_token %>
<%= hidden_input f, :state, value: @state %> <%= hidden_input f, :state, value: @state %>
<%= hidden_input f, :redirect_uri, value: @redirect_uri %> <%= hidden_input f, :redirect_uri, value: @redirect_uri %>
<%= hidden_input f, :challenge_type, value: "recovery" %> <%= hidden_input f, :challenge_type, value: "recovery" %>
</div> </div>
<%= submit Gettext.dpgettext("static_pages", "mfa recover verify recovery code button", "Verify") %> <%= submit Gettext.dpgettext("static_pages", "mfa recover verify recovery code button", "Verify") %>
<% end %> <% end %>
<a href="<%= Routes.mfa_path(@conn, :show, %{challenge_type: "totp", mfa_token: @mfa_token, state: @state, redirect_uri: @redirect_uri}) %>"> <a href="<%= Routes.mfa_path(@conn, :show, %{challenge_type: "totp", mfa_token: @mfa_token, state: @state, redirect_uri: @redirect_uri}) %>">
<%= Gettext.dpgettext("static_pages", "mfa recover use 2fa code link", "Enter a two-factor code") %> <%= Gettext.dpgettext("static_pages", "mfa recover use 2fa code link", "Enter a two-factor code") %>
</a> </a>
</div>
</div>

View file

@ -1,24 +1,28 @@
<%= if get_flash(@conn, :info) do %> <div>
<p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p> <%= if get_flash(@conn, :info) do %>
<% end %> <p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
<%= if get_flash(@conn, :error) do %> <% end %>
<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p> <%= if get_flash(@conn, :error) do %>
<% end %> <p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
<% end %>
<h2><%= Gettext.dpgettext("static_pages", "mfa auth page title", "Two-factor authentication") %></h2> <div class="panel-heading">
<%= Gettext.dpgettext("static_pages", "mfa auth page title", "Two-factor authentication") %>
<%= form_for @conn, Routes.mfa_verify_path(@conn, :verify), [as: "mfa"], fn f -> %> </div>
<div class="input"> <div class="panel-content">
<%= form_for @conn, Routes.mfa_verify_path(@conn, :verify), [as: "mfa"], fn f -> %>
<div class="input">
<%= label f, :code, Gettext.dpgettext("static_pages", "mfa auth code prompt", "Authentication code") %> <%= label f, :code, Gettext.dpgettext("static_pages", "mfa auth code prompt", "Authentication code") %>
<%= text_input f, :code, [autocomplete: "one-time-code", autocorrect: "off", autocapitalize: "off", autofocus: true, pattern: "[0-9]*", spellcheck: false] %> <%= text_input f, :code, [autocomplete: "one-time-code", autocorrect: "off", autocapitalize: "off", autofocus: true, pattern: "[0-9]*", spellcheck: false] %>
<%= hidden_input f, :mfa_token, value: @mfa_token %> <%= hidden_input f, :mfa_token, value: @mfa_token %>
<%= hidden_input f, :state, value: @state %> <%= hidden_input f, :state, value: @state %>
<%= hidden_input f, :redirect_uri, value: @redirect_uri %> <%= hidden_input f, :redirect_uri, value: @redirect_uri %>
<%= hidden_input f, :challenge_type, value: "totp" %> <%= hidden_input f, :challenge_type, value: "totp" %>
</div> </div>
<%= submit Gettext.dpgettext("static_pages", "mfa auth verify code button", "Verify") %> <%= submit Gettext.dpgettext("static_pages", "mfa auth verify code button", "Verify") %>
<% end %> <% end %>
<a href="<%= Routes.mfa_path(@conn, :show, %{challenge_type: "recovery", mfa_token: @mfa_token, state: @state, redirect_uri: @redirect_uri}) %>"> <a href="<%= Routes.mfa_path(@conn, :show, %{challenge_type: "recovery", mfa_token: @mfa_token, state: @state, redirect_uri: @redirect_uri}) %>">
<%= Gettext.dpgettext("static_pages", "mfa auth page use recovery code link", "Enter a two-factor recovery code") %> <%= Gettext.dpgettext("static_pages", "mfa auth page use recovery code link", "Enter a two-factor recovery code") %>
</a> </a>
</div>
</div>

View file

@ -1,2 +1,8 @@
<h1><%= Gettext.dpgettext("static_pages", "oauth authorization exists page title", "Authorization exists") %></h1> <div>
<h2><%= raw Gettext.dpgettext("static_pages", "oauth token code message", "Token code is <br>%{token}", token: safe_to_string(html_escape(@token.token))) %></h2> <div class="panel-heading">
<%= Gettext.dpgettext("static_pages", "oauth authorization exists page title", "Authorization exists") %>
</div>
<div class="panel-content">
<%= raw Gettext.dpgettext("static_pages", "oauth token code message", "Token code is <br>%{token}", token: safe_to_string(html_escape(@token.token))) %>
</div>
</div>

View file

@ -10,12 +10,14 @@
<%= if @user do %> <%= if @user do %>
<div class="account-header"> <div class="account-header">
<div class="account-header__banner" style="background-image: url('<%= Pleroma.User.banner_url(@user) %>')"></div> <div class="account-header__banner" style="background-image: url('<%= Pleroma.User.banner_url(@user) %>')"></div>
<div class="account-header__avatar" style="background-image: url('<%= Pleroma.User.avatar_url(@user) %>')"></div> <div class="account-header__avatar" style="background-image: url('<%= Pleroma.User.avatar_url(@user) %>')">
<div class="account-header__meta"> <div class="account-header__meta">
<div class="account-header__display-name"><%= @user.name %></div> <div class="account-header__display-name"><%= @user.name %></div>
<div class="account-header__nickname">@<%= @user.nickname %>@<%= Pleroma.User.get_host(@user) %></div> <div class="account-header__nickname">@<%= @user.nickname %>@<%= Pleroma.User.get_host(@user) %></div>
</div> </div>
</div> </div>
</div>
<% end %> <% end %>
<div class="container__content"> <div class="container__content">
@ -23,19 +25,20 @@
<div class="panel-heading"> <div class="panel-heading">
<p><%= raw Gettext.dpgettext("static_pages", "oauth authorize message", "Application <strong>%{client_name}</strong> is requesting access to your account.", client_name: safe_to_string(html_escape(@app.client_name))) %></p> <p><%= raw Gettext.dpgettext("static_pages", "oauth authorize message", "Application <strong>%{client_name}</strong> is requesting access to your account.", client_name: safe_to_string(html_escape(@app.client_name))) %></p>
</div> </div>
<%= render @view_module, "_scopes.html", Map.merge(assigns, %{form: f}) %>
<% end %> <% end %>
<div class="panel-content">
<%= render @view_module, "_scopes.html", Map.merge(assigns, %{form: f}) %>
<%= if @user do %> <%= if @user do %>
<div class="actions"> <div class="actions">
<a class="button button--cancel" href="/"> <a class="button button-cancel" href="/">
<%= Gettext.dpgettext("static_pages", "oauth authorize cancel button", "Cancel") %> <%= Gettext.dpgettext("static_pages", "oauth authorize cancel button", "Cancel") %>
</a> </a>
<%= submit Gettext.dpgettext("static_pages", "oauth authorize approve button", "Approve"), class: "button--approve" %> <%= submit Gettext.dpgettext("static_pages", "oauth authorize approve button", "Approve"), class: "button--approve" %>
</div> </div>
<% else %> <% else %>
<%= if @params["registration"] in ["true", true] do %> <%= if @params["registration"] in ["true", true] do %>
<h3><%= Gettext.dpgettext("static_pages", "oauth register page title", "This is the first time you visit! Please enter your Pleroma handle.") %></h3> <h3><%= Gettext.dpgettext("static_pages", "oauth register page title", "This is your first visit! Please enter your Akkoma handle.") %></h3>
<p><%= Gettext.dpgettext("static_pages", "oauth register nickname unchangeable warning", "Choose carefully! You won't be able to change this later. You will be able to change your display name, though.") %></p> <p><%= Gettext.dpgettext("static_pages", "oauth register nickname unchangeable warning", "Choose carefully! You won't be able to change this later. You will be able to change your display name, though.") %></p>
<div class="input"> <div class="input">
<%= label f, :nickname, Gettext.dpgettext("static_pages", "oauth register nickname prompt", "Pleroma Handle") %> <%= label f, :nickname, Gettext.dpgettext("static_pages", "oauth register nickname prompt", "Pleroma Handle") %>
@ -56,6 +59,7 @@
<%= submit Gettext.dpgettext("static_pages", "oauth login button", "Log In") %> <%= submit Gettext.dpgettext("static_pages", "oauth login button", "Log In") %>
<% end %> <% end %>
<% end %> <% end %>
</div>
</div> </div>
<%= hidden_input f, :client_id, value: @client_id %> <%= hidden_input f, :client_id, value: @client_id %>

View file

@ -112,3 +112,47 @@ button:hover {
0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset, 0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset,
0px -1px 0px 0px rgba(0, 0, 0, 0.2) inset; 0px -1px 0px 0px rgba(0, 0, 0, 0.2) inset;
} }
.actions {
display: flex;
flex-grow: 1;
}
.actions button,
.actions a.button {
width: auto;
margin-left: 2%;
width: 45%;
text-align: center;
}
.account-header__banner {
width: 100%;
height: 80px;
background-size: cover;
background-position: center;
}
.account-header__avatar {
width: 64px;
height: 64px;
background-size: cover;
background-position: center;
margin: -60px 10px 10px;
border: 6px solid var(--foreground-color);
border-radius: 999px;
}
.account-header__meta {
padding: 12px 20px 17px 70px;
}
.account-header__display-name {
font-size: 20px;
font-weight: bold;
}
.account-header__nickname {
font-size: 14px;
color: var(--muted-text-color);
}