# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ApiSpec.AccountOperation do
@spec create_operation() :: Operation.t()
def create_operation do
%Operation{
- tags: ["accounts"],
+ tags: ["Account credentials"],
summary: "Register an account",
description:
"Creates a user and account records. Returns an account access token for the app that initiated the request. The app should save this token for later, and should wait for the user to confirm their account by clicking a link in their email inbox.",
def verify_credentials_operation do
%Operation{
- tags: ["accounts"],
+ tags: ["Account credentials"],
description: "Test to make sure that the user token works.",
summary: "Verify account credentials",
operationId: "AccountController.verify_credentials",
def update_credentials_operation do
%Operation{
- tags: ["accounts"],
+ tags: ["Account credentials"],
summary: "Update account credentials",
description: "Update the user's display and preferences.",
operationId: "AccountController.update_credentials",
security: [%{"oAuth" => ["write:accounts"]}],
- requestBody: request_body("Parameters", update_creadentials_request(), required: true),
+ requestBody: request_body("Parameters", update_credentials_request(), required: true),
responses: %{
200 => Operation.response("Account", "application/json", Account),
403 => Operation.response("Error", "application/json", ApiError)
def relationships_operation do
%Operation{
- tags: ["accounts"],
- summary: "Check relationships to other accounts",
+ tags: ["Retrieve account information"],
+ summary: "Relationship with current account",
operationId: "AccountController.relationships",
description: "Find out whether a given account is followed, blocked, muted, etc.",
security: [%{"oAuth" => ["read:follows"]}],
def show_operation do
%Operation{
- tags: ["accounts"],
+ tags: ["Retrieve account information"],
summary: "Account",
operationId: "AccountController.show",
description: "View information about a profile.",
- parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
+ parameters: [
+ %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
+ with_relationships_param()
+ ],
responses: %{
200 => Operation.response("Account", "application/json", Account),
+ 401 => Operation.response("Error", "application/json", ApiError),
404 => Operation.response("Error", "application/json", ApiError)
}
}
def statuses_operation do
%Operation{
- tags: ["accounts"],
summary: "Statuses",
+ tags: ["Retrieve account information"],
operationId: "AccountController.statuses",
description:
"Statuses posted to the given account. Public (for public statuses only), or user token + `read:statuses` (for private statuses the user is authorized to see)",
:with_muted,
:query,
BooleanLike,
- "Include statuses from muted acccounts."
+ "Include statuses from muted accounts."
),
Operation.parameter(:exclude_reblogs, :query, BooleanLike, "Exclude reblogs"),
Operation.parameter(:exclude_replies, :query, BooleanLike, "Exclude replies"),
:query,
%Schema{type: :array, items: VisibilityScope},
"Exclude visibilities"
+ ),
+ Operation.parameter(
+ :with_muted,
+ :query,
+ BooleanLike,
+ "Include reactions from muted accounts."
)
] ++ pagination_params(),
responses: %{
200 => Operation.response("Statuses", "application/json", array_of_statuses()),
+ 401 => Operation.response("Error", "application/json", ApiError),
404 => Operation.response("Error", "application/json", ApiError)
}
}
def followers_operation do
%Operation{
- tags: ["accounts"],
+ tags: ["Retrieve account information"],
summary: "Followers",
operationId: "AccountController.followers",
security: [%{"oAuth" => ["read:accounts"]}],
description:
"Accounts which follow the given account, if network is not hidden by the account owner.",
- parameters:
- [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}] ++ pagination_params(),
+ parameters: [
+ %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
+ Operation.parameter(:id, :query, :string, "ID of the resource owner"),
+ with_relationships_param() | pagination_params()
+ ],
responses: %{
200 => Operation.response("Accounts", "application/json", array_of_accounts())
}
def following_operation do
%Operation{
- tags: ["accounts"],
+ tags: ["Retrieve account information"],
summary: "Following",
operationId: "AccountController.following",
security: [%{"oAuth" => ["read:accounts"]}],
description:
"Accounts which the given account is following, if network is not hidden by the account owner.",
- parameters:
- [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}] ++ pagination_params(),
+ parameters: [
+ %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
+ Operation.parameter(:id, :query, :string, "ID of the resource owner"),
+ with_relationships_param() | pagination_params()
+ ],
responses: %{200 => Operation.response("Accounts", "application/json", array_of_accounts())}
}
end
def lists_operation do
%Operation{
- tags: ["accounts"],
+ tags: ["Retrieve account information"],
summary: "Lists containing this account",
operationId: "AccountController.lists",
security: [%{"oAuth" => ["read:lists"]}],
def follow_operation do
%Operation{
- tags: ["accounts"],
+ tags: ["Account actions"],
summary: "Follow",
operationId: "AccountController.follow",
security: [%{"oAuth" => ["follow", "write:follows"]}],
description: "Follow the given account",
parameters: [
- %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
- Operation.parameter(
- :reblogs,
- :query,
- BooleanLike,
- "Receive this account's reblogs in home timeline? Defaults to true."
- )
+ %Reference{"$ref": "#/components/parameters/accountIdOrNickname"}
],
+ requestBody:
+ request_body(
+ "Parameters",
+ %Schema{
+ type: :object,
+ properties: %{
+ reblogs: %Schema{
+ type: :boolean,
+ description: "Receive this account's reblogs in home timeline? Defaults to true.",
+ default: true
+ }
+ }
+ },
+ required: false
+ ),
responses: %{
200 => Operation.response("Relationship", "application/json", AccountRelationship),
400 => Operation.response("Error", "application/json", ApiError),
def unfollow_operation do
%Operation{
- tags: ["accounts"],
+ tags: ["Account actions"],
summary: "Unfollow",
operationId: "AccountController.unfollow",
security: [%{"oAuth" => ["follow", "write:follows"]}],
def mute_operation do
%Operation{
- tags: ["accounts"],
+ tags: ["Account actions"],
summary: "Mute",
operationId: "AccountController.mute",
security: [%{"oAuth" => ["follow", "write:mutes"]}],
:query,
%Schema{allOf: [BooleanLike], default: true},
"Mute notifications in addition to statuses? Defaults to `true`."
+ ),
+ Operation.parameter(
+ :expires_in,
+ :query,
+ %Schema{type: :integer, default: 0},
+ "Expire the mute in `expires_in` seconds. Default 0 for infinity"
)
],
responses: %{
def unmute_operation do
%Operation{
- tags: ["accounts"],
+ tags: ["Account actions"],
summary: "Unmute",
operationId: "AccountController.unmute",
security: [%{"oAuth" => ["follow", "write:mutes"]}],
def block_operation do
%Operation{
- tags: ["accounts"],
+ tags: ["Account actions"],
summary: "Block",
operationId: "AccountController.block",
security: [%{"oAuth" => ["follow", "write:blocks"]}],
def unblock_operation do
%Operation{
- tags: ["accounts"],
+ tags: ["Account actions"],
summary: "Unblock",
operationId: "AccountController.unblock",
security: [%{"oAuth" => ["follow", "write:blocks"]}],
def follow_by_uri_operation do
%Operation{
- tags: ["accounts"],
+ tags: ["Account actions"],
summary: "Follow by URI",
operationId: "AccountController.follows",
security: [%{"oAuth" => ["follow", "write:follows"]}],
def mutes_operation do
%Operation{
- tags: ["accounts"],
- summary: "Muted accounts",
+ tags: ["Blocks and mutes"],
+ summary: "Retrieve list of mutes",
operationId: "AccountController.mutes",
description: "Accounts the user has muted.",
security: [%{"oAuth" => ["follow", "read:mutes"]}],
+ parameters: [with_relationships_param() | pagination_params()],
responses: %{
200 => Operation.response("Accounts", "application/json", array_of_accounts())
}
def blocks_operation do
%Operation{
- tags: ["accounts"],
- summary: "Blocked users",
+ tags: ["Blocks and mutes"],
+ summary: "Retrieve list of blocks",
operationId: "AccountController.blocks",
description: "View your blocks. See also accounts/:id/{block,unblock}",
security: [%{"oAuth" => ["read:blocks"]}],
+ parameters: pagination_params(),
responses: %{
200 => Operation.response("Accounts", "application/json", array_of_accounts())
}
def endorsements_operation do
%Operation{
- tags: ["accounts"],
+ tags: ["Retrieve account information"],
summary: "Endorsements",
operationId: "AccountController.endorsements",
description: "Not implemented",
def identity_proofs_operation do
%Operation{
- tags: ["accounts"],
+ tags: ["Retrieve account information"],
summary: "Identity proofs",
operationId: "AccountController.identity_proofs",
+ # Validators complains about unused path params otherwise
+ parameters: [
+ %Reference{"$ref": "#/components/parameters/accountIdOrNickname"}
+ ],
description: "Not implemented",
responses: %{
200 => empty_array_response()
title: "AccountCreateRequest",
description: "POST body for creating an account",
type: :object,
+ required: [:username, :password, :agreement],
properties: %{
reason: %Schema{
type: :string,
+ nullable: true,
description:
"Text that will be reviewed by moderators if registrations require manual approval"
},
username: %Schema{type: :string, description: "The desired username for the account"},
email: %Schema{
type: :string,
+ nullable: true,
description:
"The email address to be used for login. Required when `account_activation_required` is enabled.",
format: :email
format: :password
},
agreement: %Schema{
- type: :boolean,
+ allOf: [BooleanLike],
description:
"Whether the user agrees to the local rules, terms, and policies. These should be presented to the user in order to allow them to consent before setting this parameter to TRUE."
},
locale: %Schema{
type: :string,
+ nullable: true,
description: "The language of the confirmation email that will be sent"
},
# Pleroma-specific properties:
- fullname: %Schema{type: :string, description: "Full name"},
- bio: %Schema{type: :string, description: "Bio", default: ""},
+ fullname: %Schema{type: :string, nullable: true, description: "Full name"},
+ bio: %Schema{type: :string, description: "Bio", nullable: true, default: ""},
captcha_solution: %Schema{
type: :string,
+ nullable: true,
description: "Provider-specific captcha solution"
},
- captcha_token: %Schema{type: :string, description: "Provider-specific captcha token"},
- captcha_answer_data: %Schema{type: :string, description: "Provider-specific captcha data"},
+ captcha_token: %Schema{
+ type: :string,
+ nullable: true,
+ description: "Provider-specific captcha token"
+ },
+ captcha_answer_data: %Schema{
+ type: :string,
+ nullable: true,
+ description: "Provider-specific captcha data"
+ },
token: %Schema{
type: :string,
+ nullable: true,
description: "Invite token required when the registrations aren't public"
}
},
- required: [:username, :password, :agreement],
example: %{
"username" => "cofe",
"email" => "cofe@example.com",
}
end
+ # Note: this is a token response (if login succeeds!), but there's no oauth operation file yet.
defp create_response do
%Schema{
title: "AccountCreateResponse",
description: "Response schema for an account",
type: :object,
properties: %{
+ # The response when auto-login on create succeeds (token is issued):
token_type: %Schema{type: :string},
access_token: %Schema{type: :string},
- scope: %Schema{type: :array, items: %Schema{type: :string}},
- created_at: %Schema{type: :integer, format: :"date-time"}
+ refresh_token: %Schema{type: :string},
+ scope: %Schema{type: :string},
+ created_at: %Schema{type: :integer, format: :"date-time"},
+ me: %Schema{type: :string},
+ expires_in: %Schema{type: :integer},
+ #
+ # The response when registration succeeds but auto-login fails (no token):
+ identifier: %Schema{type: :string},
+ message: %Schema{type: :string}
},
+ # Note: example of successful registration with failed login response:
+ # example: %{
+ # "identifier" => "missing_confirmed_email",
+ # "message" => "You have been registered. Please check your email for further instructions."
+ # },
example: %{
+ "token_type" => "Bearer",
"access_token" => "i9hAVVzGld86Pl5JtLtizKoXVvtTlSCJvwaugCxvZzk",
+ "refresh_token" => "i9hAVVzGld86Pl5JtLtizKoXVvtTlSCJvwaugCxvZzz",
"created_at" => 1_585_918_714,
- "scope" => ["read", "write", "follow", "push"],
- "token_type" => "Bearer"
+ "expires_in" => 600,
+ "scope" => "read write follow push",
+ "me" => "https://gensokyo.2hu/users/raymoo"
}
}
end
- defp update_creadentials_request do
+ defp update_credentials_request do
%Schema{
title: "AccountUpdateCredentialsRequest",
description: "POST body for creating an account",
type: :object,
properties: %{
bot: %Schema{
- type: :boolean,
+ allOf: [BooleanLike],
+ nullable: true,
description: "Whether the account has a bot flag."
},
display_name: %Schema{
type: :string,
+ nullable: true,
description: "The display name to use for the profile."
},
note: %Schema{type: :string, description: "The account bio."},
avatar: %Schema{
type: :string,
+ nullable: true,
description: "Avatar image encoded using multipart/form-data",
format: :binary
},
header: %Schema{
type: :string,
+ nullable: true,
description: "Header image encoded using multipart/form-data",
format: :binary
},
locked: %Schema{
- type: :boolean,
+ allOf: [BooleanLike],
+ nullable: true,
description: "Whether manual approval of follow requests is required."
},
+ accepts_chat_messages: %Schema{
+ allOf: [BooleanLike],
+ nullable: true,
+ description: "Whether the user accepts receiving chat messages."
+ },
fields_attributes: %Schema{
+ nullable: true,
oneOf: [
%Schema{type: :array, items: attribute_field()},
- %Schema{type: :object, additionalProperties: %Schema{type: attribute_field()}}
+ %Schema{type: :object, additionalProperties: attribute_field()}
]
},
# NOTE: `source` field is not supported
# Pleroma-specific fields
no_rich_text: %Schema{
- type: :boolean,
+ allOf: [BooleanLike],
+ nullable: true,
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: %Schema{
+ allOf: [BooleanLike],
+ nullable: true,
+ description: "user's followers will be hidden"
+ },
+ hide_follows: %Schema{
+ allOf: [BooleanLike],
+ nullable: true,
+ description: "user's follows will be hidden"
+ },
hide_followers_count: %Schema{
- type: :boolean,
+ allOf: [BooleanLike],
+ nullable: true,
description: "user's follower count will be hidden"
},
hide_follows_count: %Schema{
- type: :boolean,
+ allOf: [BooleanLike],
+ nullable: true,
description: "user's follow count will be hidden"
},
hide_favorites: %Schema{
- type: :boolean,
+ allOf: [BooleanLike],
+ nullable: true,
description: "user's favorites timeline will be hidden"
},
show_role: %Schema{
- type: :boolean,
+ allOf: [BooleanLike],
+ nullable: true,
description: "user's role (e.g admin, moderator) will be exposed to anyone in the
API"
},
default_scope: VisibilityScope,
pleroma_settings_store: %Schema{
type: :object,
+ nullable: true,
description: "Opaque user settings to be saved on the backend."
},
skip_thread_containment: %Schema{
- type: :boolean,
+ allOf: [BooleanLike],
+ nullable: true,
description: "Skip filtering out broken threads"
},
allow_following_move: %Schema{
- type: :boolean,
+ allOf: [BooleanLike],
+ nullable: true,
description: "Allows automatically follow moved following accounts"
},
+ also_known_as: %Schema{
+ type: :array,
+ items: %Schema{type: :string},
+ nullable: true,
+ description: "List of alternate ActivityPub IDs"
+ },
pleroma_background_image: %Schema{
type: :string,
+ nullable: true,
description: "Sets the background image of the user.",
format: :binary
},
discoverable: %Schema{
- type: :boolean,
+ allOf: [BooleanLike],
+ nullable: true,
description:
- "Discovery of this account in search results and other services is allowed."
+ "Discovery (listing, indexing) of this account by external services (search bots etc.) is allowed."
},
actor_type: ActorType
},
pleroma_settings_store: %{"pleroma-fe" => %{"key" => "val"}},
skip_thread_containment: false,
allow_following_move: false,
+ also_known_as: ["https://foo.bar/users/foo"],
discoverable: false,
actor_type: "Person"
}
description: "POST body for muting an account",
type: :object,
properties: %{
- uri: %Schema{type: :string, format: :uri}
+ uri: %Schema{type: :string, nullable: true, format: :uri}
},
required: [:uri]
}
type: :object,
properties: %{
notifications: %Schema{
- type: :boolean,
+ allOf: [BooleanLike],
+ nullable: true,
description: "Mute notifications in addition to statuses? Defaults to true.",
default: true
+ },
+ expires_in: %Schema{
+ type: :integer,
+ nullable: true,
+ description: "Expire the mute in `expires_in` seconds. Default 0 for infinity",
+ default: 0
}
},
example: %{
- "notifications" => true
+ "notifications" => true,
+ "expires_in" => 86_400
}
}
end