forked from AkkomaGang/akkoma
make 2fa UI less awful
This commit is contained in:
parent
ca70d42541
commit
9a320ba814
8 changed files with 163 additions and 100 deletions
3
.gitattributes
vendored
3
.gitattributes
vendored
|
@ -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
|
|
||||||
|
|
|
@ -111,8 +111,8 @@ defp csp_string(conn) 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
|
||||||
|
|
|
@ -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 @@ def build_tags(_conn, params) 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
|
||||||
|
|
|
@ -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 %>
|
||||||
|
<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>
|
||||||
<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>
|
|
||||||
|
|
|
@ -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 %>
|
||||||
|
<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>
|
<%= submit Gettext.dpgettext("static_pages", "mfa auth verify code button", "Verify") %>
|
||||||
|
<% end %>
|
||||||
<%= form_for @conn, Routes.mfa_verify_path(@conn, :verify), [as: "mfa"], fn f -> %>
|
<a href="<%= Routes.mfa_path(@conn, :show, %{challenge_type: "recovery", mfa_token: @mfa_token, state: @state, redirect_uri: @redirect_uri}) %>">
|
||||||
<div class="input">
|
<%= Gettext.dpgettext("static_pages", "mfa auth page use recovery code link", "Enter a two-factor recovery code") %>
|
||||||
<%= label f, :code, Gettext.dpgettext("static_pages", "mfa auth code prompt", "Authentication code") %>
|
</a>
|
||||||
<%= text_input f, :code, [autocomplete: "one-time-code", autocorrect: "off", autocapitalize: "off", autofocus: true, pattern: "[0-9]*", spellcheck: false] %>
|
</div>
|
||||||
<%= 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>
|
</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>
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -10,11 +10,13 @@
|
||||||
<%= 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 %>
|
||||||
|
|
||||||
|
@ -23,39 +25,41 @@
|
||||||
<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 %>
|
||||||
|
|
||||||
<%= if @user do %>
|
<div class="panel-content">
|
||||||
<div class="actions">
|
<%= render @view_module, "_scopes.html", Map.merge(assigns, %{form: f}) %>
|
||||||
<a class="button button--cancel" href="/">
|
<%= if @user do %>
|
||||||
<%= Gettext.dpgettext("static_pages", "oauth authorize cancel button", "Cancel") %>
|
<div class="actions">
|
||||||
</a>
|
<a class="button button-cancel" href="/">
|
||||||
<%= submit Gettext.dpgettext("static_pages", "oauth authorize approve button", "Approve"), class: "button--approve" %>
|
<%= Gettext.dpgettext("static_pages", "oauth authorize cancel button", "Cancel") %>
|
||||||
</div>
|
</a>
|
||||||
<% else %>
|
<%= submit Gettext.dpgettext("static_pages", "oauth authorize approve button", "Approve"), class: "button--approve" %>
|
||||||
<%= 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>
|
</div>
|
||||||
<%= hidden_input f, :name, value: @params["name"] %>
|
|
||||||
<%= hidden_input f, :password, value: @params["password"] %>
|
|
||||||
<br>
|
|
||||||
<% else %>
|
<% else %>
|
||||||
<div class="input">
|
<%= if @params["registration"] in ["true", true] do %>
|
||||||
<%= label f, :name, Gettext.dpgettext("static_pages", "oauth login username prompt", "Username") %>
|
<h3><%= Gettext.dpgettext("static_pages", "oauth register page title", "This is your first visit! Please enter your Akkoma handle.") %></h3>
|
||||||
<%= text_input f, :name %>
|
<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>
|
<div class="input">
|
||||||
<div class="input">
|
<%= label f, :nickname, Gettext.dpgettext("static_pages", "oauth register nickname prompt", "Pleroma Handle") %>
|
||||||
<%= label f, :password, Gettext.dpgettext("static_pages", "oauth login password prompt", "Password") %>
|
<%= text_input f, :nickname, placeholder: "lain", autocomplete: "username" %>
|
||||||
<%= password_input f, :password %>
|
</div>
|
||||||
</div>
|
<%= hidden_input f, :name, value: @params["name"] %>
|
||||||
<%= submit Gettext.dpgettext("static_pages", "oauth login button", "Log In") %>
|
<%= 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 %>
|
||||||
<% end %>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= hidden_input f, :client_id, value: @client_id %>
|
<%= hidden_input f, :client_id, value: @client_id %>
|
||||||
|
|
|
@ -90,25 +90,69 @@ [type="checkbox"]:checked+label:before {
|
||||||
|
|
||||||
a.button,
|
a.button,
|
||||||
button {
|
button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #1c2a3a;
|
background-color: #1c2a3a;
|
||||||
color: var(--primary-text-color);
|
color: var(--primary-text-color);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 10px 16px;
|
padding: 10px 16px;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
box-shadow: 0px 0px 2px 0px black,
|
box-shadow: 0px 0px 2px 0px black,
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.button:hover,
|
a.button:hover,
|
||||||
button:hover {
|
button:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow: 0px 0px 0px 1px var(--brand-color),
|
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(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);
|
||||||
}
|
}
|
Loading…
Reference in a new issue