Add API endpoints for Backups
authorEgor Kislitsyn <egor@kislitsyn.com>
Tue, 8 Sep 2020 21:04:00 +0000 (01:04 +0400)
committerEgor Kislitsyn <egor@kislitsyn.com>
Wed, 7 Oct 2020 14:34:29 +0000 (18:34 +0400)
lib/pleroma/backup.ex
lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex [new file with mode: 0644]
lib/pleroma/web/pleroma_api/controllers/backup_controller.ex [new file with mode: 0644]
lib/pleroma/web/pleroma_api/views/backup_view.ex [new file with mode: 0644]
lib/pleroma/web/router.ex
test/web/pleroma_api/controllers/backup_controller_test.exs [new file with mode: 0644]

index bd50fd9108338aaaf979c2b5000f00cab5d83c05..348e537a843b68dc8d713bcc4f25a7d4ef51cc85 100644 (file)
@@ -80,6 +80,13 @@ defmodule Pleroma.Backup do
     |> Repo.one()
   end
 
+  def list(%User{id: user_id}) do
+    __MODULE__
+    |> where(user_id: ^user_id)
+    |> order_by(desc: :id)
+    |> Repo.all()
+  end
+
   def remove_outdated(%__MODULE__{id: latest_id, user_id: user_id}) do
     __MODULE__
     |> where(user_id: ^user_id)
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex
new file mode 100644 (file)
index 0000000..f877ca3
--- /dev/null
@@ -0,0 +1,79 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.PleromaBackupOperation do
+  alias OpenApiSpex.Operation
+  alias OpenApiSpex.Schema
+  alias Pleroma.Web.ApiSpec.Schemas.ApiError
+
+  def open_api_operation(action) do
+    operation = String.to_existing_atom("#{action}_operation")
+    apply(__MODULE__, operation, [])
+  end
+
+  def index_operation do
+    %Operation{
+      tags: ["Backups"],
+      summary: "List backups",
+      security: [%{"oAuth" => ["read:account"]}],
+      operationId: "PleromaAPI.BackupController.index",
+      responses: %{
+        200 =>
+          Operation.response(
+            "An array of backups",
+            "application/json",
+            %Schema{
+              type: :array,
+              items: backup()
+            }
+          ),
+        400 => Operation.response("Bad Request", "application/json", ApiError)
+      }
+    }
+  end
+
+  def create_operation do
+    %Operation{
+      tags: ["Backups"],
+      summary: "Create a backup",
+      security: [%{"oAuth" => ["read:account"]}],
+      operationId: "PleromaAPI.BackupController.create",
+      responses: %{
+        200 =>
+          Operation.response(
+            "An array of backups",
+            "application/json",
+            %Schema{
+              type: :array,
+              items: backup()
+            }
+          ),
+        400 => Operation.response("Bad Request", "application/json", ApiError)
+      }
+    }
+  end
+
+  defp backup do
+    %Schema{
+      title: "Backup",
+      description: "Response schema for a backup",
+      type: :object,
+      properties: %{
+        inserted_at: %Schema{type: :string, format: :"date-time"},
+        content_type: %Schema{type: :string},
+        file_name: %Schema{type: :string},
+        file_size: %Schema{type: :integer},
+        processed: %Schema{type: :boolean}
+      },
+      example: %{
+        "content_type" => "application/zip",
+        "file_name" =>
+          "archive-cofe-20200908T195819-1lWrJyJqpsj8-KuHFr7N03lfsYYa5nf2NL-7A9-ddFU.zip",
+        "file_size" => 1024,
+        "inserted_at" => "2020-09-08T19:58:20",
+        "processed" => true
+      }
+    }
+  end
+end
diff --git a/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex b/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex
new file mode 100644 (file)
index 0000000..e52c77f
--- /dev/null
@@ -0,0 +1,27 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.BackupController do
+  use Pleroma.Web, :controller
+
+  alias Pleroma.Plugs.OAuthScopesPlug
+
+  action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
+  plug(OAuthScopesPlug, %{scopes: ["read:accounts"]} when action in [:index, :create])
+  plug(OpenApiSpex.Plug.CastAndValidate, render_error: Pleroma.Web.ApiSpec.RenderError)
+
+  defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaBackupOperation
+
+  def index(%{assigns: %{user: user}} = conn, _params) do
+    backups = Pleroma.Backup.list(user)
+    render(conn, "index.json", backups: backups)
+  end
+
+  def create(%{assigns: %{user: user}} = conn, _params) do
+    with {:ok, _} <- Pleroma.Backup.create(user) do
+      backups = Pleroma.Backup.list(user)
+      render(conn, "index.json", backups: backups)
+    end
+  end
+end
diff --git a/lib/pleroma/web/pleroma_api/views/backup_view.ex b/lib/pleroma/web/pleroma_api/views/backup_view.ex
new file mode 100644 (file)
index 0000000..02b94ce
--- /dev/null
@@ -0,0 +1,24 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.BackupView do
+  use Pleroma.Web, :view
+
+  alias Pleroma.Backup
+  alias Pleroma.Web.CommonAPI.Utils
+
+  def render("show.json", %{backup: %Backup{} = backup}) do
+    %{
+      content_type: backup.content_type,
+      file_name: backup.file_name,
+      file_size: backup.file_size,
+      processed: backup.processed,
+      inserted_at: Utils.to_masto_date(backup.inserted_at)
+    }
+  end
+
+  def render("index.json", %{backups: backups}) do
+    render_many(backups, __MODULE__, "show.json")
+  end
+end
index e22b31b4c2a47f0b46eb1807c58fd9b24c675059..a1a5a1cb54f476b7d4fe19c56e34356ad5f9652a 100644 (file)
@@ -293,6 +293,9 @@ defmodule Pleroma.Web.Router do
     get("/accounts/mfa/setup/:method", TwoFactorAuthenticationController, :setup)
     post("/accounts/mfa/confirm/:method", TwoFactorAuthenticationController, :confirm)
     delete("/accounts/mfa/:method", TwoFactorAuthenticationController, :disable)
+
+    get("/backups", BackupController, :index)
+    post("/backups", BackupController, :create)
   end
 
   scope "/oauth", Pleroma.Web.OAuth do
diff --git a/test/web/pleroma_api/controllers/backup_controller_test.exs b/test/web/pleroma_api/controllers/backup_controller_test.exs
new file mode 100644 (file)
index 0000000..1ad1b63
--- /dev/null
@@ -0,0 +1,84 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.BackupControllerTest do
+  use Pleroma.Web.ConnCase
+
+  alias Pleroma.Backup
+
+  setup do
+    clear_config([Pleroma.Upload, :uploader])
+    clear_config([Backup, :limit_days])
+    oauth_access(["read:accounts"])
+  end
+
+  test "GET /api/pleroma/backups", %{user: user, conn: conn} do
+    assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id}}} = Backup.create(user)
+
+    backup = Backup.get(backup_id)
+
+    response =
+      conn
+      |> get("/api/pleroma/backups")
+      |> json_response_and_validate_schema(:ok)
+
+    assert [
+             %{
+               "content_type" => "application/zip",
+               "file_name" => file_name,
+               "file_size" => 0,
+               "processed" => false,
+               "inserted_at" => _
+             }
+           ] = response
+
+    assert file_name == backup.file_name
+
+    Pleroma.Tests.ObanHelpers.perform_all()
+
+    assert [
+             %{
+               "file_name" => ^file_name,
+               "processed" => true
+             }
+           ] =
+             conn
+             |> get("/api/pleroma/backups")
+             |> json_response_and_validate_schema(:ok)
+  end
+
+  test "POST /api/pleroma/backups", %{user: _user, conn: conn} do
+    assert [
+             %{
+               "content_type" => "application/zip",
+               "file_name" => file_name,
+               "file_size" => 0,
+               "processed" => false,
+               "inserted_at" => _
+             }
+           ] =
+             conn
+             |> post("/api/pleroma/backups")
+             |> json_response_and_validate_schema(:ok)
+
+    Pleroma.Tests.ObanHelpers.perform_all()
+
+    assert [
+             %{
+               "file_name" => ^file_name,
+               "processed" => true
+             }
+           ] =
+             conn
+             |> get("/api/pleroma/backups")
+             |> json_response_and_validate_schema(:ok)
+
+    days = Pleroma.Config.get([Backup, :limit_days])
+
+    assert %{"error" => "Last export was less than #{days} days ago"} ==
+             conn
+             |> post("/api/pleroma/backups")
+             |> json_response_and_validate_schema(400)
+  end
+end