@@ -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.PleromaMascotOperation 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 show_operation do | |||
%Operation{ | |||
tags: ["Mascot"], | |||
summary: "Gets user mascot image", | |||
security: [%{"oAuth" => ["read:accounts"]}], | |||
operationId: "PleromaAPI.MascotController.show", | |||
responses: %{ | |||
200 => Operation.response("Mascot", "application/json", mascot()) | |||
} | |||
} | |||
end | |||
def update_operation do | |||
%Operation{ | |||
tags: ["Mascot"], | |||
summary: "Set/clear user avatar image", | |||
description: | |||
"Behaves exactly the same as `POST /api/v1/upload`. Can only accept images - any attempt to upload non-image files will be met with `HTTP 415 Unsupported Media Type`.", | |||
operationId: "PleromaAPI.MascotController.update", | |||
requestBody: | |||
request_body( | |||
"Parameters", | |||
%Schema{ | |||
type: :object, | |||
properties: %{ | |||
file: %Schema{type: :string, format: :binary} | |||
} | |||
}, | |||
required: true | |||
), | |||
security: [%{"oAuth" => ["write:accounts"]}], | |||
responses: %{ | |||
200 => Operation.response("Mascot", "application/json", mascot()), | |||
415 => Operation.response("Unsupported Media Type", "application/json", ApiError) | |||
} | |||
} | |||
end | |||
defp mascot do | |||
%Schema{ | |||
type: :object, | |||
properties: %{ | |||
id: %Schema{type: :string}, | |||
url: %Schema{type: :string, format: :uri}, | |||
type: %Schema{type: :string}, | |||
pleroma: %Schema{ | |||
type: :object, | |||
properties: %{ | |||
mime_type: %Schema{type: :string} | |||
} | |||
} | |||
}, | |||
example: %{ | |||
"id" => "abcdefg", | |||
"url" => "https://pleroma.example.org/media/abcdefg.png", | |||
"type" => "image", | |||
"pleroma" => %{ | |||
"mime_type" => "image/png" | |||
} | |||
} | |||
} | |||
end | |||
end |
@@ -9,16 +9,19 @@ defmodule Pleroma.Web.PleromaAPI.MascotController do | |||
alias Pleroma.User | |||
alias Pleroma.Web.ActivityPub.ActivityPub | |||
plug(Pleroma.Web.ApiSpec.CastAndValidate) | |||
plug(OAuthScopesPlug, %{scopes: ["read:accounts"]} when action == :show) | |||
plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action != :show) | |||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaMascotOperation | |||
@doc "GET /api/v1/pleroma/mascot" | |||
def show(%{assigns: %{user: user}} = conn, _params) do | |||
json(conn, User.get_mascot(user)) | |||
end | |||
@doc "PUT /api/v1/pleroma/mascot" | |||
def update(%{assigns: %{user: user}} = conn, %{"file" => file}) do | |||
def update(%{assigns: %{user: user}, body_params: %{file: file}} = conn, _) do | |||
with {:ok, object} <- ActivityPub.upload(file, actor: User.ap_id(user)), | |||
# Reject if not an image | |||
%{type: "image"} = attachment <- render_attachment(object) do | |||
@@ -16,9 +16,12 @@ defmodule Pleroma.Web.PleromaAPI.MascotControllerTest do | |||
filename: "sound.mp3" | |||
} | |||
ret_conn = put(conn, "/api/v1/pleroma/mascot", %{"file" => non_image_file}) | |||
ret_conn = | |||
conn | |||
|> put_req_header("content-type", "multipart/form-data") | |||
|> put("/api/v1/pleroma/mascot", %{"file" => non_image_file}) | |||
assert json_response(ret_conn, 415) | |||
assert json_response_and_validate_schema(ret_conn, 415) | |||
file = %Plug.Upload{ | |||
content_type: "image/jpg", | |||
@@ -26,9 +29,12 @@ defmodule Pleroma.Web.PleromaAPI.MascotControllerTest do | |||
filename: "an_image.jpg" | |||
} | |||
conn = put(conn, "/api/v1/pleroma/mascot", %{"file" => file}) | |||
conn = | |||
conn | |||
|> put_req_header("content-type", "multipart/form-data") | |||
|> put("/api/v1/pleroma/mascot", %{"file" => file}) | |||
assert %{"id" => _, "type" => image} = json_response(conn, 200) | |||
assert %{"id" => _, "type" => image} = json_response_and_validate_schema(conn, 200) | |||
end | |||
test "mascot retrieving" do | |||
@@ -37,7 +43,7 @@ defmodule Pleroma.Web.PleromaAPI.MascotControllerTest do | |||
# When user hasn't set a mascot, we should just get pleroma tan back | |||
ret_conn = get(conn, "/api/v1/pleroma/mascot") | |||
assert %{"url" => url} = json_response(ret_conn, 200) | |||
assert %{"url" => url} = json_response_and_validate_schema(ret_conn, 200) | |||
assert url =~ "pleroma-fox-tan-smol" | |||
# When a user sets their mascot, we should get that back | |||
@@ -47,9 +53,12 @@ defmodule Pleroma.Web.PleromaAPI.MascotControllerTest do | |||
filename: "an_image.jpg" | |||
} | |||
ret_conn = put(conn, "/api/v1/pleroma/mascot", %{"file" => file}) | |||
ret_conn = | |||
conn | |||
|> put_req_header("content-type", "multipart/form-data") | |||
|> put("/api/v1/pleroma/mascot", %{"file" => file}) | |||
assert json_response(ret_conn, 200) | |||
assert json_response_and_validate_schema(ret_conn, 200) | |||
user = User.get_cached_by_id(user.id) | |||
@@ -58,7 +67,7 @@ defmodule Pleroma.Web.PleromaAPI.MascotControllerTest do | |||
|> assign(:user, user) | |||
|> get("/api/v1/pleroma/mascot") | |||
assert %{"url" => url, "type" => "image"} = json_response(conn, 200) | |||
assert %{"url" => url, "type" => "image"} = json_response_and_validate_schema(conn, 200) | |||
assert url =~ "an_image" | |||
end | |||
end |