Include tests for Captcha success/failure scenarios (#2344)

* Include tests for Captcha success/failure scenarios

* DRY
This commit is contained in:
Adam Rutkowski 2022-10-17 13:16:59 +02:00 committed by GitHub
parent aa97e9cf89
commit e3ca3b32db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 166 additions and 9 deletions

View File

@ -11,3 +11,5 @@ ADMIN_USER_PWD=fakepassword
ENABLE_EMAIL_VERIFICATION=true
SELFHOST=false
SITE_LIMIT=3
HCAPTCHA_SITEKEY=test
HCAPTCHA_SECRET=scottiger

View File

@ -4,18 +4,17 @@ defmodule PlausibleWeb.Captcha do
@verify_endpoint "https://hcaptcha.com/siteverify"
def enabled? do
!!sitekey()
is_binary(sitekey())
end
def sitekey() do
Application.get_env(:plausible, :hcaptcha, [])
|> Keyword.fetch!(:sitekey)
Application.get_env(:plausible, :hcaptcha, [])[:sitekey]
end
def verify(token) do
if enabled?() do
res =
HTTPClient.post(
HTTPClient.impl().post(
@verify_endpoint,
[{"content-type", "application/x-www-form-urlencoded"}],
%{
@ -25,9 +24,8 @@ defmodule PlausibleWeb.Captcha do
)
case res do
{:ok, %Finch.Response{status: 200, body: body}} ->
json = Jason.decode!(body)
json["success"]
{:ok, %Finch.Response{status: 200, body: %{"success" => success}}} ->
success
_ ->
false
@ -38,7 +36,6 @@ defmodule PlausibleWeb.Captcha do
end
defp secret() do
Application.get_env(:plausible, :hcaptcha, [])
|> Keyword.fetch!(:secret)
Application.get_env(:plausible, :hcaptcha, [])[:secret]
end
end

View File

@ -0,0 +1,66 @@
defmodule PlausibleWeb.CaptchaTest do
use Plausible.DataCase
import Mox
setup :verify_on_exit!
alias PlausibleWeb.Captcha
describe "mocked payloads" do
@failure Jason.decode!(~s/{"success":false,"error-codes":["invalid-input-response"]}/)
@success Jason.decode!(~s/{"success":true}/)
test "returns false for non-success response" do
expect(
Plausible.HTTPClient.Mock,
:post,
fn "https://hcaptcha.com/siteverify",
[{"content-type", "application/x-www-form-urlencoded"}],
%{response: "bad", secret: "scottiger"} ->
{:ok,
%Finch.Response{
status: 200,
headers: [{"content-type", "application/json"}],
body: @failure
}}
end
)
refute Captcha.verify("bad")
end
test "returns true for successful response" do
expect(
Plausible.HTTPClient.Mock,
:post,
fn "https://hcaptcha.com/siteverify",
[{"content-type", "application/x-www-form-urlencoded"}],
%{response: "good", secret: "scottiger"} ->
{:ok,
%Finch.Response{
status: 200,
headers: [{"content-type", "application/json"}],
body: @success
}}
end
)
assert Captcha.verify("good")
end
end
describe "with patched application env" do
setup do
original_env = Application.get_env(:plausible, :hcaptcha)
Application.put_env(:plausible, :hcaptcha, sitekey: nil)
on_exit(fn ->
Application.put_env(:plausible, :hcaptcha, original_env)
end)
end
test "returns true when disabled" do
assert Captcha.verify("disabled")
end
end
end

View File

@ -4,6 +4,9 @@ defmodule PlausibleWeb.AuthControllerTest do
use Plausible.Repo
import Plausible.TestUtils
import Mox
setup :verify_on_exit!
describe "GET /register" do
test "shows the register form", %{conn: conn} do
conn = get(conn, "/register")
@ -14,6 +17,8 @@ defmodule PlausibleWeb.AuthControllerTest do
describe "POST /register" do
test "registering sends an activation link", %{conn: conn} do
mock_captcha_success()
post(conn, "/register",
user: %{
name: "Jane Doe",
@ -29,6 +34,8 @@ defmodule PlausibleWeb.AuthControllerTest do
end
test "user is redirected to activate page after registration", %{conn: conn} do
mock_captcha_success()
conn =
post(conn, "/register",
user: %{
@ -43,6 +50,8 @@ defmodule PlausibleWeb.AuthControllerTest do
end
test "creates user record", %{conn: conn} do
mock_captcha_success()
post(conn, "/register",
user: %{
name: "Jane Doe",
@ -57,6 +66,8 @@ defmodule PlausibleWeb.AuthControllerTest do
end
test "logs the user in", %{conn: conn} do
mock_captcha_success()
conn =
post(conn, "/register",
user: %{
@ -71,6 +82,8 @@ defmodule PlausibleWeb.AuthControllerTest do
end
test "user is redirected to activation after registration", %{conn: conn} do
mock_captcha_success()
conn =
post(conn, "/register",
user: %{
@ -83,6 +96,22 @@ defmodule PlausibleWeb.AuthControllerTest do
assert redirected_to(conn) == "/activate"
end
test "renders captcha errors in case of captcha input verification failure", %{conn: conn} do
mock_captcha_failure()
conn =
post(conn, "/register",
user: %{
name: "Jane Doe",
email: "user@example.com",
password: "very-secret",
password_confirmation: "very-secret"
}
)
assert html_response(conn, 200) =~ "Please complete the captcha"
end
end
describe "GET /register/invitations/:invitation_id" do
@ -121,6 +150,8 @@ defmodule PlausibleWeb.AuthControllerTest do
end
test "registering sends an activation link", %{conn: conn, invitation: invitation} do
mock_captcha_success()
post(conn, "/register/invitation/#{invitation.invitation_id}",
user: %{
name: "Jane Doe",
@ -139,6 +170,8 @@ defmodule PlausibleWeb.AuthControllerTest do
conn: conn,
invitation: invitation
} do
mock_captcha_success()
conn =
post(conn, "/register/invitation/#{invitation.invitation_id}",
user: %{
@ -153,6 +186,8 @@ defmodule PlausibleWeb.AuthControllerTest do
end
test "creates user record", %{conn: conn, invitation: invitation} do
mock_captcha_success()
post(conn, "/register/invitation/#{invitation.invitation_id}",
user: %{
name: "Jane Doe",
@ -170,6 +205,8 @@ defmodule PlausibleWeb.AuthControllerTest do
conn: conn,
invitation: invitation
} do
mock_captcha_success()
post(conn, "/register/invitation/#{invitation.invitation_id}",
user: %{
name: "Jane Doe",
@ -184,6 +221,8 @@ defmodule PlausibleWeb.AuthControllerTest do
end
test "logs the user in", %{conn: conn, invitation: invitation} do
mock_captcha_success()
conn =
post(conn, "/register/invitation/#{invitation.invitation_id}",
user: %{
@ -198,6 +237,8 @@ defmodule PlausibleWeb.AuthControllerTest do
end
test "user is redirected to activation after registration", %{conn: conn} do
mock_captcha_success()
conn =
post(conn, "/register",
user: %{
@ -210,6 +251,25 @@ defmodule PlausibleWeb.AuthControllerTest do
assert redirected_to(conn) == "/activate"
end
test "renders captcha errors in case of captcha input verification failure", %{
conn: conn,
invitation: invitation
} do
mock_captcha_failure()
conn =
post(conn, "/register/invitation/#{invitation.invitation_id}",
user: %{
name: "Jane Doe",
email: "user@example.com",
password: "very-secret",
password_confirmation: "very-secret"
}
)
assert html_response(conn, 200) =~ "Please complete the captcha"
end
end
describe "GET /activate" do
@ -416,12 +476,21 @@ defmodule PlausibleWeb.AuthControllerTest do
end
test "email is present and exists - sends password reset email", %{conn: conn} do
mock_captcha_success()
user = insert(:user)
conn = post(conn, "/password/request-reset", %{email: user.email})
assert html_response(conn, 200) =~ "Success!"
assert_email_delivered_with(subject: "Plausible password reset")
end
test "renders captcha errors in case of captcha input verification failure", %{conn: conn} do
mock_captcha_failure()
user = insert(:user)
conn = post(conn, "/password/request-reset", %{email: user.email})
assert html_response(conn, 200) =~ "Please complete the captcha"
end
end
describe "GET /password/reset" do
@ -690,4 +759,27 @@ defmodule PlausibleWeb.AuthControllerTest do
assert Repo.get(ApiKey, api_key.id)
end
end
defp mock_captcha_success() do
mock_captcha(true)
end
defp mock_captcha_failure() do
mock_captcha(false)
end
defp mock_captcha(success) do
expect(
Plausible.HTTPClient.Mock,
:post,
fn _, _, _ ->
{:ok,
%Finch.Response{
status: 200,
headers: [{"content-type", "application/json"}],
body: %{"success" => success}
}}
end
)
end
end