Persist login type preference (SSO/standard) (#5520)

* First pass: store login preference

* Only set login preference if SSO is used

* Change mock DNS to use port 5354 and `domain_id` for parameter

* Make login forms use flash message for error passing

---------

Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
This commit is contained in:
Adam Rutkowski 2025-06-23 12:28:27 +02:00 committed by GitHub
parent a2ed1e04b1
commit e56baeb272
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 208 additions and 101 deletions

View File

@ -94,12 +94,12 @@ sso-stop:
docker remove idp docker remove idp
generate-corefile: generate-corefile:
$(call require, integration_id) $(call require, domain_id)
integration_id=$(integration_id) envsubst < $(PWD)/extra/fixture/Corefile.template > $(PWD)/extra/fixture/Corefile.gen.$(integration_id) domain_id=$(domain_id) envsubst < $(PWD)/extra/fixture/Corefile.template > $(PWD)/extra/fixture/Corefile.gen.$(domain_id)
mock-dns: generate-corefile mock-dns: generate-corefile
$(call require, integration_id) $(call require, domain_id)
docker run --rm -p 5353:53/udp -v $(PWD)/extra/fixture/Corefile.gen.$(integration_id):/Corefile coredns/coredns:latest -conf Corefile docker run --rm -p 5354:53/udp -v $(PWD)/extra/fixture/Corefile.gen.$(domain_id):/Corefile coredns/coredns:latest -conf Corefile
loadtest-server: loadtest-server:
@echo "Ensure your OTP installation is built with --enable-lock-counter" @echo "Ensure your OTP installation is built with --enable-lock-counter"

View File

@ -15,7 +15,7 @@ SHOW_CITIES=true
PADDLE_VENDOR_AUTH_CODE=895e20d4efaec0575bb857f44b183217b332d9592e76e69b8a PADDLE_VENDOR_AUTH_CODE=895e20d4efaec0575bb857f44b183217b332d9592e76e69b8a
PADDLE_VENDOR_ID=3942 PADDLE_VENDOR_ID=3942
SSO_ENABLED=true SSO_ENABLED=true
SSO_VERIFICATION_NAMESERVERS=0.0.0.0:5353 SSO_VERIFICATION_NAMESERVERS=0.0.0.0:5354
GOOGLE_CLIENT_ID=875387135161-l8tp53dpt7fdhdg9m1pc3vl42si95rh0.apps.googleusercontent.com GOOGLE_CLIENT_ID=875387135161-l8tp53dpt7fdhdg9m1pc3vl42si95rh0.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=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 GOOGLE_CLIENT_SECRET=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

View File

@ -1,7 +1,7 @@
. { . {
bind 0.0.0.0 bind 0.0.0.0
template IN TXT plausible.test { template IN TXT plausible.test {
answer "{{ .Name }} 60 IN TXT \"plausible-sso-verification=${integration_id}\"" answer "{{ .Name }} 60 IN TXT \"plausible-sso-verification=${domain_id}\""
fallthrough fallthrough
} }
log log

View File

@ -4,6 +4,7 @@ defmodule PlausibleWeb.SSOController do
require Logger require Logger
alias Plausible.Auth.SSO alias Plausible.Auth.SSO
alias PlausibleWeb.LoginPreference
alias PlausibleWeb.Router.Helpers, as: Routes alias PlausibleWeb.Router.Helpers, as: Routes
@ -11,7 +12,16 @@ defmodule PlausibleWeb.SSOController do
[:owner] when action in [:sso_settings] [:owner] when action in [:sso_settings]
def login_form(conn, params) do def login_form(conn, params) do
render(conn, "login_form.html", error: params["error"]) login_preference = LoginPreference.get(conn)
error = Phoenix.Flash.get(conn.assigns.flash, :login_error)
case {login_preference, params["prefer"], error} do
{nil, nil, nil} ->
redirect(conn, to: Routes.auth_path(conn, :login_form, return_to: params["return_to"]))
_ ->
render(conn, "login_form.html")
end
end end
def login(conn, %{"email" => email} = params) do def login(conn, %{"email" => email} = params) do
@ -29,7 +39,9 @@ defmodule PlausibleWeb.SSOController do
) )
{:error, :not_found} -> {:error, :not_found} ->
render(conn, "login_form.html", error: "Wrong email.") conn
|> put_flash(:login_error, "Wrong email.")
|> redirect(to: Routes.sso_path(conn, :login_form))
end end
end end

View File

@ -48,12 +48,10 @@ defmodule PlausibleWeb.SSO.FakeSAMLAdapter do
PlausibleWeb.UserAuth.log_in_user(conn, identity, params["return_to"]) PlausibleWeb.UserAuth.log_in_user(conn, identity, params["return_to"])
{:error, :not_found} -> {:error, :not_found} ->
Phoenix.Controller.redirect(conn, conn
to: |> Phoenix.Controller.put_flash(:login_error, "Wrong email.")
Routes.sso_path(conn, :login_form, |> Phoenix.Controller.redirect(
error: "Wrong email.", to: Routes.sso_path(conn, :login_form, return_to: params["return_to"])
return_to: params["return_to"]
)
) )
end end
end end

View File

@ -50,12 +50,10 @@ defmodule PlausibleWeb.SSO.RealSAMLAdapter do
|> Phoenix.Controller.redirect(external: url) |> Phoenix.Controller.redirect(external: url)
{:error, :not_found} -> {:error, :not_found} ->
Phoenix.Controller.redirect(conn, conn
to: |> Phoenix.Controller.put_flash(:login_error, "Wrong email.")
Routes.sso_path(conn, :login_form, |> Phoenix.Controller.redirect(
error: "Wrong email.", to: Routes.sso_path(conn, :login_form, return_to: return_to)
return_to: return_to
)
) )
end end
end end
@ -72,9 +70,9 @@ defmodule PlausibleWeb.SSO.RealSAMLAdapter do
|> consume(integration_id, cookie, saml_response, relay_state) |> consume(integration_id, cookie, saml_response, relay_state)
{:error, :session_expired} -> {:error, :session_expired} ->
Phoenix.Controller.redirect(conn, conn
to: Routes.sso_path(conn, :login_form, error: "Session expired.") |> Phoenix.Controller.put_flash(:login_error, "Session expired.")
) |> Phoenix.Controller.redirect(to: Routes.sso_path(conn, :login_form))
end end
end end
@ -105,12 +103,10 @@ defmodule PlausibleWeb.SSO.RealSAMLAdapter do
PlausibleWeb.UserAuth.log_in_user(conn, identity, cookie.return_to) PlausibleWeb.UserAuth.log_in_user(conn, identity, cookie.return_to)
else else
{:error, reason} -> {:error, reason} ->
Phoenix.Controller.redirect(conn, conn
to: |> Phoenix.Controller.put_flash(:login_error, error_by_reason(reason))
Routes.sso_path(conn, :login_form, |> Phoenix.Controller.redirect(
error: error_by_reason(reason), to: Routes.sso_path(conn, :login_form, return_to: cookie.return_to)
return_to: cookie.return_to
)
) )
end end
end end

View File

@ -19,8 +19,8 @@
/> />
</div> </div>
<%= if @conn.assigns[:error] do %> <%= if login_error = Phoenix.Flash.get(@flash, :login_error) do %>
<div class="text-red-500 mt-4">{@conn.assigns[:error]}</div> <div class="text-red-500 mt-4">{login_error}</div>
<% end %> <% end %>
<.input type="hidden" field={f[:return_to]} /> <.input type="hidden" field={f[:return_to]} />
@ -33,7 +33,10 @@
<:item> <:item>
Have a standard account? Have a standard account?
<.styled_link href={ <.styled_link href={
Routes.auth_path(@conn, :login_form, return_to: @conn.params["return_to"]) Routes.auth_path(@conn, :login_form,
return_to: @conn.params["return_to"],
prefer: "manual"
)
}> }>
Log in here Log in here
</.styled_link> </.styled_link>

View File

@ -1,11 +1,13 @@
defmodule PlausibleWeb.AuthController do defmodule PlausibleWeb.AuthController do
use PlausibleWeb, :controller use PlausibleWeb, :controller
use Plausible.Repo use Plausible.Repo
use Plausible
alias Plausible.Auth alias Plausible.Auth
alias Plausible.Teams alias Plausible.Teams
alias PlausibleWeb.TwoFactor alias PlausibleWeb.TwoFactor
alias PlausibleWeb.UserAuth alias PlausibleWeb.UserAuth
alias PlausibleWeb.LoginPreference
require Logger require Logger
@ -227,9 +229,28 @@ defmodule PlausibleWeb.AuthController do
|> redirect(to: Routes.auth_path(conn, :login_form)) |> redirect(to: Routes.auth_path(conn, :login_form))
end end
on_ee do
def login_form(conn, params) do
login_preference = LoginPreference.get(conn)
error = Phoenix.Flash.get(conn.assigns.flash, :login_error)
case {login_preference, params["prefer"], error} do
{"sso", nil, nil} ->
if Plausible.sso_enabled?() do
redirect(conn, to: Routes.sso_path(conn, :login_form, return_to: params["return_to"]))
else
render(conn, "login_form.html")
end
_ ->
render(conn, "login_form.html")
end
end
else
def login_form(conn, _params) do def login_form(conn, _params) do
render(conn, "login_form.html") render(conn, "login_form.html")
end end
end
def login(conn, %{"user" => params}) do def login(conn, %{"user" => params}) do
login(conn, params) login(conn, params)
@ -268,18 +289,24 @@ defmodule PlausibleWeb.AuthController do
params["return_to"] params["return_to"]
end end
UserAuth.log_in_user(conn, user, redirect_path) conn
|> LoginPreference.clear()
|> UserAuth.log_in_user(user, redirect_path)
else else
{:error, :wrong_password} -> {:error, :wrong_password} ->
maybe_log_failed_login_attempts("wrong password for #{email}") maybe_log_failed_login_attempts("wrong password for #{email}")
render(conn, "login_form.html", error: "Wrong email or password. Please try again.") conn
|> put_flash(:login_error, "Wrong email or password. Please try again.")
|> render("login_form.html")
{:error, :user_not_found} -> {:error, :user_not_found} ->
maybe_log_failed_login_attempts("user not found for #{email}") maybe_log_failed_login_attempts("user not found for #{email}")
Plausible.Auth.Password.dummy_calculation() Plausible.Auth.Password.dummy_calculation()
render(conn, "login_form.html", error: "Wrong email or password. Please try again.") conn
|> put_flash(:login_error, "Wrong email or password. Please try again.")
|> render("login_form.html")
{:error, {:rate_limit, _}} -> {:error, {:rate_limit, _}} ->
maybe_log_failed_login_attempts("too many login attempts for #{email}") maybe_log_failed_login_attempts("too many login attempts for #{email}")

View File

@ -0,0 +1,40 @@
defmodule PlausibleWeb.LoginPreference do
@moduledoc """
Functions for managing user login preference cookies.
This module handles storing and retrieving the user's preferred login method
(standard or SSO) to provide a better user experience by showing their
preferred option first.
"""
@cookie_name "login_preference"
@cookie_max_age 60 * 60 * 24 * 365
@spec set_sso(Plug.Conn.t()) :: Plug.Conn.t()
def set_sso(conn) do
secure_cookie = PlausibleWeb.Endpoint.secure_cookie?()
Plug.Conn.put_resp_cookie(conn, @cookie_name, "sso",
http_only: true,
secure: secure_cookie,
max_age: @cookie_max_age,
same_site: "Lax"
)
end
@spec clear(Plug.Conn.t()) :: Plug.Conn.t()
def clear(conn) do
Plug.Conn.delete_resp_cookie(conn, @cookie_name)
end
@spec get(Plug.Conn.t()) :: String.t() | nil
def get(conn) do
case Plug.Conn.fetch_cookies(conn) do
%{cookies: %{@cookie_name => "sso"}} ->
"sso"
_ ->
nil
end
end
end

View File

@ -29,8 +29,8 @@
/> />
</div> </div>
<%= if @conn.assigns[:error] do %> <%= if login_error = Phoenix.Flash.get(@flash, :login_error) do %>
<div class="text-red-500 mt-4">{@conn.assigns[:error]}</div> <div class="text-red-500 mt-4">{login_error}</div>
<% end %> <% end %>
<.input type="hidden" field={f[:return_to]} /> <.input type="hidden" field={f[:return_to]} />
@ -53,7 +53,10 @@
<%= on_ee do %> <%= on_ee do %>
Have a Single Sign-on account? Have a Single Sign-on account?
<.styled_link href={ <.styled_link href={
Routes.sso_path(@conn, :login_form, return_to: @conn.params["return_to"]) Routes.sso_path(@conn, :login_form,
return_to: @conn.params["return_to"],
prefer: "manual"
)
}> }>
Sign in here Sign in here
</.styled_link> </.styled_link>

View File

@ -44,15 +44,16 @@ defmodule PlausibleWeb.UserAuth do
conn conn
|> set_user_token(session.token) |> set_user_token(session.token)
|> Plug.Conn.put_session("current_team_id", team.identifier) |> Plug.Conn.put_session("current_team_id", team.identifier)
|> PlausibleWeb.LoginPreference.set_sso()
|> set_logged_in_cookie() |> set_logged_in_cookie()
|> Phoenix.Controller.redirect(to: redirect_to) |> Phoenix.Controller.redirect(to: redirect_to)
{:error, :integration_not_found} -> {:error, :integration_not_found} ->
conn conn
|> log_out_user() |> log_out_user()
|> Phoenix.Controller.put_flash(:login_error, "Wrong email.")
|> Phoenix.Controller.redirect( |> Phoenix.Controller.redirect(
to: to: Routes.sso_path(conn, :login_form, return_to: redirect_path)
Routes.sso_path(conn, :login_form, error: "Wrong email.", return_to: redirect_path)
) )
{:error, :over_limit} -> {:error, :over_limit} ->
@ -60,8 +61,9 @@ defmodule PlausibleWeb.UserAuth do
conn conn
|> log_out_user() |> log_out_user()
|> Phoenix.Controller.put_flash(:login_error, error)
|> Phoenix.Controller.redirect( |> Phoenix.Controller.redirect(
to: Routes.sso_path(conn, :login_form, error: error, return_to: redirect_path) to: Routes.sso_path(conn, :login_form, return_to: redirect_path)
) )
{:error, reason, team, user} {:error, reason, team, user}

View File

@ -488,6 +488,20 @@ defmodule PlausibleWeb.AuthControllerTest do
assert input_value == "/dummy.site" assert input_value == "/dummy.site"
end end
@tag :ee_only
test "redirects to sso login if preferred", %{conn: conn} do
conn = PlausibleWeb.LoginPreference.set_sso(conn)
conn = get(conn, "/login?return_to=foo")
assert redirected_to(conn, 302) == "/sso/login?return_to=foo"
end
@tag :ee_only
test "keeps standard login form if preference manually overridden", %{conn: conn} do
conn = PlausibleWeb.LoginPreference.set_sso(conn)
conn = get(conn, "/login?prefer=manual")
assert html_response(conn, 200) =~ "Enter your account credentials"
end
end end
describe "POST /login" do describe "POST /login" do

View File

@ -223,8 +223,9 @@ defmodule PlausibleWeb.SSOControllerSyncTest do
) )
) )
assert redirected_to(conn, 302) == assert redirected_to(conn, 302) == Routes.sso_path(conn, :login_form, return_to: "/sites")
Routes.sso_path(conn, :login_form, error: "Wrong email.", return_to: "/sites")
assert Phoenix.Flash.get(conn.assigns.flash, :login_error) == "Wrong email."
end end
end end
@ -341,8 +342,9 @@ defmodule PlausibleWeb.SSOControllerSyncTest do
conn = post(conn, Routes.sso_path(conn, :saml_consume, Ecto.UUID.generate()), params) conn = post(conn, Routes.sso_path(conn, :saml_consume, Ecto.UUID.generate()), params)
assert redirected_to(conn, 302) == assert redirected_to(conn, 302) == Routes.sso_path(conn, :login_form, return_to: "/sites")
Routes.sso_path(conn, :login_form, error: "Wrong email.", return_to: "/sites")
assert Phoenix.Flash.get(conn.assigns.flash, :login_error) == "Wrong email."
end end
test "redirects with error on mismatch of RelayState", %{ test "redirects with error on mismatch of RelayState", %{
@ -356,11 +358,10 @@ defmodule PlausibleWeb.SSOControllerSyncTest do
conn = post(conn, Routes.sso_path(conn, :saml_consume, integration.identifier), params) conn = post(conn, Routes.sso_path(conn, :saml_consume, integration.identifier), params)
assert redirected_to(conn, 302) == assert redirected_to(conn, 302) == Routes.sso_path(conn, :login_form, return_to: "/sites")
Routes.sso_path(conn, :login_form,
error: "Authentication failed (reason: :invalid_relay_state).", assert Phoenix.Flash.get(conn.assigns.flash, :login_error) ==
return_to: "/sites" "Authentication failed (reason: :invalid_relay_state)."
)
end end
test "redirects with error on missing relay state", %{ test "redirects with error on missing relay state", %{
@ -371,11 +372,10 @@ defmodule PlausibleWeb.SSOControllerSyncTest do
conn = post(conn, Routes.sso_path(conn, :saml_consume, integration.identifier), params) conn = post(conn, Routes.sso_path(conn, :saml_consume, integration.identifier), params)
assert redirected_to(conn, 302) == assert redirected_to(conn, 302) == Routes.sso_path(conn, :login_form, return_to: "/sites")
Routes.sso_path(conn, :login_form,
error: "Authentication failed (reason: :invalid_relay_state).", assert Phoenix.Flash.get(conn.assigns.flash, :login_error) ==
return_to: "/sites" "Authentication failed (reason: :invalid_relay_state)."
)
end end
test "redirects with error on malformed assertion", %{ test "redirects with error on malformed assertion", %{
@ -390,11 +390,10 @@ defmodule PlausibleWeb.SSOControllerSyncTest do
conn = post(conn, Routes.sso_path(conn, :saml_consume, integration.identifier), params) conn = post(conn, Routes.sso_path(conn, :saml_consume, integration.identifier), params)
assert redirected_to(conn, 302) == assert redirected_to(conn, 302) == Routes.sso_path(conn, :login_form, return_to: "/sites")
Routes.sso_path(conn, :login_form,
error: "Authentication failed (reason: :base64_decoding_failed).", assert Phoenix.Flash.get(conn.assigns.flash, :login_error) ==
return_to: "/sites" "Authentication failed (reason: :base64_decoding_failed)."
)
end end
test "redirects with error on malformed certificate in config (should not happen)", %{ test "redirects with error on malformed certificate in config (should not happen)", %{
@ -417,11 +416,10 @@ defmodule PlausibleWeb.SSOControllerSyncTest do
conn = post(conn, Routes.sso_path(conn, :saml_consume, integration.identifier), params) conn = post(conn, Routes.sso_path(conn, :saml_consume, integration.identifier), params)
assert redirected_to(conn, 302) == assert redirected_to(conn, 302) == Routes.sso_path(conn, :login_form, return_to: "/sites")
Routes.sso_path(conn, :login_form,
error: "Authentication failed (reason: :malformed_certificate).", assert Phoenix.Flash.get(conn.assigns.flash, :login_error) ==
return_to: "/sites" "Authentication failed (reason: :malformed_certificate)."
)
end end
test "redirects with error on mismatched certificate in config", %{ test "redirects with error on mismatched certificate in config", %{
@ -438,11 +436,10 @@ defmodule PlausibleWeb.SSOControllerSyncTest do
conn = post(conn, Routes.sso_path(conn, :saml_consume, integration.identifier), params) conn = post(conn, Routes.sso_path(conn, :saml_consume, integration.identifier), params)
assert redirected_to(conn, 302) == assert redirected_to(conn, 302) == Routes.sso_path(conn, :login_form, return_to: "/sites")
Routes.sso_path(conn, :login_form,
error: "Authentication failed (reason: :digest_verification_failed).", assert Phoenix.Flash.get(conn.assigns.flash, :login_error) ==
return_to: "/sites" "Authentication failed (reason: :digest_verification_failed)."
)
end end
test "redirects with error on missing email attribute in assertion", %{ test "redirects with error on missing email attribute in assertion", %{
@ -457,11 +454,10 @@ defmodule PlausibleWeb.SSOControllerSyncTest do
conn = post(conn, Routes.sso_path(conn, :saml_consume, integration.identifier), params) conn = post(conn, Routes.sso_path(conn, :saml_consume, integration.identifier), params)
assert redirected_to(conn, 302) == assert redirected_to(conn, 302) == Routes.sso_path(conn, :login_form, return_to: "/sites")
Routes.sso_path(conn, :login_form,
error: "Authentication failed (reason: :missing_email_attribute).", assert Phoenix.Flash.get(conn.assigns.flash, :login_error) ==
return_to: "/sites" "Authentication failed (reason: :missing_email_attribute)."
)
end end
test "redirects with error on invalid email attribute in assertion", %{ test "redirects with error on invalid email attribute in assertion", %{
@ -476,11 +472,10 @@ defmodule PlausibleWeb.SSOControllerSyncTest do
conn = post(conn, Routes.sso_path(conn, :saml_consume, integration.identifier), params) conn = post(conn, Routes.sso_path(conn, :saml_consume, integration.identifier), params)
assert redirected_to(conn, 302) == assert redirected_to(conn, 302) == Routes.sso_path(conn, :login_form, return_to: "/sites")
Routes.sso_path(conn, :login_form,
error: "Authentication failed (reason: :invalid_email_attribute).", assert Phoenix.Flash.get(conn.assigns.flash, :login_error) ==
return_to: "/sites" "Authentication failed (reason: :invalid_email_attribute)."
)
end end
test "redirects with error on missing name attributes in assertion", %{ test "redirects with error on missing name attributes in assertion", %{
@ -495,11 +490,10 @@ defmodule PlausibleWeb.SSOControllerSyncTest do
conn = post(conn, Routes.sso_path(conn, :saml_consume, integration.identifier), params) conn = post(conn, Routes.sso_path(conn, :saml_consume, integration.identifier), params)
assert redirected_to(conn, 302) == assert redirected_to(conn, 302) == Routes.sso_path(conn, :login_form, return_to: "/sites")
Routes.sso_path(conn, :login_form,
error: "Authentication failed (reason: :missing_name_attributes).", assert Phoenix.Flash.get(conn.assigns.flash, :login_error) ==
return_to: "/sites" "Authentication failed (reason: :missing_name_attributes)."
)
end end
end end

View File

@ -24,7 +24,7 @@ defmodule PlausibleWeb.SSOControllerTest do
describe "login_form/2" do describe "login_form/2" do
test "renders login view", %{conn: conn} do test "renders login view", %{conn: conn} do
conn = get(conn, Routes.sso_path(conn, :login_form)) conn = get(conn, Routes.sso_path(conn, :login_form, prefer: "sso"))
assert html = html_response(conn, 200) assert html = html_response(conn, 200)
@ -34,10 +34,27 @@ defmodule PlausibleWeb.SSOControllerTest do
end end
test "passes return_to parameter to form", %{conn: conn} do test "passes return_to parameter to form", %{conn: conn} do
conn = get(conn, Routes.sso_path(conn, :login_form, return_to: "/sites", prefer: "sso"))
assert html = html_response(conn, 200)
assert text_of_attr(html, "input[name=return_to]", "value") == "/sites"
end
test "renders error if provided in login_error flash message", %{conn: conn} do
conn =
conn
|> init_session()
|> fetch_session()
|> fetch_flash()
|> put_flash(:login_error, "Wrong email.")
conn = get(conn, Routes.sso_path(conn, :login_form, return_to: "/sites")) conn = get(conn, Routes.sso_path(conn, :login_form, return_to: "/sites"))
assert html = html_response(conn, 200) assert html = html_response(conn, 200)
assert html =~ "Wrong email."
assert element_exists?(html, "input[name=email]")
assert text_of_attr(html, "input[name=return_to]", "value") == "/sites" assert text_of_attr(html, "input[name=return_to]", "value") == "/sites"
end end
end end
@ -83,11 +100,9 @@ defmodule PlausibleWeb.SSOControllerTest do
"return_to" => "/sites" "return_to" => "/sites"
}) })
assert html = html_response(conn, 200) assert redirected_to(conn, 302) == Routes.sso_path(conn, :login_form)
assert html =~ "Wrong email." assert Phoenix.Flash.get(conn.assigns.flash, :login_error) == "Wrong email."
assert element_exists?(html, "input[name=email]")
assert text_of_attr(html, "input[name=return_to]", "value") == "/sites"
end end
end end
@ -177,8 +192,9 @@ defmodule PlausibleWeb.SSOControllerTest do
"return_to" => "/sites" "return_to" => "/sites"
}) })
assert redirected_to(conn, 302) == assert redirected_to(conn, 302) == Routes.sso_path(conn, :login_form, return_to: "/sites")
Routes.sso_path(conn, :login_form, error: "Wrong email.", return_to: "/sites")
assert Phoenix.Flash.get(conn.assigns.flash, :login_error) == "Wrong email."
end end
end end

View File

@ -140,12 +140,14 @@ defmodule PlausibleWeb.UserAuthTest do
conn = conn =
conn conn
|> init_session() |> init_session()
|> fetch_flash()
|> UserAuth.log_in_user(identity) |> UserAuth.log_in_user(identity)
assert %{sessions: []} = user |> Repo.reload!() |> Repo.preload(:sessions) assert %{sessions: []} = user |> Repo.reload!() |> Repo.preload(:sessions)
assert redirected_to(conn, 302) == assert redirected_to(conn, 302) == Routes.sso_path(conn, :login_form, return_to: "")
Routes.sso_path(conn, :login_form, error: "Wrong email.", return_to: "")
assert Phoenix.Flash.get(conn.assigns.flash, :login_error) == "Wrong email."
assert conn.private[:plug_session_info] == :renew assert conn.private[:plug_session_info] == :renew
refute get_session(conn, :user_token) refute get_session(conn, :user_token)
@ -170,15 +172,15 @@ defmodule PlausibleWeb.UserAuthTest do
conn = conn =
conn conn
|> init_session() |> init_session()
|> fetch_flash()
|> UserAuth.log_in_user(identity) |> UserAuth.log_in_user(identity)
assert %{sessions: []} = user |> Repo.reload!() |> Repo.preload(:sessions) assert %{sessions: []} = user |> Repo.reload!() |> Repo.preload(:sessions)
assert redirected_to(conn, 302) == assert redirected_to(conn, 302) == Routes.sso_path(conn, :login_form, return_to: "")
Routes.sso_path(conn, :login_form,
error: "Team can't accept more members. Please contact the owner.", assert Phoenix.Flash.get(conn.assigns.flash, :login_error) ==
return_to: "" "Team can't accept more members. Please contact the owner."
)
assert conn.private[:plug_session_info] == :renew assert conn.private[:plug_session_info] == :renew
refute get_session(conn, :user_token) refute get_session(conn, :user_token)