purge more passkey and gettext updates
This commit is contained in:
parent
02413d5cfd
commit
bd6dad85e1
16 changed files with 473 additions and 173 deletions
|
|
@ -16,8 +16,8 @@ defmodule Towerops.Accounts.LoginAttempt do
|
|||
@primary_key {:id, :binary_id, autogenerate: true}
|
||||
@foreign_key_type :binary_id
|
||||
|
||||
@valid_methods ~w(password magic_link webauthn mobile_qr)
|
||||
@valid_failure_reasons ~w(invalid_credentials invalid_totp invalid_magic_link invalid_passkey account_disabled)
|
||||
@valid_methods ~w(password magic_link mobile_qr)
|
||||
@valid_failure_reasons ~w(invalid_credentials invalid_totp invalid_magic_link account_disabled)
|
||||
|
||||
schema "login_attempts" do
|
||||
field :email, :string
|
||||
|
|
@ -46,7 +46,7 @@ defmodule Towerops.Accounts.LoginAttempt do
|
|||
|
||||
## Required fields
|
||||
- `:success` - Boolean indicating if login was successful
|
||||
- `:method` - Login method (password, magic_link, webauthn, mobile_qr)
|
||||
- `:method` - Login method (password, magic_link, mobile_qr)
|
||||
- `:ip_address` - IP address of the login attempt
|
||||
|
||||
## Conditional validation
|
||||
|
|
|
|||
|
|
@ -1178,7 +1178,6 @@ curl -X DELETE https://towerops.net/api/v1/devices/650e8400-e29b-41d4-a716-44665
|
|||
|
||||
<ul class="mt-4 space-y-2 text-sm text-gray-600 dark:text-gray-400 list-disc list-inside">
|
||||
<li>Profile information (email, name, timezone)</li>
|
||||
<li>WebAuthn credentials and passkeys</li>
|
||||
<li>Organizations and membership roles</li>
|
||||
<li>Devices across all organizations</li>
|
||||
<li>Recent alerts (last 90 days)</li>
|
||||
|
|
|
|||
|
|
@ -3,41 +3,38 @@
|
|||
<div class="text-center">
|
||||
<.header>
|
||||
<%= if @invitation do %>
|
||||
Join {@invitation.organization.name}
|
||||
{t_auth("Join %{organization}", organization: @invitation.organization.name)}
|
||||
<% else %>
|
||||
Register for an account
|
||||
{t_auth("Register for an account")}
|
||||
<% end %>
|
||||
<:subtitle>
|
||||
Already registered?
|
||||
{t_auth("Already registered?")}
|
||||
<.link
|
||||
navigate={~p"/users/log-in"}
|
||||
class="font-semibold text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
|
||||
>
|
||||
Log in
|
||||
{t_auth("Log in")}
|
||||
</.link>
|
||||
to your account now.
|
||||
{t_auth("to your account now.")}
|
||||
</:subtitle>
|
||||
</.header>
|
||||
|
||||
<%= if @invitation do %>
|
||||
<div class="mt-6 rounded-lg bg-blue-50 dark:bg-blue-900/20 p-4 border border-blue-200 dark:border-blue-800">
|
||||
<p class="text-sm text-blue-900 dark:text-blue-100">
|
||||
You've been invited to join
|
||||
<span class="font-semibold">{@invitation.organization.name}</span>
|
||||
as
|
||||
a {@invitation.role}.
|
||||
{t_auth("You've been invited to join %{organization} as a %{role}.", organization: @invitation.organization.name, role: @invitation.role)}
|
||||
</p>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="mt-6 rounded-lg bg-blue-50 dark:bg-blue-900/20 p-4 border border-blue-200 dark:border-blue-800">
|
||||
<p class="text-sm font-medium text-blue-900 dark:text-blue-100">
|
||||
Free tier includes:
|
||||
{t_auth("Free tier includes:")}
|
||||
</p>
|
||||
<ul class="mt-2 text-sm text-blue-800 dark:text-blue-200 space-y-1">
|
||||
<li>✓ Monitor up to 10 devices</li>
|
||||
<li>✓ Real-time alerts and notifications</li>
|
||||
<li>✓ Performance charts and historical data</li>
|
||||
<li>✓ No credit card required</li>
|
||||
<li>{t_auth("✓ Monitor up to 10 devices")}</li>
|
||||
<li>{t_auth("✓ Real-time alerts and notifications")}</li>
|
||||
<li>{t_auth("✓ Performance charts and historical data")}</li>
|
||||
<li>{t_auth("✓ No credit card required")}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
@ -52,7 +49,7 @@
|
|||
<.input
|
||||
field={f[:email]}
|
||||
type="email"
|
||||
label="Email"
|
||||
label={t_auth("Email")}
|
||||
autocomplete="email"
|
||||
required
|
||||
phx-mounted={JS.focus()}
|
||||
|
|
@ -60,7 +57,7 @@
|
|||
<.input
|
||||
field={f[:password]}
|
||||
type="password"
|
||||
label="Password"
|
||||
label={t_auth("Password")}
|
||||
autocomplete="new-password"
|
||||
required
|
||||
/>
|
||||
|
|
@ -70,8 +67,8 @@
|
|||
name="user[organization_name]"
|
||||
value=""
|
||||
type="text"
|
||||
label="Organization Name"
|
||||
placeholder="My Company"
|
||||
label={t_auth("Organization Name")}
|
||||
placeholder={t_auth("My Company")}
|
||||
required
|
||||
/>
|
||||
<% end %>
|
||||
|
|
@ -89,14 +86,7 @@
|
|||
</div>
|
||||
<div class="ml-3 text-sm">
|
||||
<label for="privacy_policy_consent" class="text-zinc-700 dark:text-zinc-300">
|
||||
I agree to the
|
||||
<.link
|
||||
href={~p"/privacy"}
|
||||
target="_blank"
|
||||
class="font-medium text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
|
||||
>
|
||||
Privacy Policy
|
||||
</.link>
|
||||
{t_auth("I agree to the %{link}", link: raw(~s(<a href="/privacy" target="_blank" class="font-medium text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300">#{t_auth("Privacy Policy")}</a>)))}
|
||||
<span class="text-red-600 dark:text-red-400">*</span>
|
||||
</label>
|
||||
</div>
|
||||
|
|
@ -114,22 +104,15 @@
|
|||
</div>
|
||||
<div class="ml-3 text-sm">
|
||||
<label for="terms_of_service_consent" class="text-zinc-700 dark:text-zinc-300">
|
||||
I agree to the
|
||||
<.link
|
||||
href={~p"/terms"}
|
||||
target="_blank"
|
||||
class="font-medium text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
|
||||
>
|
||||
Terms of Service
|
||||
</.link>
|
||||
{t_auth("I agree to the %{link}", link: raw(~s(<a href="/terms" target="_blank" class="font-medium text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300">#{t_auth("Terms of Service")}</a>)))}
|
||||
<span class="text-red-600 dark:text-red-400">*</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<.button phx-disable-with="Creating account..." class="w-full mt-6" variant="primary">
|
||||
{if @invitation, do: "Accept invitation and create account", else: "Create an account"}
|
||||
<.button phx-disable-with={t_auth("Creating account...")} class="w-full mt-6" variant="primary">
|
||||
{if @invitation, do: t_auth("Accept invitation and create account"), else: t_auth("Create an account")}
|
||||
</.button>
|
||||
</.form>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
<div class="mx-auto max-w-sm">
|
||||
<div class="text-center">
|
||||
<.header>
|
||||
Reset password
|
||||
{t_auth("Reset password")}
|
||||
<:subtitle>
|
||||
Enter your new password below.
|
||||
{t_auth("Enter your new password below.")}
|
||||
</:subtitle>
|
||||
</.header>
|
||||
</div>
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
<.input
|
||||
field={f[:password]}
|
||||
type="password"
|
||||
label="New password"
|
||||
label={t_auth("New password")}
|
||||
autocomplete="new-password"
|
||||
required
|
||||
phx-mounted={JS.focus()}
|
||||
|
|
@ -22,13 +22,13 @@
|
|||
<.input
|
||||
field={f[:password_confirmation]}
|
||||
type="password"
|
||||
label="Confirm new password"
|
||||
label={t_auth("Confirm new password")}
|
||||
autocomplete="new-password"
|
||||
required
|
||||
/>
|
||||
<div class="mt-6">
|
||||
<.button class="w-full" variant="primary">
|
||||
Reset password
|
||||
{t_auth("Reset password")}
|
||||
</.button>
|
||||
</div>
|
||||
</.form>
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
navigate={~p"/users/log-in"}
|
||||
class="text-sm font-semibold text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
|
||||
>
|
||||
Back to log in
|
||||
{t_auth("Back to log in")}
|
||||
</.link>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
<div class="mx-auto max-w-sm">
|
||||
<div class="text-center">
|
||||
<.header>
|
||||
Forgot your password?
|
||||
{t_auth("Forgot your password?")}
|
||||
<:subtitle>
|
||||
Enter your email address and we'll send you a link to reset your password.
|
||||
{t_auth("Enter your email address and we'll send you a link to reset your password.")}
|
||||
</:subtitle>
|
||||
</.header>
|
||||
</div>
|
||||
|
|
@ -14,14 +14,14 @@
|
|||
<.input
|
||||
field={f[:email]}
|
||||
type="email"
|
||||
label="Email"
|
||||
label={t_auth("Email")}
|
||||
autocomplete="email"
|
||||
required
|
||||
phx-mounted={JS.focus()}
|
||||
/>
|
||||
<div class="mt-6">
|
||||
<.button class="w-full" variant="primary">
|
||||
Send reset instructions
|
||||
{t_auth("Send reset instructions")}
|
||||
</.button>
|
||||
</div>
|
||||
</.form>
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
navigate={~p"/users/log-in"}
|
||||
class="text-sm font-semibold text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
|
||||
>
|
||||
Back to log in
|
||||
{t_auth("Back to log in")}
|
||||
</.link>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,19 +2,19 @@
|
|||
<div class="mx-auto max-w-sm">
|
||||
<div class="text-center">
|
||||
<.header>
|
||||
Log in
|
||||
{t_auth("Log in")}
|
||||
<:subtitle>
|
||||
<%= if @current_scope do %>
|
||||
You need to reauthenticate to perform sensitive actions on your account.
|
||||
{t_auth("You need to reauthenticate to perform sensitive actions on your account.")}
|
||||
<% else %>
|
||||
Don't have an account?
|
||||
{t_auth("Don't have an account?")}
|
||||
<.link
|
||||
navigate={~p"/users/register"}
|
||||
class="font-semibold text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
|
||||
>
|
||||
Sign up
|
||||
{t_auth("Sign up")}
|
||||
</.link>
|
||||
for an account now.
|
||||
{t_auth("for an account now.")}
|
||||
<% end %>
|
||||
</:subtitle>
|
||||
</.header>
|
||||
|
|
@ -31,10 +31,10 @@
|
|||
/>
|
||||
<div class="ml-3">
|
||||
<p class="text-sm text-blue-700 dark:text-blue-200">
|
||||
You are running the local mail adapter.
|
||||
{t_auth("You are running the local mail adapter.")}
|
||||
</p>
|
||||
<p class="mt-1 text-sm text-blue-700 dark:text-blue-200">
|
||||
To see sent emails, visit <.link href="/dev/mailbox" class="font-medium underline">the mailbox page</.link>.
|
||||
{t_auth("To see sent emails, visit %{link}.", link: raw(~s(<a href="/dev/mailbox" class="font-medium underline">#{t_auth("the mailbox page")}</a>)))}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
readonly={!!@current_scope}
|
||||
field={f[:email]}
|
||||
type="email"
|
||||
label="Email"
|
||||
label={t_auth("Email")}
|
||||
autocomplete="email"
|
||||
required
|
||||
phx-mounted={JS.focus()}
|
||||
|
|
@ -55,7 +55,7 @@
|
|||
<.input
|
||||
field={f[:password]}
|
||||
type="password"
|
||||
label="Password"
|
||||
label={t_auth("Password")}
|
||||
autocomplete="current-password"
|
||||
required
|
||||
/>
|
||||
|
|
@ -64,12 +64,12 @@
|
|||
navigate={~p"/users/reset-password"}
|
||||
class="text-sm font-semibold text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
|
||||
>
|
||||
Forgot password?
|
||||
{t_auth("Forgot password?")}
|
||||
</.link>
|
||||
</div>
|
||||
<div class="space-y-3">
|
||||
<.button class="w-full" variant="primary" name={@form[:remember_me].name} value="true">
|
||||
Log in <span aria-hidden="true">→</span>
|
||||
{t_auth("Log in")} <span aria-hidden="true">→</span>
|
||||
</.button>
|
||||
</div>
|
||||
</.form>
|
||||
|
|
@ -80,42 +80,25 @@
|
|||
</div>
|
||||
<div class="relative flex justify-center text-sm">
|
||||
<span class="bg-gray-50 px-2 text-gray-600 dark:bg-gray-950 dark:text-gray-400">
|
||||
or
|
||||
{t("or")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Alternative: Email Login Link -->
|
||||
<.form :let={f} for={@form} as={:user} id="login_form_magic" action={~p"/users/log-in"}>
|
||||
<.input
|
||||
readonly={!!@current_scope}
|
||||
field={f[:email]}
|
||||
type="email"
|
||||
label="Email"
|
||||
label={t_auth("Email")}
|
||||
autocomplete="email"
|
||||
required
|
||||
/>
|
||||
<.button class="w-full">
|
||||
Send me a login link instead
|
||||
{t_auth("Send me a login link instead")}
|
||||
</.button>
|
||||
</.form>
|
||||
|
||||
<!-- Passkey Login (Discoverable) -->
|
||||
<div>
|
||||
<div
|
||||
id="passkey-discoverable-error"
|
||||
class="hidden mb-3 rounded-lg bg-red-50 p-3 dark:bg-red-900/20"
|
||||
>
|
||||
<p class="text-sm text-red-800 dark:text-red-200"></p>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
id="passkey-discoverable-btn"
|
||||
class="w-full inline-flex items-center justify-center gap-2 rounded-lg bg-gray-100 px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-200 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-600 disabled:opacity-50 disabled:cursor-not-allowed dark:bg-white/10 dark:text-white dark:hover:bg-white/20"
|
||||
>
|
||||
<.icon name="hero-key" class="h-5 w-5" /> Log in with passkey
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Layouts.app>
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<div class="md:col-span-2" phx-update="replace" id="mikrotik-config-section">
|
||||
<div class="md:col-span-2">
|
||||
<.input
|
||||
field={@form[:mikrotik_enabled]}
|
||||
type="checkbox"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ defmodule ToweropsWeb.UserSettingsLive do
|
|||
@moduledoc """
|
||||
LiveView for managing user account settings.
|
||||
|
||||
Allows users to update email, password, manage passkeys, and mobile sessions.
|
||||
Allows users to update email, password, and mobile sessions.
|
||||
"""
|
||||
use ToweropsWeb, :live_view
|
||||
|
||||
|
|
|
|||
|
|
@ -1583,78 +1583,4 @@
|
|||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<!-- Passkey Registration Modal -->
|
||||
<div
|
||||
id="passkey-modal"
|
||||
class="hidden fixed inset-0 z-50 overflow-y-auto"
|
||||
aria-labelledby="modal-title"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
>
|
||||
<div class="flex min-h-screen items-end justify-center px-4 pb-20 pt-4 text-center sm:block sm:p-0">
|
||||
<div
|
||||
class="fixed inset-0 z-0 bg-gray-500 bg-opacity-75 transition-opacity dark:bg-gray-950 dark:bg-opacity-75"
|
||||
aria-hidden="true"
|
||||
>
|
||||
</div>
|
||||
<span
|
||||
class="relative z-10 hidden sm:inline-block sm:h-screen sm:align-middle"
|
||||
aria-hidden="true"
|
||||
>
|
||||
​
|
||||
</span>
|
||||
|
||||
<div class="relative z-10 inline-block transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left align-bottom shadow-xl transition-all dark:bg-gray-800/95 sm:my-8 sm:w-full sm:max-w-lg sm:p-6 sm:align-middle">
|
||||
<div>
|
||||
<div class="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-blue-100 dark:bg-blue-900">
|
||||
<.icon name="hero-key" class="h-6 w-6 text-blue-600 dark:text-blue-400" />
|
||||
</div>
|
||||
<div class="mt-3 text-center sm:mt-5">
|
||||
<h3
|
||||
class="text-lg font-semibold leading-6 text-gray-900 dark:text-white"
|
||||
id="add-passkey-modal-title"
|
||||
>
|
||||
Add Passkey
|
||||
</h3>
|
||||
<div class="mt-2">
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">
|
||||
Give this passkey a name to help you identify it later (e.g., "MacBook Touch ID", "iPhone").
|
||||
</p>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<input
|
||||
type="text"
|
||||
id="passkey-name-input"
|
||||
placeholder="e.g., MacBook Touch ID"
|
||||
class="block w-full rounded-lg border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:border-white/10 dark:bg-gray-800/50 dark:text-white sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
id="passkey-error"
|
||||
class="mt-3 hidden rounded-lg bg-red-50 p-3 dark:bg-red-900/20"
|
||||
>
|
||||
<p class="text-sm text-red-800 dark:text-red-200"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 sm:mt-6 sm:grid sm:grid-flow-row-dense sm:grid-cols-2 sm:gap-3">
|
||||
<button
|
||||
type="button"
|
||||
id="confirm-add-passkey"
|
||||
class="inline-flex w-full justify-center rounded-lg bg-blue-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-blue-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600 disabled:opacity-50 disabled:cursor-not-allowed sm:col-start-2"
|
||||
>
|
||||
Continue
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="cancel-add-passkey"
|
||||
class="mt-3 inline-flex w-full justify-center rounded-lg bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-800/50 dark:text-white dark:ring-white/10 dark:hover:bg-gray-800 sm:col-start-1 sm:mt-0"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Layouts.authenticated>
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ defmodule ToweropsWeb.UserSettingsLive.Helpers do
|
|||
case method do
|
||||
"password" -> {"hero-lock-closed", "Password"}
|
||||
"magic_link" -> {"hero-envelope", "Magic Link"}
|
||||
"webauthn" -> {"hero-key", "Passkey"}
|
||||
"mobile_qr" -> {"hero-device-phone-mobile", "Mobile QR"}
|
||||
_ -> {"hero-question-mark-circle", method}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,3 +13,202 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Language: en\n"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:115
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Accept invitation and create account"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Already registered?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/edit.html.heex:41
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/new.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to log in"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/edit.html.heex:25
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Confirm new password"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:115
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Create an account"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:114
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Creating account..."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:10
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Don't have an account?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:52
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/new.html.heex:17
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:50
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:94
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/new.html.heex:7
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Enter your email address and we'll send you a link to reset your password."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/edit.html.heex:7
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Enter your new password below."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:67
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Forgot password?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/new.html.heex:5
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Forgot your password?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:31
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Free tier includes:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:89
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:107
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I agree to the %{link}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Join %{organization}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:16
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:5
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:72
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Log in"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:71
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "My Company"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/edit.html.heex:17
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "New password"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:70
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Organization Name"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:60
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:58
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:89
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Privacy Policy"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Register for an account"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/edit.html.heex:5
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/edit.html.heex:31
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Reset password"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Send me a login link instead"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/new.html.heex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Send reset instructions"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:15
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Sign up"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:107
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Terms of Service"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "To see sent emails, visit %{link}."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You are running the local mail adapter."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You need to reauthenticate to perform sensitive actions on your account."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:25
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You've been invited to join %{organization} as a %{role}."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:17
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "for an account now."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "the mailbox page"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:18
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "to your account now."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "✓ Monitor up to 10 devices"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "✓ No credit card required"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:36
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "✓ Performance charts and historical data"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:35
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "✓ Real-time alerts and notifications"
|
||||
msgstr ""
|
||||
|
|
|
|||
|
|
@ -86,3 +86,8 @@ msgstr ""
|
|||
#, elixir-autogen, elixir-format
|
||||
msgid "close"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:83
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "or"
|
||||
msgstr ""
|
||||
|
|
|
|||
|
|
@ -10,3 +10,202 @@ msgid ""
|
|||
msgstr ""
|
||||
"Language: en\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:115
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Accept invitation and create account"
|
||||
msgstr "Accept invitation and create account"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Already registered?"
|
||||
msgstr "Already registered?"
|
||||
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/edit.html.heex:41
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/new.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to log in"
|
||||
msgstr "Back to log in"
|
||||
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/edit.html.heex:25
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Confirm new password"
|
||||
msgstr "Confirm new password"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:115
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Create an account"
|
||||
msgstr "Create an account"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:114
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Creating account..."
|
||||
msgstr "Creating account..."
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:10
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Don't have an account?"
|
||||
msgstr "Don't have an account?"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:52
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/new.html.heex:17
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:50
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:94
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Email"
|
||||
msgstr "Email"
|
||||
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/new.html.heex:7
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Enter your email address and we'll send you a link to reset your password."
|
||||
msgstr "Enter your email address and we'll send you a link to reset your password."
|
||||
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/edit.html.heex:7
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Enter your new password below."
|
||||
msgstr "Enter your new password below."
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:67
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Forgot password?"
|
||||
msgstr "Forgot password?"
|
||||
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/new.html.heex:5
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Forgot your password?"
|
||||
msgstr "Forgot your password?"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:31
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Free tier includes:"
|
||||
msgstr "Free tier includes:"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:89
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:107
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I agree to the %{link}"
|
||||
msgstr "I agree to the %{link}"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Join %{organization}"
|
||||
msgstr "Join %{organization}"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:16
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:5
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:72
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Log in"
|
||||
msgstr "Log in"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:71
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "My Company"
|
||||
msgstr "My Company"
|
||||
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/edit.html.heex:17
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "New password"
|
||||
msgstr "New password"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:70
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Organization Name"
|
||||
msgstr "Organization Name"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:60
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:58
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Password"
|
||||
msgstr "Password"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:89
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Privacy Policy"
|
||||
msgstr "Privacy Policy"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Register for an account"
|
||||
msgstr "Register for an account"
|
||||
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/edit.html.heex:5
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/edit.html.heex:31
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Reset password"
|
||||
msgstr "Reset password"
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Send me a login link instead"
|
||||
msgstr "Send me a login link instead"
|
||||
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/new.html.heex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Send reset instructions"
|
||||
msgstr "Send reset instructions"
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:15
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Sign up"
|
||||
msgstr "Sign up"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:107
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Terms of Service"
|
||||
msgstr "Terms of Service"
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "To see sent emails, visit %{link}."
|
||||
msgstr "To see sent emails, visit %{link}."
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You are running the local mail adapter."
|
||||
msgstr "You are running the local mail adapter."
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You need to reauthenticate to perform sensitive actions on your account."
|
||||
msgstr "You need to reauthenticate to perform sensitive actions on your account."
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:25
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You've been invited to join %{organization} as a %{role}."
|
||||
msgstr "You've been invited to join %{organization} as a %{role}."
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:17
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "for an account now."
|
||||
msgstr "for an account now."
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "the mailbox page"
|
||||
msgstr "the mailbox page"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:18
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "to your account now."
|
||||
msgstr "to your account now."
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "✓ Monitor up to 10 devices"
|
||||
msgstr "✓ Monitor up to 10 devices"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "✓ No credit card required"
|
||||
msgstr "✓ No credit card required"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:36
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "✓ Performance charts and historical data"
|
||||
msgstr "✓ Performance charts and historical data"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:35
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "✓ Real-time alerts and notifications"
|
||||
msgstr "✓ Real-time alerts and notifications"
|
||||
|
|
|
|||
|
|
@ -86,3 +86,8 @@ msgstr "We can't find the internet"
|
|||
#, elixir-autogen, elixir-format
|
||||
msgid "close"
|
||||
msgstr "close"
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:83
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "or"
|
||||
msgstr "or"
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ defmodule ToweropsWeb.UserSessionHTMLTest do
|
|||
|
||||
assert html =~ "Log in"
|
||||
assert html =~ "Sign up"
|
||||
assert html =~ "Log in with passkey"
|
||||
assert html =~ "Send me a login link instead"
|
||||
# Password login is now the default (no longer separated by "or use password")
|
||||
assert html =~ "Password"
|
||||
|
|
|
|||
|
|
@ -62,11 +62,12 @@ defmodule ToweropsWeb.Org.SettingsLiveTest do
|
|||
|> log_in_user(user)
|
||||
|> live(~p"/orgs/#{org.slug}/settings")
|
||||
|
||||
assert view
|
||||
|> form("#organization-form", organization: %{name: "Updated Name"})
|
||||
|> render_submit()
|
||||
html =
|
||||
view
|
||||
|> form("#organization-form", organization: %{name: "Updated Name"})
|
||||
|> render_submit()
|
||||
|
||||
assert_redirected(view, ~p"/orgs/#{org.slug}")
|
||||
assert html =~ "Settings saved successfully"
|
||||
|
||||
# Verify the organization was actually updated
|
||||
updated_org = Towerops.Organizations.get_organization!(org.id)
|
||||
|
|
@ -81,11 +82,12 @@ defmodule ToweropsWeb.Org.SettingsLiveTest do
|
|||
|> log_in_user(user)
|
||||
|> live(~p"/orgs/#{org.slug}/settings")
|
||||
|
||||
assert view
|
||||
|> form("#organization-form", organization: %{default_agent_token_id: agent_token.id})
|
||||
|> render_submit()
|
||||
html =
|
||||
view
|
||||
|> form("#organization-form", organization: %{default_agent_token_id: agent_token.id})
|
||||
|> render_submit()
|
||||
|
||||
assert_redirected(view, ~p"/orgs/#{org.slug}")
|
||||
assert html =~ "Settings saved successfully"
|
||||
|
||||
# Verify the default agent was set
|
||||
updated_org = Towerops.Organizations.get_organization!(org.id)
|
||||
|
|
@ -107,11 +109,12 @@ defmodule ToweropsWeb.Org.SettingsLiveTest do
|
|||
|> live(~p"/orgs/#{org.slug}/settings")
|
||||
|
||||
# Now clear it
|
||||
assert view
|
||||
|> form("#organization-form", organization: %{default_agent_token_id: ""})
|
||||
|> render_submit()
|
||||
html =
|
||||
view
|
||||
|> form("#organization-form", organization: %{default_agent_token_id: ""})
|
||||
|> render_submit()
|
||||
|
||||
assert_redirected(view, ~p"/orgs/#{org.slug}")
|
||||
assert html =~ "Settings saved successfully"
|
||||
|
||||
# Verify the default agent was cleared
|
||||
updated_org = Towerops.Organizations.get_organization!(org.id)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue