diff --git a/server/assets/css/phoenix.css b/server/assets/css/phoenix.css index 0d59050f89..961499844d 100644 --- a/server/assets/css/phoenix.css +++ b/server/assets/css/phoenix.css @@ -28,6 +28,11 @@ select { width: auto; } +label { + font-weight:300; + display:inline; +} + /* Phoenix promo and logo */ .phx-hero { text-align: center; diff --git a/server/lib/field_hub/project.ex b/server/lib/field_hub/project.ex index 9d55713786..66094fc335 100644 --- a/server/lib/field_hub/project.ex +++ b/server/lib/field_hub/project.ex @@ -130,7 +130,8 @@ defmodule FieldHub.Project do __Parameters__ - `project_identifier` the project's name. """ - def exists?(project_identifier) do + def exists?(project_identifier) + when project_identifier != "" and not is_nil(project_identifier) do CouchService.get_db_infos(project_identifier) |> case do %{status_code: 200} -> diff --git a/server/lib/field_hub_web/controllers/api/project_controller.ex b/server/lib/field_hub_web/controllers/api/project_controller.ex index b0a3ce0ca5..e6c8b40c6c 100644 --- a/server/lib/field_hub_web/controllers/api/project_controller.ex +++ b/server/lib/field_hub_web/controllers/api/project_controller.ex @@ -12,6 +12,10 @@ defmodule FieldHubWeb.Api.ProjectController do @identifier_length Application.compile_env(:field_hub, :max_project_identifier_length) + @moduledoc """ + This API controller module handles the HTTP requests for listing, creating or deleting projects. + """ + def index(%{assigns: %{current_user: user_name}} = conn, _params) do render(conn, "list.json", %{projects: Project.get_all_for_user(user_name)}) end @@ -86,12 +90,12 @@ defmodule FieldHubWeb.Api.ProjectController do end def delete(conn, %{"project" => id}) do - project = Project.delete(id) - user = User.delete(id) + project_deletion_result = Project.delete(id) + user_deletion_result = User.delete(id) response_payload = %{ - status_project: project, - status_user: user + status_project: project_deletion_result, + status_user: user_deletion_result } conn diff --git a/server/lib/field_hub_web/live/project_show_live.ex b/server/lib/field_hub_web/live/project_show_live.ex index f5c235c4f2..9f0f769b6a 100644 --- a/server/lib/field_hub_web/live/project_show_live.ex +++ b/server/lib/field_hub_web/live/project_show_live.ex @@ -1,4 +1,6 @@ defmodule FieldHubWeb.ProjectShowLive do + alias FieldHub.Project + alias FieldHubWeb.{ Router.Helpers, UserAuth, @@ -42,6 +44,8 @@ defmodule FieldHubWeb.ProjectShowLive do |> assign(:project, project) |> assign(:current_user, user_name) |> assign(:new_password, "") + |> assign(:confirm_project_name, "") + |> assign(:delete_files, false) |> read_project_doc() } @@ -112,6 +116,62 @@ defmodule FieldHubWeb.ProjectShowLive do {:noreply, assign(socket, :new_password, password)} end + def handle_event( + "delete_form_change", + %{ + "repeat_project_name_input" => repeated_project_name, + "delete_files_radio" => delete_files + } = _values, + socket + ) do + delete_files = + case delete_files do + "delete_files" -> + true + + "keep_files" -> + false + end + + socket = assign(socket, :confirm_project_name, repeated_project_name) + socket = assign(socket, :delete_files, delete_files) + {:noreply, socket} + end + + def handle_event( + "delete", + _values, + %{assigns: %{project: project, current_user: user_name, delete_files: delete_files}} = + socket + ) do + socket = + case User.is_admin?(user_name) do + true -> + %{database: :deleted} = Project.delete(project, delete_files) + :deleted = User.delete(project) + + if delete_files == false do + {:ok, "Project database`#{project}` has been deleted successfully."} + else + {:ok, "Project database`#{project}` and images have been deleted successfully."} + end + + false -> + {:error, "You are not authorized to delete the project."} + end + |> case do + {:ok, msg} -> + socket + |> put_flash(:info, msg) + + {:error, msg} -> + socket + |> put_flash(:error, msg) + end + + {:noreply, redirect(socket, to: "/")} + end + def handle_event("generate_password", _values, socket) do {:noreply, assign(socket, :new_password, CouchService.create_password())} end diff --git a/server/lib/field_hub_web/live/project_show_live.html.heex b/server/lib/field_hub_web/live/project_show_live.html.heex index 5877682552..9291f24118 100644 --- a/server/lib/field_hub_web/live/project_show_live.html.heex +++ b/server/lib/field_hub_web/live/project_show_live.html.heex @@ -126,7 +126,7 @@ <%= if User.is_admin?(@current_user) do %>

Password change

-
+

+

Delete project

+ +
+
+ +
+
+ +
+
+ +
+ + + +
+
+
+
+ +
+
+ <% end %>
diff --git a/server/test/field_hub_web/live/project_show_live_test.exs b/server/test/field_hub_web/live/project_show_live_test.exs index 189e020e36..ac4f1d74d2 100644 --- a/server/test/field_hub_web/live/project_show_live_test.exs +++ b/server/test/field_hub_web/live/project_show_live_test.exs @@ -341,7 +341,7 @@ defmodule FieldHubWeb.ProjectShowLiveTest do {:ok, %{conn: conn}} end - test "admin has passwort setting interface", %{conn: conn} do + test "admin has password setting interface", %{conn: conn} do {:ok, view, _html_on_mount} = live(conn, "/ui/projects/show/#{@project}") html = render(view) @@ -362,7 +362,7 @@ defmodule FieldHubWeb.ProjectShowLiveTest do html = view - |> element("form") + |> element("#pwd_form") |> render_change(%{password: "typed_in_password"}) assert html =~ @@ -397,7 +397,7 @@ defmodule FieldHubWeb.ProjectShowLiveTest do new_password = "updated_password" view - |> element("form") + |> element("#pwd_form") |> render_change(%{password: new_password}) html = @@ -422,6 +422,123 @@ defmodule FieldHubWeb.ProjectShowLiveTest do }) end + test "admin is able to delete a project's database", %{conn: conn} do + {:ok, view, _html_on_mount} = live(conn, "/ui/projects/show/#{@project}") + + # Check if the system knows the project currently + assert true == FieldHub.Project.exists?(@project) + + assert FieldHub.FileStore.file_index(@project) |> Enum.count() > 0 + + # Simulate the repeated project name input + view + |> element("#del_form") + |> render_change(%{repeat_project_name_input: @project}) + + # Check if we are beeing redirected to the landing page + {:error, {:redirect, %{to: "/"}}} = + view + |> element("button", "Delete") + |> render_click() + + # Check if the project got deleted. + assert false == FieldHub.Project.exists?(@project) + + assert FieldHub.FileStore.file_index(@project) |> Enum.count() > 0 + end + + test "admin is able to delete a project's database and files still exist after having changed the radio button selection", + %{conn: conn} do + {:ok, view, _html_on_mount} = live(conn, "/ui/projects/show/#{@project}") + + # Check if the system knows the project. + assert true == FieldHub.Project.exists?(@project) + + # Check if the project's file directory exists. + assert File.exists?("test/tmp/#{@project}/") + + # Simulate the repeated project name input + view + |> element("#del_form") + |> render_change(%{repeat_project_name_input: @project}) + + view + |> element("#del_form") + |> render_change(%{delete_files_radio: "delete_files"}) + + html = + view + |> element("#del_form") + |> render_change(%{delete_files_radio: "keep_files"}) + + assert html =~ "value=\"keep_files\" checked" + + # Check if we are beeing redirected to the landing page + {:error, {:redirect, %{to: "/"}}} = + view + |> element("button", "Delete") + |> render_click() + + # Check if the project got deleted. + assert false == FieldHub.Project.exists?(@project) + + # Check if files have been deleted. + assert File.exists?("test/tmp/#{@project}/") + end + + test "admin is able to delete a project's database and its files", %{conn: conn} do + {:ok, view, _html_on_mount} = live(conn, "/ui/projects/show/#{@project}") + + # Check if the system knows the project. + assert true == FieldHub.Project.exists?(@project) + + # Check if the project's file directory exists. + assert File.exists?("test/tmp/#{@project}/") + + # Simulate the repeated project name input + view + |> element("#del_form") + |> render_change(%{repeat_project_name_input: @project}) + + html = + view + |> element("#del_form") + |> render_change(%{delete_files_radio: "delete_files"}) + + assert html =~ "value=\"delete_files\" checked" + + # Check if we are beeing redirected to the landing page + {:error, {:redirect, %{to: "/"}}} = + view + |> element("button", "Delete") + |> render_click() + + # Check if the project got deleted. + assert false == FieldHub.Project.exists?(@project) + + # Check if files have been deleted. + assert not File.exists?("test/tmp/#{@project}/") + end + + test "project deletion button is disabled until project name is repeated", %{conn: conn} do + {:ok, view, _html_on_mount} = live(conn, "/ui/projects/show/#{@project}") + + assert true == FieldHub.Project.exists?(@project) + + html = render(view) + + # The "Delete" button should be disabled as long as the repeated project name does not match. + assert html =~ "phx-click=\"delete\" disabled=\"disabled\"" + + html = + view + |> element("#del_form") + |> render_change(%{repeat_project_name_input: @project}) + + # The "Delete" button should be enabled now. + assert not (html =~ "phx-click=\"delete\" disabled=\"disabled\"") + end + test "throws warning if default user is missing", %{conn: conn} do # This case is highly unlikely, but is checked by the view nonetheless for completeness sake. @@ -430,7 +547,7 @@ defmodule FieldHubWeb.ProjectShowLiveTest do User.delete(@user_name) view - |> element("form") + |> element("#pwd_form") |> render_change(%{password: "updated_password"}) html =