Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delete account feature #367

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .cla/contributors.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
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
25 changes: 25 additions & 0 deletions lib/keila_web/controllers/account_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,31 @@ defmodule KeilaWeb.AccountController do
end
end

@spec delete(Plug.Conn.t(), map()) :: Plug.Conn.t()
def delete(conn, params) do
case get_in(params, ["require_confirmation"]) do
"true" ->
render_delete_confirmation(conn)

_ ->
Keila.Admin.purge_user(conn.assigns.current_user.id)

conn
|> end_auth_session()
|> redirect(to: Routes.auth_path(conn, :login))
end
end

defp render_delete_confirmation(conn) do
account =
Accounts.get_user_account(conn.assigns.current_user.id)

conn
|> put_meta(:title, gettext("Confirm Account Deletion"))
|> assign(:account, account)
|> render("delete.html")
end

defp render_edit(conn, changeset) do
account = Accounts.get_user_account(conn.assigns.current_user.id)
credits = if account, do: Accounts.get_credits(account.id)
Expand Down
1 change: 1 addition & 0 deletions lib/keila_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ defmodule KeilaWeb.Router do
get "/account", AccountController, :edit
put "/account", AccountController, :post_edit
get "/account/await-subscription", AccountController, :await_subscription
delete "/account", AccountController, :delete

get "/", ProjectController, :index
get "/projects/new", ProjectController, :new
Expand Down
33 changes: 33 additions & 0 deletions lib/keila_web/templates/account/delete.html.heex
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<div class="container flex py-8 sm:py-11 mb-4">
<h1 class="text-2xl sm:text-3xl">
<%= gettext("Delete Account?") %>
</h1>
</div>

<div class="container">
<div class="p-4 ring ring-red-900">
<p class="text-lg text-gray-200">
<%= gettext("Do you really want to delete your account?") %>
</p>

<.form
for={@conn}
as="account"
action={Routes.account_path(@conn, :delete)}
method="delete"
class="flex flex-col gap-4"
>
<p class="text-lg text-gray-200 font-bold">
<%= gettext("Deleting an account cannot be undone.") %>
</p>
<div class="flex gap-4 mt-4">
<a class="button button--text button--large" href={Routes.account_path(@conn, :edit)}>
<%= gettext("Cancel") %>
</a>
<button type="submit" class="button button--warn button--large">
<%= gettext("Delete") %>
</button>
</div>
</.form>
</div>
</div>
24 changes: 24 additions & 0 deletions lib/keila_web/templates/account/edit.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,30 @@
</button>
</div>
</.form>
<.form
let={f}
for={@conn}
action={Routes.account_path(@conn, :delete)}
class="rounded shadow p-8 mt-8 max-w-5xl mx-auto flex flex-col gap-4 bg-gray-900 text-gray-50"
method="delete"
>
<%= hidden_input(f, :require_confirmation, value: "true") %>
<h2 class="text-3xl font-bold">
<%= gettext("Remove account") %>
</h2>
<p class="text-lg text-gray-200">
<%= gettext("Here you can remove your Keila account") %>
</p>
<div class="flex justify-end mt-8">
<button
type="submit"
class="button button--warn button--large"
@click="setUnsavedReminder(false)"
>
<%= gettext("Remove account") %>
</button>
</div>
</.form>
</div>

<script src="https://cdn.paddle.com/paddle/paddle.js">
Expand Down
12 changes: 12 additions & 0 deletions test/keila_web/controllers/account_controller_test.exs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
defmodule KeilaWeb.AccountControllerTest do
use KeilaWeb.ConnCase
alias Keila.Auth
alias Keila.Accounts

describe "GET /account" do
@tag :account_controller
Expand Down Expand Up @@ -28,4 +29,15 @@ defmodule KeilaWeb.AccountControllerTest do
assert {:ok, %{id: ^user_id}} = Auth.find_user_by_credentials(credentials)
end
end

describe "DELETE /account" do
@tag :account_controller
test "deletes account", %{conn: conn} do
conn = with_login(conn)

conn = delete(conn, Routes.account_path(conn, :delete))
assert redirected_to(conn, 302) == Routes.auth_path(conn, :login)
assert nil == Accounts.get_user_account(conn.assigns.current_user.id)
end
end
end