- <.form for={%{}} phx-submit="decrypt">
- <%= if @secret.encryption_algo == :rsa do %>
-
-
-
- <.label for="decryption_key">RSA Private Key PEM
-
+ <.input type="textarea" name="key" value={@decrypted_text} readonly />
+
+ <% else %>
+
+ <.form for={%{}} phx-submit="decrypt">
+ <%= if @secret.encryption_algo == :rsa do %>
+
+
+
+ <.label for="decryption_key">RSA Private Key PEM
+
-
- <.icon name="hero-eye" class="h-5 w-5" />
-
+
+ <.icon name="hero-eye" class="h-5 w-5" />
+
-
- <.icon name="hero-eye-slash" class="h-5 w-5" />
+
+ <.icon name="hero-eye-slash" class="h-5 w-5" />
+
+
+ <.input
+ type="textarea"
+ autocomplete="off"
+ name="key"
+ spellcheck="false"
+ value=""
+ style="color: transparent;text-shadow: 0 0 8px rgba(0,0,0,0.5);"
+ x-bind:style="!show && 'color: transparent;text-shadow: 0 0 8px rgba(0,0,0,0.5);'"
+ />
- <.input
- type="textarea"
- autocomplete="off"
- name="key"
- spellcheck="false"
- value=""
- style="color: transparent;text-shadow: 0 0 8px rgba(0,0,0,0.5);"
- x-bind:style="!show && 'color: transparent;text-shadow: 0 0 8px rgba(0,0,0,0.5);'"
- />
-
+
+ <% end %>
-
- <% end %>
+ <%= if @secret.encryption_algo == :aes_gcm do %>
+
+
+
+ <.label for="decryption_key">Password
+
- <%= if @secret.encryption_algo == :aes_gcm do %>
-
-
-
- <.label for="decryption_key">Password
-
+
+ <.icon name="hero-eye" class="h-5 w-5" />
+
-
- <.icon name="hero-eye" class="h-5 w-5" />
+
+ <.icon name="hero-eye-slash" class="h-5 w-5" />
+
-
- <.icon name="hero-eye-slash" class="h-5 w-5" />
-
+ <.input
+ autocomplete="off"
+ name="key"
+ spellcheck="false"
+ value=""
+ style="color: transparent;text-shadow: 0 0 8px rgba(0,0,0,0.5);"
+ x-bind:style="!show && 'color: transparent;text-shadow: 0 0 8px rgba(0,0,0,0.5);'"
+ />
- <.input
- autocomplete="off"
- name="key"
- spellcheck="false"
- value=""
- style="color: transparent;text-shadow: 0 0 8px rgba(0,0,0,0.5);"
- x-bind:style="!show && 'color: transparent;text-shadow: 0 0 8px rgba(0,0,0,0.5);'"
- />
-
+
+ <% end %>
-
- <% end %>
+ <%= if @secret.encryption_algo == :plaintext do %>
+
+ <.input name="key" value="plaintext" />
+
+ <% end %>
- <%= if @secret.encryption_algo == :plaintext do %>
-
- <.input name="key" value="plaintext" />
+
+ <.button>Reveal Secret
- <% end %>
-
-
- <.button>Reveal Secret
-
-
-
- <% end %>
-
+
+
+ <% end %>
+
+<% end %>
diff --git a/test/heimdall/secrets_test.exs b/test/heimdall/secrets_test.exs
index 45a6686..0eae420 100644
--- a/test/heimdall/secrets_test.exs
+++ b/test/heimdall/secrets_test.exs
@@ -176,4 +176,47 @@ defmodule Heimdall.SecretsTest do
assert error == "Error in decryption"
end
end
+
+ describe "not_stale?/1" do
+ test "returns true when max reads are greater than secret reads" do
+ {:ok, secret} = Factory.encrypt_and_create(%{max_reads: 2})
+
+ assert Secrets.not_stale?(secret)
+ end
+
+ test "returns false when max reads are less than or eq secret reads" do
+ {:ok, secret} = Factory.encrypt_and_create(%{max_reads: 1})
+
+ _read = Secrets.create_secret_read(secret, "ip", DateTime.utc_now())
+
+ refute Secrets.not_stale?(secret)
+ end
+
+ test "returns true when max reads are nil" do
+ {:ok, secret} = Factory.encrypt_and_create(%{max_reads: nil})
+
+ assert Secrets.not_stale?(secret)
+ end
+
+ test "returns true when max attempts are greater than secret attempts" do
+ {:ok, secret} = Factory.encrypt_and_create(%{max_decryption_attempts: 2})
+
+ assert Secrets.not_stale?(secret)
+ end
+
+ test "returns false when max attempts are less than or eq secret attempts" do
+ {:ok, secret} = Factory.encrypt_and_create(%{max_decryption_attempts: 1})
+
+ _attempt = Secrets.create_secret_attempt(secret, "ip", DateTime.utc_now())
+
+ refute Secrets.not_stale?(secret)
+ end
+
+ test "returns true when max attempts are nil" do
+ {:ok, secret} =
+ Factory.encrypt_and_create(%{max_decryption_attempts: nil})
+
+ assert Secrets.not_stale?(secret)
+ end
+ end
end
diff --git a/test/heimdall_web/live/secret_revealer_live_test.exs b/test/heimdall_web/live/secret_revealer_live_test.exs
index c2926a9..6731a6d 100644
--- a/test/heimdall_web/live/secret_revealer_live_test.exs
+++ b/test/heimdall_web/live/secret_revealer_live_test.exs
@@ -2,6 +2,7 @@ defmodule HeimdallWeb.SecretRevealerLiveTest do
use HeimdallWeb.ConnCase
import Phoenix.LiveViewTest
+ alias Heimdall.Data.Secret.Read
alias Heimdall.Factory
alias Heimdall.Repo
alias HeimdallWeb.SecretRevealerLive
@@ -26,6 +27,22 @@ defmodule HeimdallWeb.SecretRevealerLiveTest do
assert html =~ secret.title
end
+
+ test "doesn't show secret parameters if wrong ip", %{conn: conn} do
+ {:ok, secret} =
+ Factory.encrypt_and_create(%{
+ ip_regex: "bad_regex"
+ })
+
+ {:ok, _view, html} =
+ live_isolated(
+ conn,
+ SecretRevealerLive,
+ session: %{"secret_id" => secret.id, "ip" => "ip"}
+ )
+
+ refute html =~ secret.title
+ end
end
describe "handle_event/3 (decrypt)" do
@@ -85,6 +102,24 @@ defmodule HeimdallWeb.SecretRevealerLiveTest do
|> element("form")
|> render_submit(%{"key" => "bad_key"}) =~ "Error in decryption"
end
+
+ test "doesn't show secret parameters if wrong ip", %{conn: conn} do
+ {:ok, secret} =
+ Factory.encrypt_and_create(%{
+ ip_regex: "bad_regex"
+ })
+
+ {:ok, view, _html} =
+ live_isolated(
+ conn,
+ SecretRevealerLive,
+ session: %{"secret_id" => secret.id, "ip" => "ip"}
+ )
+
+ # Secret isn't visible if bad ip is given
+ refute view
+ |> has_element?("form")
+ end
end
describe "handle_info/3 (check_expiration)" do
@@ -155,14 +190,16 @@ defmodule HeimdallWeb.SecretRevealerLiveTest do
refute Process.alive?(view.pid)
end
- test "doesn't redirect if secret isn't expired", %{conn: conn} do
+ test "redirects if secret is not expired but stale", %{conn: conn} do
raw = "supersecretpassword"
key = "key"
{:ok, secret} =
Factory.encrypt_and_create(%{
encryption_key: key,
- encrypted_text: raw
+ encrypted_text: raw,
+ expires_at: DateTime.add(DateTime.utc_now(), 2, :second),
+ max_reads: 1
})
{:ok, view, _html} =
@@ -172,19 +209,47 @@ defmodule HeimdallWeb.SecretRevealerLiveTest do
session: %{"secret_id" => secret.id, "ip" => "ip"}
)
- html =
- view
- |> element("form")
- |> render_submit(%{"key" => key})
+ %{secret_id: secret.id}
+ |> Factory.valid_secret_read_params()
+ |> Read.changeset()
+ |> Repo.insert()
- # Doesn't say secret is expired
- refute html =~ "Secret Expired"
+ view
+ |> element("form")
+ |> render_submit(%{"key" => key})
+
+ # Wait for enough time for the secret to expire
+ :timer.sleep(5_000)
+
+ # Live redirect
+ refute Process.alive?(view.pid)
+ end
+
+ test "doesn't redirect if secret isn't expired", %{conn: conn} do
+ raw = "supersecretpassword"
+ key = "key"
- :timer.sleep(1_000)
+ {:ok, secret} =
+ Factory.encrypt_and_create(%{
+ encryption_key: key,
+ encrypted_text: raw
+ })
- updated_html = render(view)
+ {:ok, view, _html} =
+ live_isolated(
+ conn,
+ SecretRevealerLive,
+ session: %{"secret_id" => secret.id, "ip" => "ip"}
+ )
+
+ view
+ |> element("form")
+ |> render_submit(%{"key" => key})
+
+ :timer.sleep(5_000)
- refute updated_html =~ "Secret Expired"
+ # No Live redirect
+ assert Process.alive?(view.pid)
end
end
end