mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-03-21 20:41:57 +00:00
Prevent last admin from being deleted (#694)
* Prevent last admin from being deleted * fix tests
This commit is contained in:
@@ -32,6 +32,10 @@ defmodule FzHttp.Users do
|
||||
Repo.exists?(from u in User, where: u.id == ^user_id)
|
||||
end
|
||||
|
||||
def list_admins do
|
||||
Repo.all(from User, where: [role: :admin])
|
||||
end
|
||||
|
||||
def get_user!(email: email) do
|
||||
Repo.get_by!(User, email: email)
|
||||
end
|
||||
|
||||
@@ -10,6 +10,12 @@ defmodule FzHttpWeb.UserController do
|
||||
def delete(conn, _params) do
|
||||
user = Authentication.get_current_user(conn)
|
||||
|
||||
with %{role: :admin} <- user do
|
||||
unless length(Users.list_admins()) > 1 do
|
||||
raise "Cannot delete one last admin"
|
||||
end
|
||||
end
|
||||
|
||||
case Users.delete_user(user) do
|
||||
{:ok, _user} ->
|
||||
FzHttpWeb.Endpoint.broadcast("users_socket:#{user.id}", "disconnect", %{})
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
|
||||
<%# This is purposefully a synchronous form in order to easily clear the session %>
|
||||
<%= form_for @changeset, Routes.user_path(@socket, :delete), [id: "delete-account", method: :delete], fn _f -> %>
|
||||
<%= submit(class: "button is-danger", data: [confirm: "Are you sure?"]) do %>
|
||||
<%= submit(class: "button is-danger", data: [confirm: "Are you sure?"], disabled: !@allow_delete) do %>
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-trash"></i>
|
||||
</span>
|
||||
|
||||
@@ -25,7 +25,8 @@ defmodule FzHttpWeb.SettingLive.Account do
|
||||
|
||||
@impl Phoenix.LiveView
|
||||
def handle_params(_params, _url, socket) do
|
||||
{:noreply, socket}
|
||||
admins = Users.list_admins()
|
||||
{:noreply, assign(socket, :allow_delete, length(admins) > 1)}
|
||||
end
|
||||
|
||||
@impl Phoenix.LiveView
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
defmodule FzHttpWeb.UserControllerTest do
|
||||
use FzHttpWeb.ConnCase, async: true
|
||||
|
||||
alias FzHttp.Users
|
||||
alias FzHttp.{Users, UsersFixtures}
|
||||
|
||||
setup do
|
||||
{:ok, extra_admin: UsersFixtures.user()}
|
||||
end
|
||||
|
||||
describe "when user signed in" do
|
||||
test "deletes the user", %{admin_conn: conn} do
|
||||
@@ -9,9 +13,24 @@ defmodule FzHttpWeb.UserControllerTest do
|
||||
|
||||
assert redirected_to(test_conn) == Routes.root_path(test_conn, :index)
|
||||
end
|
||||
|
||||
test "prevents deletion if no extra admin", %{admin_conn: conn, extra_admin: extra_admin} do
|
||||
Users.delete_user(extra_admin)
|
||||
|
||||
assert_raise(RuntimeError, fn ->
|
||||
delete(conn, Routes.user_path(conn, :delete))
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when user is already deleted" do
|
||||
setup do
|
||||
# this allows there to be 2 admins left after the main test admin is
|
||||
# deleted, so that the deletion doesn't raise
|
||||
_yet_another_admin = UsersFixtures.user()
|
||||
:ok
|
||||
end
|
||||
|
||||
test "returns 404", %{admin_user: user, admin_conn: conn} do
|
||||
user.id
|
||||
|> Users.get_user!()
|
||||
|
||||
Reference in New Issue
Block a user