From fca48154a23c0b38d514b2bc4d49a74274e02a8f Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Tue, 26 May 2020 15:21:33 +0400 Subject: Add AdminAPI.InviteView --- .../web/admin_api/controllers/invite_controller.ex | 78 +++++++++++ .../controllers/invite_token_controller.ex | 79 ----------- lib/pleroma/web/admin_api/views/account_view.ex | 18 --- lib/pleroma/web/admin_api/views/invite_view.ex | 25 ++++ .../api_spec/operations/admin/invite_operation.ex | 148 +++++++++++++++++++++ .../operations/admin/invite_token_operation.ex | 148 --------------------- lib/pleroma/web/router.ex | 8 +- 7 files changed, 255 insertions(+), 249 deletions(-) create mode 100644 lib/pleroma/web/admin_api/controllers/invite_controller.ex delete mode 100644 lib/pleroma/web/admin_api/controllers/invite_token_controller.ex create mode 100644 lib/pleroma/web/admin_api/views/invite_view.ex create mode 100644 lib/pleroma/web/api_spec/operations/admin/invite_operation.ex delete mode 100644 lib/pleroma/web/api_spec/operations/admin/invite_token_operation.ex (limited to 'lib') diff --git a/lib/pleroma/web/admin_api/controllers/invite_controller.ex b/lib/pleroma/web/admin_api/controllers/invite_controller.ex new file mode 100644 index 000000000..7d169b8d2 --- /dev/null +++ b/lib/pleroma/web/admin_api/controllers/invite_controller.ex @@ -0,0 +1,78 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.InviteController do + use Pleroma.Web, :controller + + import Pleroma.Web.ControllerHelper, only: [json_response: 3] + + alias Pleroma.Config + alias Pleroma.Plugs.OAuthScopesPlug + alias Pleroma.UserInviteToken + + require Logger + + plug(Pleroma.Web.ApiSpec.CastAndValidate) + plug(OAuthScopesPlug, %{scopes: ["read:invites"], admin: true} when action == :index) + + plug( + OAuthScopesPlug, + %{scopes: ["write:invites"], admin: true} when action in [:create, :revoke, :email] + ) + + action_fallback(Pleroma.Web.AdminAPI.FallbackController) + + defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.InviteOperation + + @doc "Get list of created invites" + def index(conn, _params) do + invites = UserInviteToken.list_invites() + + render(conn, "index.json", invites: invites) + end + + @doc "Create an account registration invite token" + def create(%{body_params: params} = conn, _) do + {:ok, invite} = UserInviteToken.create_invite(params) + + render(conn, "show.json", invite: invite) + end + + @doc "Revokes invite by token" + 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 + render(conn, "show.json", invite: updated_invite) + else + nil -> {:error, :not_found} + error -> error + end + end + + @doc "Sends registration invite via email" + 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(), + {:ok, _} <- + user + |> Pleroma.Emails.UserEmail.user_invitation_email( + invite_token, + email, + params[:name] + ) + |> Pleroma.Emails.Mailer.deliver() do + json_response(conn, :no_content, "") + else + {:registrations_open, _} -> + {:error, "To send invites you need to set the `registrations_open` option to false."} + + {:invites_enabled, _} -> + {:error, "To send invites you need to set the `invites_enabled` option to true."} + + {:error, error} -> + {:error, error} + end + end +end diff --git a/lib/pleroma/web/admin_api/controllers/invite_token_controller.ex b/lib/pleroma/web/admin_api/controllers/invite_token_controller.ex deleted file mode 100644 index a09966e5c..000000000 --- a/lib/pleroma/web/admin_api/controllers/invite_token_controller.ex +++ /dev/null @@ -1,79 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.AdminAPI.InviteTokenController do - use Pleroma.Web, :controller - - import Pleroma.Web.ControllerHelper, only: [json_response: 3] - - alias Pleroma.Config - alias Pleroma.Plugs.OAuthScopesPlug - alias Pleroma.UserInviteToken - alias Pleroma.Web.AdminAPI.AccountView - - require Logger - - plug(Pleroma.Web.ApiSpec.CastAndValidate) - plug(OAuthScopesPlug, %{scopes: ["read:invites"], admin: true} when action == :index) - - plug( - OAuthScopesPlug, - %{scopes: ["write:invites"], admin: true} when action in [:create, :revoke, :email] - ) - - 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() - - conn - |> put_view(AccountView) - |> render("invites.json", %{invites: invites}) - end - - @doc "Create an account registration invite token" - 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(%{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 - |> put_view(AccountView) - |> render("invite.json", %{invite: updated_invite}) - else - nil -> {:error, :not_found} - end - end - - @doc "Sends registration invite via email" - 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(), - email <- - Pleroma.Emails.UserEmail.user_invitation_email( - user, - invite_token, - email, - params[:name] - ), - {:ok, _} <- Pleroma.Emails.Mailer.deliver(email) do - json_response(conn, :no_content, "") - else - {:registrations_open, _} -> - {:error, "To send invites you need to set the `registrations_open` option to false."} - - {:invites_enabled, _} -> - {:error, "To send invites you need to set the `invites_enabled` option to true."} - end - end -end diff --git a/lib/pleroma/web/admin_api/views/account_view.ex b/lib/pleroma/web/admin_api/views/account_view.ex index 46dadb5ee..120159527 100644 --- a/lib/pleroma/web/admin_api/views/account_view.ex +++ b/lib/pleroma/web/admin_api/views/account_view.ex @@ -80,24 +80,6 @@ defmodule Pleroma.Web.AdminAPI.AccountView do } end - def render("invite.json", %{invite: invite}) do - %{ - "id" => invite.id, - "token" => invite.token, - "used" => invite.used, - "expires_at" => invite.expires_at, - "uses" => invite.uses, - "max_use" => invite.max_use, - "invite_type" => invite.invite_type - } - end - - def render("invites.json", %{invites: invites}) do - %{ - invites: render_many(invites, AccountView, "invite.json", as: :invite) - } - end - def render("created.json", %{user: user}) do %{ type: "success", diff --git a/lib/pleroma/web/admin_api/views/invite_view.ex b/lib/pleroma/web/admin_api/views/invite_view.ex new file mode 100644 index 000000000..f93cb6916 --- /dev/null +++ b/lib/pleroma/web/admin_api/views/invite_view.ex @@ -0,0 +1,25 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.InviteView do + use Pleroma.Web, :view + + def render("index.json", %{invites: invites}) do + %{ + invites: render_many(invites, __MODULE__, "show.json", as: :invite) + } + end + + def render("show.json", %{invite: invite}) do + %{ + "id" => invite.id, + "token" => invite.token, + "used" => invite.used, + "expires_at" => invite.expires_at, + "uses" => invite.uses, + "max_use" => invite.max_use, + "invite_type" => invite.invite_type + } + end +end diff --git a/lib/pleroma/web/api_spec/operations/admin/invite_operation.ex b/lib/pleroma/web/api_spec/operations/admin/invite_operation.ex new file mode 100644 index 000000000..4ae44fff6 --- /dev/null +++ b/lib/pleroma/web/api_spec/operations/admin/invite_operation.ex @@ -0,0 +1,148 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ApiSpec.Admin.InviteOperation do + alias OpenApiSpex.Operation + alias OpenApiSpex.Schema + alias Pleroma.Web.ApiSpec.Schemas.ApiError + + import Pleroma.Web.ApiSpec.Helpers + + def open_api_operation(action) do + operation = String.to_existing_atom("#{action}_operation") + apply(__MODULE__, operation, []) + end + + def index_operation do + %Operation{ + tags: ["Admin", "Invites"], + summary: "Get a list of generated invites", + operationId: "AdminAPI.InviteController.index", + security: [%{"oAuth" => ["read:invites"]}], + responses: %{ + 200 => + 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 create_operation do + %Operation{ + tags: ["Admin", "Invites"], + summary: "Create an account registration invite token", + operationId: "AdminAPI.InviteController.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("Invite", "application/json", invite()) + } + } + end + + def revoke_operation do + %Operation{ + tags: ["Admin", "Invites"], + summary: "Revoke invite by token", + operationId: "AdminAPI.InviteController.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.InviteController.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"] + } + }, + example: %{ + "id" => 123, + "token" => "kSQtDj_GNy2NZsL9AQDFIsHN5qdbguB6qRg3WHw6K1U=", + "used" => true, + "expires_at" => nil, + "uses" => 0, + "max_use" => nil, + "invite_type" => "one_time" + } + } + end +end diff --git a/lib/pleroma/web/api_spec/operations/admin/invite_token_operation.ex b/lib/pleroma/web/api_spec/operations/admin/invite_token_operation.ex deleted file mode 100644 index 0f7403f26..000000000 --- a/lib/pleroma/web/api_spec/operations/admin/invite_token_operation.ex +++ /dev/null @@ -1,148 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.ApiSpec.Admin.InviteTokenOperation do - alias OpenApiSpex.Operation - alias OpenApiSpex.Schema - alias Pleroma.Web.ApiSpec.Schemas.ApiError - - import Pleroma.Web.ApiSpec.Helpers - - def open_api_operation(action) do - operation = String.to_existing_atom("#{action}_operation") - apply(__MODULE__, operation, []) - end - - def index_operation do - %Operation{ - tags: ["Admin", "Invites"], - summary: "Get a list of generated invites", - operationId: "AdminAPI.InviteTokenController.index", - security: [%{"oAuth" => ["read:invites"]}], - responses: %{ - 200 => - 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 create_operation do - %Operation{ - 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("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"] - } - }, - example: %{ - "id" => 123, - "token" => "kSQtDj_GNy2NZsL9AQDFIsHN5qdbguB6qRg3WHw6K1U=", - "used" => true, - "expires_at" => nil, - "uses" => 0, - "max_use" => nil, - "invite_type" => "one_time" - } - } - end -end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index fe36f0189..9b7c7ee3d 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -164,10 +164,10 @@ defmodule Pleroma.Web.Router do post("/relay", AdminAPIController, :relay_follow) delete("/relay", AdminAPIController, :relay_unfollow) - post("/users/invite_token", InviteTokenController, :create) - get("/users/invites", InviteTokenController, :index) - post("/users/revoke_invite", InviteTokenController, :revoke) - post("/users/email_invite", InviteTokenController, :email) + post("/users/invite_token", InviteController, :create) + get("/users/invites", InviteController, :index) + post("/users/revoke_invite", InviteController, :revoke) + post("/users/email_invite", InviteController, :email) get("/users/:nickname/password_reset", AdminAPIController, :get_password_reset) patch("/users/force_password_reset", AdminAPIController, :force_password_reset) -- cgit v1.2.3