make 2fa UI less awful
authorFloatingGhost <hannah@coffee-and-dreams.uk>
Fri, 16 Dec 2022 11:50:25 +0000 (11:50 +0000)
committerFloatingGhost <hannah@coffee-and-dreams.uk>
Fri, 16 Dec 2022 11:50:25 +0000 (11:50 +0000)
.gitattributes
lib/pleroma/web/plugs/http_security_plug.ex
lib/pleroma/web/preload.ex
lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex
lib/pleroma/web/templates/o_auth/mfa/totp.html.eex
lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex
lib/pleroma/web/templates/o_auth/o_auth/show.html.eex
priv/static/static-fe/forms.css

index 7273afe43e9bec216cf5e6ff20e3a0d205fe09b0..ac67c53c24f55f13fe5dd141589f091d6d5a5bb9 100644 (file)
@@ -7,5 +7,4 @@
 *.js.map binary
 *.css binary
 
-priv/static/instance/static.css diff=css
-priv/static/static-fe/static-fe.css diff=css
+*.css diff=css
index 6593347caf2a6d8281e701fccaea64bcbca7c0f8..5f0b775bea9e1025b28bdbc03111308743f7c02a 100644 (file)
@@ -111,8 +111,8 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlug do
         ["connect-src 'self' blob: ", static_url, ?\s, websocket_url]
       end
 
-    style_src = "style-src 'self' '#{nonce_tag}'"
-    font_src = "font-src 'self' '#{nonce_tag}' data:"
+    style_src = "style-src 'self' 'unsafe-inline'"
+    font_src = "font-src 'self' data:"
 
     script_src =
       if Config.get(:env) == :dev do
index 34a181e17dae558aa446fea7bc668feff7628180..e554965a26a12f42498ca952103f1835db85fabf 100644 (file)
@@ -5,7 +5,7 @@
 defmodule Pleroma.Web.Preload do
   alias Phoenix.HTML
 
-  def build_tags(_conn, params) do
+  def build_tags(%{assigns: %{csp_nonce: nonce}} = conn, params) do
     preload_data =
       Enum.reduce(Pleroma.Config.get([__MODULE__, :providers], []), %{}, fn parser, acc ->
         terms =
@@ -20,16 +20,17 @@ defmodule Pleroma.Web.Preload do
     rendered_html =
       preload_data
       |> Jason.encode!()
-      |> build_script_tag()
+      |> build_script_tag(nonce)
       |> HTML.safe_to_string()
 
     rendered_html
   end
 
-  def build_script_tag(content) do
+  def build_script_tag(content, nonce) do
     HTML.Tag.content_tag(:script, HTML.raw(content),
       id: "initial-results",
-      type: "application/json"
+      type: "application/json",
+      nonce: nonce
     )
   end
 end
index e45d13bdfae20f1c9e920c4c0512f17c6b9ab4ba..ee40cf2774256c3dfd816021dbb836f2915a5f8f 100644 (file)
@@ -1,24 +1,29 @@
-<%= if get_flash(@conn, :info) do %>
-<p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
-<% end %>
-<%= if get_flash(@conn, :error) do %>
-<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
-<% end %>
+<div>
+  <%= if get_flash(@conn, :info) do %>
+  <p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
+  <% end %>
+  <%= if get_flash(@conn, :error) do %>
+  <p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
+  <% end %>
+  <div class="panel-heading">
+      <%= Gettext.dpgettext("static_pages", "mfa recover page title", "Two-factor recovery") %>
+  </div>
+  <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") %>
+        <%= 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, :state, value: @state %>
+        <%= hidden_input f, :redirect_uri, value: @redirect_uri %>
+        <%= hidden_input f, :challenge_type, value: "recovery" %>
+      </div>
 
-<h2><%= Gettext.dpgettext("static_pages", "mfa recover page title", "Two-factor recovery") %></h2>
+      <%= submit Gettext.dpgettext("static_pages", "mfa recover verify recovery code button", "Verify") %>
+      <% end %>
+      <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") %>
+      </a>
 
-<%= 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") %>
-  <%= 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, :state, value: @state %>
-  <%= hidden_input f, :redirect_uri, value: @redirect_uri %>
-  <%= hidden_input f, :challenge_type, value: "recovery" %>
+  </div>
 </div>
-
-<%= submit Gettext.dpgettext("static_pages", "mfa recover verify recovery code button", "Verify") %>
-<% end %>
-<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") %>
-</a>
index 50e6c04b64dd7d96776e66372a80e40cef6be42b..734e621123769615aa8adb5e74bff6b82938cd14 100644 (file)
@@ -1,24 +1,28 @@
-<%= if get_flash(@conn, :info) do %>
-<p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
-<% end %>
-<%= if get_flash(@conn, :error) do %>
-<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
-<% end %>
+<div>
+  <%= if get_flash(@conn, :info) do %>
+  <p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
+  <% end %>
+  <%= if get_flash(@conn, :error) do %>
+  <p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
+  <% end %>
+  <div class="panel-heading">
+      <%= Gettext.dpgettext("static_pages", "mfa auth page title", "Two-factor authentication") %>
+  </div>
+  <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") %>
+        <%= 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, :state, value: @state %>
+        <%= hidden_input f, :redirect_uri, value: @redirect_uri %>
+        <%= hidden_input f, :challenge_type, value: "totp" %>
+      </div>
 
-<h2><%= Gettext.dpgettext("static_pages", "mfa auth page title", "Two-factor authentication") %></h2>
-
-<%= 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") %>
-  <%= 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, :state, value: @state %>
-  <%= hidden_input f, :redirect_uri, value: @redirect_uri %>
-  <%= hidden_input f, :challenge_type, value: "totp" %>
+      <%= submit Gettext.dpgettext("static_pages", "mfa auth verify code button", "Verify") %>
+      <% end %>
+      <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") %>
+      </a>
+  </div>
 </div>
-
-<%= submit Gettext.dpgettext("static_pages", "mfa auth verify code button", "Verify") %>
-<% end %>
-<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") %>
-</a>
index 754bf2eb0959085cf4d6add5663a82fe2432a310..11671fa1c349dba48153fa4964e105aa4f5f8147 100644 (file)
@@ -1,2 +1,8 @@
-<h1><%= Gettext.dpgettext("static_pages", "oauth authorization exists page title", "Authorization exists") %></h1>
-<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>
+    <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>
index 48c3c5eb92afdf79bf53a25c095f64799760fc7f..986e6ffcecc1c5b31d4362e78096f0dc5484c4ce 100644 (file)
 <%= if @user do %>
   <div class="account-header">
     <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__meta">
+    <div class="account-header__avatar" style="background-image: url('<%= Pleroma.User.avatar_url(@user) %>')">
+      <div class="account-header__meta">
       <div class="account-header__display-name"><%= @user.name %></div>
       <div class="account-header__nickname">@<%= @user.nickname %>@<%= Pleroma.User.get_host(@user) %></div>
     </div>
+    </div>
+
   </div>
 <% end %>
 
     <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>
     </div>
-    <%= render @view_module, "_scopes.html", Map.merge(assigns, %{form: f}) %>
   <% end %>
 
-  <%= if @user do %>
-    <div class="actions">
-      <a class="button button--cancel" href="/">
-        <%= Gettext.dpgettext("static_pages", "oauth authorize cancel button", "Cancel") %>
-      </a>
-      <%= submit Gettext.dpgettext("static_pages", "oauth authorize approve button", "Approve"), class: "button--approve" %>
-    </div>
-  <% else %>
-    <%= 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>
-      <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">
-        <%= label f, :nickname, Gettext.dpgettext("static_pages", "oauth register nickname prompt", "Pleroma Handle") %>
-        <%= text_input f, :nickname, placeholder: "lain", autocomplete: "username" %>
+  <div class="panel-content">
+    <%= render @view_module, "_scopes.html", Map.merge(assigns, %{form: f}) %>
+    <%= if @user do %>
+      <div class="actions">
+        <a class="button button-cancel" href="/">
+          <%= Gettext.dpgettext("static_pages", "oauth authorize cancel button", "Cancel") %>
+        </a>
+        <%= submit Gettext.dpgettext("static_pages", "oauth authorize approve button", "Approve"), class: "button--approve" %>
       </div>
-      <%= hidden_input f, :name, value: @params["name"] %>
-      <%= hidden_input f, :password, value: @params["password"] %>
-      <br>
     <% else %>
-      <div class="input">
-        <%= label f, :name, Gettext.dpgettext("static_pages", "oauth login username prompt", "Username") %>
-        <%= text_input f, :name %>
-      </div>
-      <div class="input">
-        <%= label f, :password, Gettext.dpgettext("static_pages", "oauth login password prompt", "Password") %>
-        <%= password_input f, :password %>
-      </div>
-      <%= submit Gettext.dpgettext("static_pages", "oauth login button", "Log In") %>
+      <%= if @params["registration"] in ["true", true] do %>
+        <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>
+        <div class="input">
+          <%= label f, :nickname, Gettext.dpgettext("static_pages", "oauth register nickname prompt", "Pleroma Handle") %>
+          <%= text_input f, :nickname, placeholder: "lain", autocomplete: "username" %>
+        </div>
+        <%= hidden_input f, :name, value: @params["name"] %>
+        <%= hidden_input f, :password, value: @params["password"] %>
+        <br>
+      <% else %>
+        <div class="input">
+          <%= label f, :name, Gettext.dpgettext("static_pages", "oauth login username prompt", "Username") %>
+          <%= text_input f, :name %>
+        </div>
+        <div class="input">
+          <%= label f, :password, Gettext.dpgettext("static_pages", "oauth login password prompt", "Password") %>
+          <%= password_input f, :password %>
+        </div>
+        <%= submit Gettext.dpgettext("static_pages", "oauth login button", "Log In") %>
+      <% end %>
     <% end %>
-  <% end %>
+  </div>
 </div>
 
 <%= hidden_input f, :client_id, value: @client_id %>
index f7196eef6be09ed99e63838939ab1f89a02ac709..196713ea09a27c6be48b700ce367a7572a3329b0 100644 (file)
@@ -90,25 +90,69 @@ input {
 
 a.button,
 button {
-  width: 100%;
-  background-color: #1c2a3a;
-  color: var(--primary-text-color);
-  border-radius: 4px;
-  border: none;
-  padding: 10px 16px;
-  margin-top: 20px;
-  margin-bottom: 20px;
-  text-transform: uppercase;
-  font-size: 16px;
-  box-shadow: 0px 0px 2px 0px black,
-    0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset,
-    0px -1px 0px 0px rgba(0, 0, 0, 0.2) inset;
+    width: 100%;
+    background-color: #1c2a3a;
+    color: var(--primary-text-color);
+    border-radius: 4px;
+    border: none;
+    padding: 10px 16px;
+    margin-top: 20px;
+    margin-bottom: 20px;
+    text-transform: uppercase;
+    font-size: 16px;
+    box-shadow: 0px 0px 2px 0px black,
+        0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset,
+        0px -1px 0px 0px rgba(0, 0, 0, 0.2) inset;
 }
 
 a.button:hover,
 button:hover {
-  cursor: pointer;
-  box-shadow: 0px 0px 0px 1px var(--brand-color),
-    0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset,
-    0px -1px 0px 0px rgba(0, 0, 0, 0.2) inset;
+    cursor: pointer;
+    box-shadow: 0px 0px 0px 1px var(--brand-color),
+        0px 1px 0px 0px rgba(255, 255, 255, 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);
+}
\ No newline at end of file