Add OpenAPI spec for AdminAPI.InviteTokenController
authorEgor Kislitsyn <egor@kislitsyn.com>
Tue, 26 May 2020 11:02:51 +0000 (15:02 +0400)
committerEgor Kislitsyn <egor@kislitsyn.com>
Tue, 26 May 2020 11:03:07 +0000 (15:03 +0400)
lib/pleroma/web/admin_api/controllers/invite_token_controller.ex
lib/pleroma/web/api_spec/operations/admin/invite_token_operation.ex
test/web/admin_api/controllers/invite_token_controller_test.exs

index a0291e9c344578b6845d96ca38a3a49ac3daaed4..a09966e5c2fd16034d3fb87c03b155ed6abc5165 100644 (file)
@@ -14,6 +14,7 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenController do
 
   require Logger
 
+  plug(Pleroma.Web.ApiSpec.CastAndValidate)
   plug(OAuthScopesPlug, %{scopes: ["read:invites"], admin: true} when action == :index)
 
   plug(
@@ -23,6 +24,8 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenController do
 
   action_fallback(Pleroma.Web.AdminAPI.FallbackController)
 
+  defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.InviteTokenOperation
+
   @doc "Get list of created invites"
   def index(conn, _params) do
     invites = UserInviteToken.list_invites()
@@ -33,26 +36,14 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenController do
   end
 
   @doc "Create an account registration invite token"
-  def create(conn, params) do
-    opts = %{}
-
-    opts =
-      if params["max_use"],
-        do: Map.put(opts, :max_use, params["max_use"]),
-        else: opts
-
-    opts =
-      if params["expires_at"],
-        do: Map.put(opts, :expires_at, params["expires_at"]),
-        else: opts
-
-    {:ok, invite} = UserInviteToken.create_invite(opts)
+  def create(%{body_params: params} = conn, _) do
+    {:ok, invite} = UserInviteToken.create_invite(params)
 
     json(conn, AccountView.render("invite.json", %{invite: invite}))
   end
 
   @doc "Revokes invite by token"
-  def revoke(conn, %{"token" => token}) do
+  def revoke(%{body_params: %{token: token}} = conn, _) do
     with {:ok, invite} <- UserInviteToken.find_by_token(token),
          {:ok, updated_invite} = UserInviteToken.update_invite(invite, %{used: true}) do
       conn
@@ -64,7 +55,7 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenController do
   end
 
   @doc "Sends registration invite via email"
-  def email(%{assigns: %{user: user}} = conn, %{"email" => email} = params) do
+  def email(%{assigns: %{user: user}, body_params: %{email: email} = params} = conn, _) do
     with {_, false} <- {:registrations_open, Config.get([:instance, :registrations_open])},
          {_, true} <- {:invites_enabled, Config.get([:instance, :invites_enabled])},
          {:ok, invite_token} <- UserInviteToken.create_invite(),
@@ -73,7 +64,7 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenController do
              user,
              invite_token,
              email,
-             params["name"]
+             params[:name]
            ),
          {:ok, _} <- Pleroma.Emails.Mailer.deliver(email) do
       json_response(conn, :no_content, "")
index 09a7735d174db2620fb7cd6ce119d2ebf1600bcf..0f7403f26ac6f03385a287d3c5433e724e12999b 100644 (file)
@@ -5,14 +5,9 @@
 defmodule Pleroma.Web.ApiSpec.Admin.InviteTokenOperation do
   alias OpenApiSpex.Operation
   alias OpenApiSpex.Schema
-  alias Pleroma.Web.ApiSpec.Schemas.Account
   alias Pleroma.Web.ApiSpec.Schemas.ApiError
-  alias Pleroma.Web.ApiSpec.Schemas.FlakeID
-  alias Pleroma.Web.ApiSpec.Schemas.Status
-  alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
 
   import Pleroma.Web.ApiSpec.Helpers
-  import Pleroma.Web.ApiSpec.StatusOperation, only: [id_param: 0]
 
   def open_api_operation(action) do
     operation = String.to_existing_atom("#{action}_operation")
@@ -21,144 +16,132 @@ defmodule Pleroma.Web.ApiSpec.Admin.InviteTokenOperation do
 
   def index_operation do
     %Operation{
-      tags: ["Admin", "Statuses"],
-      operationId: "AdminAPI.StatusController.index",
-      security: [%{"oAuth" => ["read:statuses"]}],
-      parameters: [
-        Operation.parameter(
-          :godmode,
-          :query,
-          %Schema{type: :boolean, default: false},
-          "Allows to see private statuses"
-        ),
-        Operation.parameter(
-          :local_only,
-          :query,
-          %Schema{type: :boolean, default: false},
-          "Excludes remote statuses"
-        ),
-        Operation.parameter(
-          :with_reblogs,
-          :query,
-          %Schema{type: :boolean, default: false},
-          "Allows to see reblogs"
-        ),
-        Operation.parameter(
-          :page,
-          :query,
-          %Schema{type: :integer, default: 1},
-          "Page"
-        ),
-        Operation.parameter(
-          :page_size,
-          :query,
-          %Schema{type: :integer, default: 50},
-          "Number of statuses to return"
-        )
-      ],
+      tags: ["Admin", "Invites"],
+      summary: "Get a list of generated invites",
+      operationId: "AdminAPI.InviteTokenController.index",
+      security: [%{"oAuth" => ["read:invites"]}],
       responses: %{
         200 =>
-          Operation.response("Array of statuses", "application/json", %Schema{
-            type: :array,
-            items: status()
+          Operation.response("Intites", "application/json", %Schema{
+            type: :object,
+            properties: %{
+              invites: %Schema{type: :array, items: invite()}
+            },
+            example: %{
+              "invites" => [
+                %{
+                  "id" => 123,
+                  "token" => "kSQtDj_GNy2NZsL9AQDFIsHN5qdbguB6qRg3WHw6K1U=",
+                  "used" => true,
+                  "expires_at" => nil,
+                  "uses" => 0,
+                  "max_use" => nil,
+                  "invite_type" => "one_time"
+                }
+              ]
+            }
           })
       }
     }
   end
 
-  def show_operation do
+  def create_operation do
     %Operation{
-      tags: ["Admin", "Statuses"],
-      summary: "Show Status",
-      operationId: "AdminAPI.StatusController.show",
-      parameters: [id_param()],
-      security: [%{"oAuth" => ["read:statuses"]}],
+      tags: ["Admin", "Invites"],
+      summary: "Create an account registration invite token",
+      operationId: "AdminAPI.InviteTokenController.create",
+      security: [%{"oAuth" => ["write:invites"]}],
+      requestBody:
+        request_body("Parameters", %Schema{
+          type: :object,
+          properties: %{
+            max_use: %Schema{type: :integer},
+            expires_at: %Schema{type: :string, format: :date, example: "2020-04-20"}
+          }
+        }),
       responses: %{
-        200 => Operation.response("Status", "application/json", Status),
-        404 => Operation.response("Not Found", "application/json", ApiError)
+        200 => Operation.response("Invite", "application/json", invite())
       }
     }
   end
 
-  def update_operation do
+  def revoke_operation do
     %Operation{
-      tags: ["Admin", "Statuses"],
-      summary: "Change the scope of an individual reported status",
-      operationId: "AdminAPI.StatusController.update",
-      parameters: [id_param()],
-      security: [%{"oAuth" => ["write:statuses"]}],
-      requestBody: request_body("Parameters", update_request(), required: true),
+      tags: ["Admin", "Invites"],
+      summary: "Revoke invite by token",
+      operationId: "AdminAPI.InviteTokenController.revoke",
+      security: [%{"oAuth" => ["write:invites"]}],
+      requestBody:
+        request_body(
+          "Parameters",
+          %Schema{
+            type: :object,
+            required: [:token],
+            properties: %{
+              token: %Schema{type: :string}
+            }
+          },
+          required: true
+        ),
       responses: %{
-        200 => Operation.response("Status", "application/json", Status),
-        400 => Operation.response("Error", "application/json", ApiError)
+        200 => Operation.response("Invite", "application/json", invite()),
+        400 => Operation.response("Bad Request", "application/json", ApiError),
+        404 => Operation.response("Not Found", "application/json", ApiError)
       }
     }
   end
 
-  def delete_operation do
+  def email_operation do
     %Operation{
-      tags: ["Admin", "Statuses"],
-      summary: "Delete an individual reported status",
-      operationId: "AdminAPI.StatusController.delete",
-      parameters: [id_param()],
-      security: [%{"oAuth" => ["write:statuses"]}],
+      tags: ["Admin", "Invites"],
+      summary: "Sends registration invite via email",
+      operationId: "AdminAPI.InviteTokenController.email",
+      security: [%{"oAuth" => ["write:invites"]}],
+      requestBody:
+        request_body(
+          "Parameters",
+          %Schema{
+            type: :object,
+            required: [:email],
+            properties: %{
+              email: %Schema{type: :string, format: :email},
+              name: %Schema{type: :string}
+            }
+          },
+          required: true
+        ),
       responses: %{
-        200 => empty_object_response(),
-        404 => Operation.response("Not Found", "application/json", ApiError)
+        204 => no_content_response(),
+        400 => Operation.response("Bad Request", "application/json", ApiError),
+        403 => Operation.response("Forbidden", "application/json", ApiError)
       }
     }
   end
 
-  defp status do
-    %Schema{
-      anyOf: [
-        Status,
-        %Schema{
-          type: :object,
-          properties: %{
-            account: %Schema{allOf: [Account, admin_account()]}
-          }
-        }
-      ]
-    }
-  end
-
-  defp admin_account do
+  defp invite do
     %Schema{
+      title: "Invite",
       type: :object,
       properties: %{
-        id: FlakeID,
-        avatar: %Schema{type: :string},
-        nickname: %Schema{type: :string},
-        display_name: %Schema{type: :string},
-        deactivated: %Schema{type: :boolean},
-        local: %Schema{type: :boolean},
-        roles: %Schema{
-          type: :object,
-          properties: %{
-            admin: %Schema{type: :boolean},
-            moderator: %Schema{type: :boolean}
-          }
-        },
-        tags: %Schema{type: :string},
-        confirmation_pending: %Schema{type: :string}
-      }
-    }
-  end
-
-  defp update_request do
-    %Schema{
-      type: :object,
-      properties: %{
-        sensitive: %Schema{
-          type: :boolean,
-          description: "Mark status and attached media as sensitive?"
-        },
-        visibility: VisibilityScope
+        id: %Schema{type: :integer},
+        token: %Schema{type: :string},
+        used: %Schema{type: :boolean},
+        expires_at: %Schema{type: :string, format: :date, nullable: true},
+        uses: %Schema{type: :integer},
+        max_use: %Schema{type: :integer, nullable: true},
+        invite_type: %Schema{
+          type: :string,
+          enum: ["one_time", "reusable", "date_limited", "reusable_date_limited"]
+        }
       },
       example: %{
-        "visibility" => "private",
-        "sensitive" => "false"
+        "id" => 123,
+        "token" => "kSQtDj_GNy2NZsL9AQDFIsHN5qdbguB6qRg3WHw6K1U=",
+        "used" => true,
+        "expires_at" => nil,
+        "uses" => 0,
+        "max_use" => nil,
+        "invite_type" => "one_time"
       }
     }
   end
index eb57b4d44219a5cdec3694946167f8095591e441..cb486f4d17dddad0847e4cad0deb6672190c460c 100644 (file)
@@ -32,12 +32,14 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
       recipient_name = "J. D."
 
       conn =
-        post(
-          conn,
-          "/api/pleroma/admin/users/email_invite?email=#{recipient_email}&name=#{recipient_name}"
-        )
+        conn
+        |> put_req_header("content-type", "application/json;charset=utf-8")
+        |> post("/api/pleroma/admin/users/email_invite", %{
+          email: recipient_email,
+          name: recipient_name
+        })
 
-      assert json_response(conn, :no_content)
+      assert json_response_and_validate_schema(conn, :no_content)
 
       token_record = List.last(Repo.all(Pleroma.UserInviteToken))
       assert token_record
@@ -69,7 +71,11 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
         build_conn()
         |> assign(:user, non_admin_user)
         |> assign(:token, token)
-        |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
+        |> put_req_header("content-type", "application/json;charset=utf-8")
+        |> post("/api/pleroma/admin/users/email_invite", %{
+          email: "foo@bar.com",
+          name: "JD"
+        })
 
       assert json_response(conn, :forbidden)
     end
@@ -80,7 +86,7 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
       conn
       |> put_req_header("content-type", "application/json;charset=utf-8")
       |> post("/api/pleroma/admin/users/email_invite", %{email: recipient_email})
-      |> json_response(:no_content)
+      |> json_response_and_validate_schema(:no_content)
 
       token_record =
         Pleroma.UserInviteToken
@@ -116,9 +122,15 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
       Config.put([:instance, :registrations_open], false)
       Config.put([:instance, :invites_enabled], false)
 
-      conn = post(conn, "/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
+      conn =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/pleroma/admin/users/email_invite", %{
+          email: "foo@bar.com",
+          name: "JD"
+        })
 
-      assert json_response(conn, :bad_request) ==
+      assert json_response_and_validate_schema(conn, :bad_request) ==
                %{
                  "error" =>
                    "To send invites you need to set the `invites_enabled` option to true."
@@ -129,9 +141,15 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
       Config.put([:instance, :registrations_open], true)
       Config.put([:instance, :invites_enabled], true)
 
-      conn = post(conn, "/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
+      conn =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/pleroma/admin/users/email_invite", %{
+          email: "foo@bar.com",
+          name: "JD"
+        })
 
-      assert json_response(conn, :bad_request) ==
+      assert json_response_and_validate_schema(conn, :bad_request) ==
                %{
                  "error" =>
                    "To send invites you need to set the `registrations_open` option to false."
@@ -141,9 +159,12 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
 
   describe "POST /api/pleroma/admin/users/invite_token" do
     test "without options", %{conn: conn} do
-      conn = post(conn, "/api/pleroma/admin/users/invite_token")
+      conn =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/pleroma/admin/users/invite_token")
 
-      invite_json = json_response(conn, 200)
+      invite_json = json_response_and_validate_schema(conn, 200)
       invite = UserInviteToken.find_by_token!(invite_json["token"])
       refute invite.used
       refute invite.expires_at
@@ -153,11 +174,13 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
 
     test "with expires_at", %{conn: conn} do
       conn =
-        post(conn, "/api/pleroma/admin/users/invite_token", %{
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/pleroma/admin/users/invite_token", %{
           "expires_at" => Date.to_string(Date.utc_today())
         })
 
-      invite_json = json_response(conn, 200)
+      invite_json = json_response_and_validate_schema(conn, 200)
       invite = UserInviteToken.find_by_token!(invite_json["token"])
 
       refute invite.used
@@ -167,9 +190,12 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
     end
 
     test "with max_use", %{conn: conn} do
-      conn = post(conn, "/api/pleroma/admin/users/invite_token", %{"max_use" => 150})
+      conn =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/pleroma/admin/users/invite_token", %{"max_use" => 150})
 
-      invite_json = json_response(conn, 200)
+      invite_json = json_response_and_validate_schema(conn, 200)
       invite = UserInviteToken.find_by_token!(invite_json["token"])
       refute invite.used
       refute invite.expires_at
@@ -179,12 +205,14 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
 
     test "with max use and expires_at", %{conn: conn} do
       conn =
-        post(conn, "/api/pleroma/admin/users/invite_token", %{
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/pleroma/admin/users/invite_token", %{
           "max_use" => 150,
           "expires_at" => Date.to_string(Date.utc_today())
         })
 
-      invite_json = json_response(conn, 200)
+      invite_json = json_response_and_validate_schema(conn, 200)
       invite = UserInviteToken.find_by_token!(invite_json["token"])
       refute invite.used
       assert invite.expires_at == Date.utc_today()
@@ -197,7 +225,7 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
     test "no invites", %{conn: conn} do
       conn = get(conn, "/api/pleroma/admin/users/invites")
 
-      assert json_response(conn, 200) == %{"invites" => []}
+      assert json_response_and_validate_schema(conn, 200) == %{"invites" => []}
     end
 
     test "with invite", %{conn: conn} do
@@ -205,7 +233,7 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
 
       conn = get(conn, "/api/pleroma/admin/users/invites")
 
-      assert json_response(conn, 200) == %{
+      assert json_response_and_validate_schema(conn, 200) == %{
                "invites" => [
                  %{
                    "expires_at" => nil,
@@ -225,9 +253,12 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
     test "with token", %{conn: conn} do
       {:ok, invite} = UserInviteToken.create_invite()
 
-      conn = post(conn, "/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token})
+      conn =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token})
 
-      assert json_response(conn, 200) == %{
+      assert json_response_and_validate_schema(conn, 200) == %{
                "expires_at" => nil,
                "id" => invite.id,
                "invite_type" => "one_time",
@@ -239,9 +270,12 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
     end
 
     test "with invalid token", %{conn: conn} do
-      conn = post(conn, "/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"})
+      conn =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"})
 
-      assert json_response(conn, :not_found) == %{"error" => "Not found"}
+      assert json_response_and_validate_schema(conn, :not_found) == %{"error" => "Not found"}
     end
   end
 end