Add OpenAPI spec for AdminAPI.InviteTokenController

This commit is contained in:
Egor Kislitsyn 2020-05-26 15:02:51 +04:00
parent 95ebfb9190
commit 2a4f965191
No known key found for this signature in database
GPG key ID: 1B49CB15B71E7805
3 changed files with 179 additions and 171 deletions

View file

@ -14,6 +14,7 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenController do
require Logger require Logger
plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug(OAuthScopesPlug, %{scopes: ["read:invites"], admin: true} when action == :index) plug(OAuthScopesPlug, %{scopes: ["read:invites"], admin: true} when action == :index)
plug( plug(
@ -23,6 +24,8 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenController do
action_fallback(Pleroma.Web.AdminAPI.FallbackController) action_fallback(Pleroma.Web.AdminAPI.FallbackController)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.InviteTokenOperation
@doc "Get list of created invites" @doc "Get list of created invites"
def index(conn, _params) do def index(conn, _params) do
invites = UserInviteToken.list_invites() invites = UserInviteToken.list_invites()
@ -33,26 +36,14 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenController do
end end
@doc "Create an account registration invite token" @doc "Create an account registration invite token"
def create(conn, params) do def create(%{body_params: params} = conn, _) do
opts = %{} {:ok, invite} = UserInviteToken.create_invite(params)
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)
json(conn, AccountView.render("invite.json", %{invite: invite})) json(conn, AccountView.render("invite.json", %{invite: invite}))
end end
@doc "Revokes invite by token" @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), with {:ok, invite} <- UserInviteToken.find_by_token(token),
{:ok, updated_invite} = UserInviteToken.update_invite(invite, %{used: true}) do {:ok, updated_invite} = UserInviteToken.update_invite(invite, %{used: true}) do
conn conn
@ -64,7 +55,7 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenController do
end end
@doc "Sends registration invite via email" @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])}, with {_, false} <- {:registrations_open, Config.get([:instance, :registrations_open])},
{_, true} <- {:invites_enabled, Config.get([:instance, :invites_enabled])}, {_, true} <- {:invites_enabled, Config.get([:instance, :invites_enabled])},
{:ok, invite_token} <- UserInviteToken.create_invite(), {:ok, invite_token} <- UserInviteToken.create_invite(),
@ -73,7 +64,7 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenController do
user, user,
invite_token, invite_token,
email, email,
params["name"] params[:name]
), ),
{:ok, _} <- Pleroma.Emails.Mailer.deliver(email) do {:ok, _} <- Pleroma.Emails.Mailer.deliver(email) do
json_response(conn, :no_content, "") json_response(conn, :no_content, "")

View file

@ -5,14 +5,9 @@
defmodule Pleroma.Web.ApiSpec.Admin.InviteTokenOperation do defmodule Pleroma.Web.ApiSpec.Admin.InviteTokenOperation do
alias OpenApiSpex.Operation alias OpenApiSpex.Operation
alias OpenApiSpex.Schema alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.Schemas.Account
alias Pleroma.Web.ApiSpec.Schemas.ApiError 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.Helpers
import Pleroma.Web.ApiSpec.StatusOperation, only: [id_param: 0]
def open_api_operation(action) do def open_api_operation(action) do
operation = String.to_existing_atom("#{action}_operation") operation = String.to_existing_atom("#{action}_operation")
@ -21,144 +16,132 @@ defmodule Pleroma.Web.ApiSpec.Admin.InviteTokenOperation do
def index_operation do def index_operation do
%Operation{ %Operation{
tags: ["Admin", "Statuses"], tags: ["Admin", "Invites"],
operationId: "AdminAPI.StatusController.index", summary: "Get a list of generated invites",
security: [%{"oAuth" => ["read:statuses"]}], operationId: "AdminAPI.InviteTokenController.index",
parameters: [ security: [%{"oAuth" => ["read:invites"]}],
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"
)
],
responses: %{ responses: %{
200 => 200 =>
Operation.response("Array of statuses", "application/json", %Schema{ Operation.response("Intites", "application/json", %Schema{
type: :array, type: :object,
items: status() 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 end
def show_operation do def create_operation do
%Operation{ %Operation{
tags: ["Admin", "Statuses"], tags: ["Admin", "Invites"],
summary: "Show Status", summary: "Create an account registration invite token",
operationId: "AdminAPI.StatusController.show", operationId: "AdminAPI.InviteTokenController.create",
parameters: [id_param()], security: [%{"oAuth" => ["write:invites"]}],
security: [%{"oAuth" => ["read:statuses"]}], requestBody:
responses: %{ request_body("Parameters", %Schema{
200 => Operation.response("Status", "application/json", Status),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
def update_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),
responses: %{
200 => Operation.response("Status", "application/json", Status),
400 => Operation.response("Error", "application/json", ApiError)
}
}
end
def delete_operation do
%Operation{
tags: ["Admin", "Statuses"],
summary: "Delete an individual reported status",
operationId: "AdminAPI.StatusController.delete",
parameters: [id_param()],
security: [%{"oAuth" => ["write:statuses"]}],
responses: %{
200 => empty_object_response(),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
defp status do
%Schema{
anyOf: [
Status,
%Schema{
type: :object, type: :object,
properties: %{ properties: %{
account: %Schema{allOf: [Account, admin_account()]} max_use: %Schema{type: :integer},
expires_at: %Schema{type: :string, format: :date, example: "2020-04-20"}
} }
}),
responses: %{
200 => Operation.response("Invite", "application/json", invite())
}
}
end
def revoke_operation do
%Operation{
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("Invite", "application/json", invite()),
400 => Operation.response("Bad Request", "application/json", ApiError),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
def email_operation do
%Operation{
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: %{
204 => no_content_response(),
400 => Operation.response("Bad Request", "application/json", ApiError),
403 => Operation.response("Forbidden", "application/json", ApiError)
}
}
end
defp invite do
%Schema{
title: "Invite",
type: :object,
properties: %{
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"]
} }
]
}
end
defp admin_account do
%Schema{
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
}, },
example: %{ example: %{
"visibility" => "private", "id" => 123,
"sensitive" => "false" "token" => "kSQtDj_GNy2NZsL9AQDFIsHN5qdbguB6qRg3WHw6K1U=",
"used" => true,
"expires_at" => nil,
"uses" => 0,
"max_use" => nil,
"invite_type" => "one_time"
} }
} }
end end

View file

@ -32,12 +32,14 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
recipient_name = "J. D." recipient_name = "J. D."
conn = conn =
post( conn
conn, |> put_req_header("content-type", "application/json;charset=utf-8")
"/api/pleroma/admin/users/email_invite?email=#{recipient_email}&name=#{recipient_name}" |> 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)) token_record = List.last(Repo.all(Pleroma.UserInviteToken))
assert token_record assert token_record
@ -69,7 +71,11 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
build_conn() build_conn()
|> assign(:user, non_admin_user) |> assign(:user, non_admin_user)
|> assign(:token, token) |> 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) assert json_response(conn, :forbidden)
end end
@ -80,7 +86,7 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
conn conn
|> put_req_header("content-type", "application/json;charset=utf-8") |> put_req_header("content-type", "application/json;charset=utf-8")
|> post("/api/pleroma/admin/users/email_invite", %{email: recipient_email}) |> post("/api/pleroma/admin/users/email_invite", %{email: recipient_email})
|> json_response(:no_content) |> json_response_and_validate_schema(:no_content)
token_record = token_record =
Pleroma.UserInviteToken Pleroma.UserInviteToken
@ -116,9 +122,15 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
Config.put([:instance, :registrations_open], false) Config.put([:instance, :registrations_open], false)
Config.put([:instance, :invites_enabled], 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" => "error" =>
"To send invites you need to set the `invites_enabled` option to true." "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, :registrations_open], true)
Config.put([:instance, :invites_enabled], 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" => "error" =>
"To send invites you need to set the `registrations_open` option to false." "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 describe "POST /api/pleroma/admin/users/invite_token" do
test "without options", %{conn: conn} 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"]) invite = UserInviteToken.find_by_token!(invite_json["token"])
refute invite.used refute invite.used
refute invite.expires_at refute invite.expires_at
@ -153,11 +174,13 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
test "with expires_at", %{conn: conn} do test "with expires_at", %{conn: conn} do
conn = 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()) "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"]) invite = UserInviteToken.find_by_token!(invite_json["token"])
refute invite.used refute invite.used
@ -167,9 +190,12 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
end end
test "with max_use", %{conn: conn} do 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"]) invite = UserInviteToken.find_by_token!(invite_json["token"])
refute invite.used refute invite.used
refute invite.expires_at refute invite.expires_at
@ -179,12 +205,14 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
test "with max use and expires_at", %{conn: conn} do test "with max use and expires_at", %{conn: conn} do
conn = 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, "max_use" => 150,
"expires_at" => Date.to_string(Date.utc_today()) "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"]) invite = UserInviteToken.find_by_token!(invite_json["token"])
refute invite.used refute invite.used
assert invite.expires_at == Date.utc_today() assert invite.expires_at == Date.utc_today()
@ -197,7 +225,7 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
test "no invites", %{conn: conn} do test "no invites", %{conn: conn} do
conn = get(conn, "/api/pleroma/admin/users/invites") conn = get(conn, "/api/pleroma/admin/users/invites")
assert json_response(conn, 200) == %{"invites" => []} assert json_response_and_validate_schema(conn, 200) == %{"invites" => []}
end end
test "with invite", %{conn: conn} do test "with invite", %{conn: conn} do
@ -205,7 +233,7 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
conn = get(conn, "/api/pleroma/admin/users/invites") conn = get(conn, "/api/pleroma/admin/users/invites")
assert json_response(conn, 200) == %{ assert json_response_and_validate_schema(conn, 200) == %{
"invites" => [ "invites" => [
%{ %{
"expires_at" => nil, "expires_at" => nil,
@ -225,9 +253,12 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
test "with token", %{conn: conn} do test "with token", %{conn: conn} do
{:ok, invite} = UserInviteToken.create_invite() {: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, "expires_at" => nil,
"id" => invite.id, "id" => invite.id,
"invite_type" => "one_time", "invite_type" => "one_time",
@ -239,9 +270,12 @@ defmodule Pleroma.Web.AdminAPI.InviteTokenControllerTest do
end end
test "with invalid token", %{conn: conn} do 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 end
end end