Add spec for AccountController.update_credentials
This commit is contained in:
parent
f80116125f
commit
260cbddc94
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
defmodule Pleroma.Web.ApiSpec.Helpers do
|
defmodule Pleroma.Web.ApiSpec.Helpers do
|
||||||
def request_body(description, schema_ref, opts \\ []) do
|
def request_body(description, schema_ref, opts \\ []) do
|
||||||
media_types = ["application/json", "multipart/form-data"]
|
media_types = ["application/json", "multipart/form-data", "application/x-www-form-urlencoded"]
|
||||||
|
|
||||||
content =
|
content =
|
||||||
media_types
|
media_types
|
||||||
|
|
|
@ -8,6 +8,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.Account
|
alias Pleroma.Web.ApiSpec.Schemas.Account
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.AccountCreateRequest
|
alias Pleroma.Web.ApiSpec.Schemas.AccountCreateRequest
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.AccountCreateResponse
|
alias Pleroma.Web.ApiSpec.Schemas.AccountCreateResponse
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.AccountUpdateCredentialsRequest
|
||||||
|
|
||||||
@spec open_api_operation(atom) :: Operation.t()
|
@spec open_api_operation(atom) :: Operation.t()
|
||||||
def open_api_operation(action) do
|
def open_api_operation(action) do
|
||||||
|
@ -44,7 +45,18 @@ def verify_credentials_operation do
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_credentials_operation do
|
def update_credentials_operation do
|
||||||
:ok
|
%Operation{
|
||||||
|
tags: ["accounts"],
|
||||||
|
summary: "Update account credentials",
|
||||||
|
description: "Update the user's display and preferences.",
|
||||||
|
operationId: "AccountController.update_credentials",
|
||||||
|
security: [%{"oAuth" => ["write:accounts"]}],
|
||||||
|
requestBody:
|
||||||
|
Helpers.request_body("Parameters", AccountUpdateCredentialsRequest, required: true),
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("Account", "application/json", Account)
|
||||||
|
}
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def relationships_operation do
|
def relationships_operation do
|
||||||
|
|
26
lib/pleroma/web/api_spec/schemas/account_field_attribute.ex
Normal file
26
lib/pleroma/web/api_spec/schemas/account_field_attribute.ex
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# 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.Schemas.AccountAttributeField do
|
||||||
|
alias OpenApiSpex.Schema
|
||||||
|
|
||||||
|
require OpenApiSpex
|
||||||
|
|
||||||
|
OpenApiSpex.schema(%{
|
||||||
|
title: "AccountAttributeField",
|
||||||
|
description: "Request schema for account custom fields",
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
name: %Schema{type: :string},
|
||||||
|
value: %Schema{type: :string}
|
||||||
|
},
|
||||||
|
required: [:name, :value],
|
||||||
|
example: %{
|
||||||
|
"JSON" => %{
|
||||||
|
"name" => "Website",
|
||||||
|
"value" => "https://pleroma.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
end
|
|
@ -0,0 +1,123 @@
|
||||||
|
# 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.Schemas.AccountUpdateCredentialsRequest do
|
||||||
|
alias OpenApiSpex.Schema
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.AccountAttributeField
|
||||||
|
require OpenApiSpex
|
||||||
|
|
||||||
|
OpenApiSpex.schema(%{
|
||||||
|
title: "AccountUpdateCredentialsRequest",
|
||||||
|
description: "POST body for creating an account",
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
bot: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "Whether the account has a bot flag."
|
||||||
|
},
|
||||||
|
display_name: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "The display name to use for the profile."
|
||||||
|
},
|
||||||
|
note: %Schema{type: :string, description: "The account bio."},
|
||||||
|
avatar: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "Avatar image encoded using multipart/form-data",
|
||||||
|
format: :binary
|
||||||
|
},
|
||||||
|
header: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "Header image encoded using multipart/form-data",
|
||||||
|
format: :binary
|
||||||
|
},
|
||||||
|
locked: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "Whether manual approval of follow requests is required."
|
||||||
|
},
|
||||||
|
fields_attributes: %Schema{
|
||||||
|
oneOf: [%Schema{type: :array, items: AccountAttributeField}, %Schema{type: :object}]
|
||||||
|
},
|
||||||
|
# NOTE: `source` field is not supported
|
||||||
|
#
|
||||||
|
# source: %Schema{
|
||||||
|
# type: :object,
|
||||||
|
# properties: %{
|
||||||
|
# privacy: %Schema{type: :string},
|
||||||
|
# sensitive: %Schema{type: :boolean},
|
||||||
|
# language: %Schema{type: :string}
|
||||||
|
# }
|
||||||
|
# },
|
||||||
|
|
||||||
|
# Pleroma-specific fields
|
||||||
|
no_rich_text: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "html tags are stripped from all statuses requested from the API"
|
||||||
|
},
|
||||||
|
hide_followers: %Schema{type: :boolean, description: "user's followers will be hidden"},
|
||||||
|
hide_follows: %Schema{type: :boolean, description: "user's follows will be hidden"},
|
||||||
|
hide_followers_count: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "user's follower count will be hidden"
|
||||||
|
},
|
||||||
|
hide_follows_count: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "user's follow count will be hidden"
|
||||||
|
},
|
||||||
|
hide_favorites: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "user's favorites timeline will be hidden"
|
||||||
|
},
|
||||||
|
show_role: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "user's role (e.g admin, moderator) will be exposed to anyone in the
|
||||||
|
API"
|
||||||
|
},
|
||||||
|
default_scope: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "The scope returned under privacy key in Source subentity"
|
||||||
|
},
|
||||||
|
pleroma_settings_store: %Schema{
|
||||||
|
type: :object,
|
||||||
|
description: "Opaque user settings to be saved on the backend."
|
||||||
|
},
|
||||||
|
skip_thread_containment: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "Skip filtering out broken threads"
|
||||||
|
},
|
||||||
|
allow_following_move: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "Allows automatically follow moved following accounts"
|
||||||
|
},
|
||||||
|
pleroma_background_image: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "Sets the background image of the user.",
|
||||||
|
format: :binary
|
||||||
|
},
|
||||||
|
discoverable: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "Discovery of this account in search results and other services is allowed."
|
||||||
|
},
|
||||||
|
actor_type: %Schema{type: :string, description: "the type of this account."}
|
||||||
|
},
|
||||||
|
example: %{
|
||||||
|
bot: false,
|
||||||
|
display_name: "cofe",
|
||||||
|
note: "foobar",
|
||||||
|
fields_attributes: [%{name: "foo", value: "bar"}],
|
||||||
|
no_rich_text: false,
|
||||||
|
hide_followers: true,
|
||||||
|
hide_follows: false,
|
||||||
|
hide_followers_count: false,
|
||||||
|
hide_follows_count: false,
|
||||||
|
hide_favorites: false,
|
||||||
|
show_role: false,
|
||||||
|
default_scope: "private",
|
||||||
|
pleroma_settings_store: %{"pleroma-fe" => %{"key" => "val"}},
|
||||||
|
skip_thread_containment: false,
|
||||||
|
allow_following_move: false,
|
||||||
|
discoverable: false,
|
||||||
|
actor_type: "Person"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
end
|
|
@ -82,7 +82,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
OpenApiSpex.Plug.CastAndValidate,
|
OpenApiSpex.Plug.CastAndValidate,
|
||||||
[render_error: Pleroma.Web.ApiSpec.RenderError] when action == :create
|
[render_error: Pleroma.Web.ApiSpec.RenderError]
|
||||||
|
when action in [:create, :verify_credentials, :update_credentials]
|
||||||
)
|
)
|
||||||
|
|
||||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
|
@ -152,9 +153,15 @@ def verify_credentials(%{assigns: %{user: user}} = conn, _) do
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc "PATCH /api/v1/accounts/update_credentials"
|
@doc "PATCH /api/v1/accounts/update_credentials"
|
||||||
def update_credentials(%{assigns: %{user: original_user}} = conn, params) do
|
def update_credentials(%{assigns: %{user: original_user}, body_params: params} = conn, _params) do
|
||||||
user = original_user
|
user = original_user
|
||||||
|
|
||||||
|
params =
|
||||||
|
params
|
||||||
|
|> Map.from_struct()
|
||||||
|
|> Enum.filter(fn {_, value} -> not is_nil(value) end)
|
||||||
|
|> Enum.into(%{})
|
||||||
|
|
||||||
user_params =
|
user_params =
|
||||||
[
|
[
|
||||||
:no_rich_text,
|
:no_rich_text,
|
||||||
|
@ -170,22 +177,22 @@ def update_credentials(%{assigns: %{user: original_user}} = conn, params) do
|
||||||
:discoverable
|
:discoverable
|
||||||
]
|
]
|
||||||
|> Enum.reduce(%{}, fn key, acc ->
|
|> Enum.reduce(%{}, fn key, acc ->
|
||||||
add_if_present(acc, params, to_string(key), key, &{:ok, truthy_param?(&1)})
|
add_if_present(acc, params, key, key, &{:ok, truthy_param?(&1)})
|
||||||
end)
|
end)
|
||||||
|> add_if_present(params, "display_name", :name)
|
|> add_if_present(params, :display_name, :name)
|
||||||
|> add_if_present(params, "note", :bio)
|
|> add_if_present(params, :note, :bio)
|
||||||
|> add_if_present(params, "avatar", :avatar)
|
|> add_if_present(params, :avatar, :avatar)
|
||||||
|> add_if_present(params, "header", :banner)
|
|> add_if_present(params, :header, :banner)
|
||||||
|> add_if_present(params, "pleroma_background_image", :background)
|
|> add_if_present(params, :pleroma_background_image, :background)
|
||||||
|> add_if_present(
|
|> add_if_present(
|
||||||
params,
|
params,
|
||||||
"fields_attributes",
|
:fields_attributes,
|
||||||
:raw_fields,
|
:raw_fields,
|
||||||
&{:ok, normalize_fields_attributes(&1)}
|
&{:ok, normalize_fields_attributes(&1)}
|
||||||
)
|
)
|
||||||
|> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store)
|
|> add_if_present(params, :pleroma_settings_store, :pleroma_settings_store)
|
||||||
|> add_if_present(params, "default_scope", :default_scope)
|
|> add_if_present(params, :default_scope, :default_scope)
|
||||||
|> add_if_present(params, "actor_type", :actor_type)
|
|> add_if_present(params, :actor_type, :actor_type)
|
||||||
|
|
||||||
changeset = User.update_changeset(user, user_params)
|
changeset = User.update_changeset(user, user_params)
|
||||||
|
|
||||||
|
@ -200,7 +207,7 @@ def update_credentials(%{assigns: %{user: original_user}} = conn, params) do
|
||||||
|
|
||||||
defp add_if_present(map, params, params_field, map_field, value_function \\ &{:ok, &1}) do
|
defp add_if_present(map, params, params_field, map_field, value_function \\ &{:ok, &1}) do
|
||||||
with true <- Map.has_key?(params, params_field),
|
with true <- Map.has_key?(params, params_field),
|
||||||
{:ok, new_value} <- value_function.(params[params_field]) do
|
{:ok, new_value} <- value_function.(Map.get(params, params_field)) do
|
||||||
Map.put(map, map_field, new_value)
|
Map.put(map, map_field, new_value)
|
||||||
else
|
else
|
||||||
_ -> map
|
_ -> map
|
||||||
|
@ -211,7 +218,13 @@ defp normalize_fields_attributes(fields) do
|
||||||
if Enum.all?(fields, &is_tuple/1) do
|
if Enum.all?(fields, &is_tuple/1) do
|
||||||
Enum.map(fields, fn {_, v} -> v end)
|
Enum.map(fields, fn {_, v} -> v end)
|
||||||
else
|
else
|
||||||
fields
|
Enum.map(fields, fn
|
||||||
|
%Pleroma.Web.ApiSpec.Schemas.AccountAttributeField{} = field ->
|
||||||
|
%{"name" => field.name, "value" => field.value}
|
||||||
|
|
||||||
|
field ->
|
||||||
|
field
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,11 @@ defp oauth_access(scopes, opts \\ []) do
|
||||||
%{user: user, token: token, conn: conn}
|
%{user: user, token: token, conn: conn}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp request_content_type(%{conn: conn}) do
|
||||||
|
conn = put_req_header(conn, "content-type", "multipart/form-data")
|
||||||
|
[conn: conn]
|
||||||
|
end
|
||||||
|
|
||||||
defp ensure_federating_or_authenticated(conn, url, user) do
|
defp ensure_federating_or_authenticated(conn, url, user) do
|
||||||
initial_setting = Config.get([:instance, :federating])
|
initial_setting = Config.get([:instance, :federating])
|
||||||
on_exit(fn -> Config.put([:instance, :federating], initial_setting) end)
|
on_exit(fn -> Config.put([:instance, :federating], initial_setting) end)
|
||||||
|
|
|
@ -9,6 +9,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperationTest do
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.Account
|
alias Pleroma.Web.ApiSpec.Schemas.Account
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.AccountCreateRequest
|
alias Pleroma.Web.ApiSpec.Schemas.AccountCreateRequest
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.AccountCreateResponse
|
alias Pleroma.Web.ApiSpec.Schemas.AccountCreateResponse
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.AccountUpdateCredentialsRequest
|
||||||
|
|
||||||
import OpenApiSpex.TestAssertions
|
import OpenApiSpex.TestAssertions
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
@ -31,6 +32,12 @@ test "AccountCreateResponse example matches schema" do
|
||||||
assert_schema(schema.example, "AccountCreateResponse", api_spec)
|
assert_schema(schema.example, "AccountCreateResponse", api_spec)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "AccountUpdateCredentialsRequest example matches schema" do
|
||||||
|
api_spec = ApiSpec.spec()
|
||||||
|
schema = AccountUpdateCredentialsRequest.schema()
|
||||||
|
assert_schema(schema.example, "AccountUpdateCredentialsRequest", api_spec)
|
||||||
|
end
|
||||||
|
|
||||||
test "AccountController produces a AccountCreateResponse", %{conn: conn} do
|
test "AccountController produces a AccountCreateResponse", %{conn: conn} do
|
||||||
api_spec = ApiSpec.spec()
|
api_spec = ApiSpec.spec()
|
||||||
app_token = insert(:oauth_token, user: nil)
|
app_token = insert(:oauth_token, user: nil)
|
||||||
|
@ -52,4 +59,29 @@ test "AccountController produces a AccountCreateResponse", %{conn: conn} do
|
||||||
|
|
||||||
assert_schema(json, "AccountCreateResponse", api_spec)
|
assert_schema(json, "AccountCreateResponse", api_spec)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "AccountUpdateCredentialsRequest produces an Account", %{conn: conn} do
|
||||||
|
api_spec = ApiSpec.spec()
|
||||||
|
token = insert(:oauth_token, scopes: ["read", "write"])
|
||||||
|
|
||||||
|
json =
|
||||||
|
conn
|
||||||
|
|> put_req_header("authorization", "Bearer " <> token.token)
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> patch(
|
||||||
|
"/api/v1/accounts/update_credentials",
|
||||||
|
%{
|
||||||
|
hide_followers_count: "true",
|
||||||
|
hide_follows_count: "true",
|
||||||
|
skip_thread_containment: "true",
|
||||||
|
hide_follows: "true",
|
||||||
|
pleroma_settings_store: %{"pleroma-fe" => %{"key" => "val"}},
|
||||||
|
note: "foobar",
|
||||||
|
fields_attributes: [%{name: "foo", value: "bar"}]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
assert_schema(json, "Account", api_spec)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,6 +14,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
|
||||||
|
|
||||||
describe "updating credentials" do
|
describe "updating credentials" do
|
||||||
setup do: oauth_access(["write:accounts"])
|
setup do: oauth_access(["write:accounts"])
|
||||||
|
setup :request_content_type
|
||||||
|
|
||||||
test "sets user settings in a generic way", %{conn: conn} do
|
test "sets user settings in a generic way", %{conn: conn} do
|
||||||
res_conn =
|
res_conn =
|
||||||
|
@ -237,6 +238,7 @@ test "requires 'write:accounts' permission" do
|
||||||
for token <- [token1, token2] do
|
for token <- [token1, token2] do
|
||||||
conn =
|
conn =
|
||||||
build_conn()
|
build_conn()
|
||||||
|
|> put_req_header("content-type", "multipart/form-data")
|
||||||
|> put_req_header("authorization", "Bearer #{token.token}")
|
|> put_req_header("authorization", "Bearer #{token.token}")
|
||||||
|> patch("/api/v1/accounts/update_credentials", %{})
|
|> patch("/api/v1/accounts/update_credentials", %{})
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue