Page MenuHomePhorge

No OneTemporary

Authored By
Unknown
Size
76 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex
index 70069d6f9..988bab882 100644
--- a/lib/pleroma/web/api_spec/operations/account_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/account_operation.ex
@@ -1,688 +1,726 @@
# 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.AccountOperation do
alias OpenApiSpex.Operation
alias OpenApiSpex.Reference
alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.Schemas.Account
alias Pleroma.Web.ApiSpec.Schemas.AccountRelationship
alias Pleroma.Web.ApiSpec.Schemas.ActorType
alias Pleroma.Web.ApiSpec.Schemas.ApiError
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
alias Pleroma.Web.ApiSpec.Schemas.List
alias Pleroma.Web.ApiSpec.Schemas.Status
alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
import Pleroma.Web.ApiSpec.Helpers
@spec open_api_operation(atom) :: Operation.t()
def open_api_operation(action) do
operation = String.to_existing_atom("#{action}_operation")
apply(__MODULE__, operation, [])
end
@spec create_operation() :: Operation.t()
def create_operation do
%Operation{
tags: ["accounts"],
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.",
operationId: "AccountController.create",
requestBody: request_body("Parameters", create_request(), required: true),
responses: %{
200 => Operation.response("Account", "application/json", create_response()),
400 => Operation.response("Error", "application/json", ApiError),
403 => Operation.response("Error", "application/json", ApiError),
429 => Operation.response("Error", "application/json", ApiError)
}
}
end
def verify_credentials_operation do
%Operation{
tags: ["accounts"],
description: "Test to make sure that the user token works.",
summary: "Verify account credentials",
operationId: "AccountController.verify_credentials",
security: [%{"oAuth" => ["read:accounts"]}],
responses: %{
200 => Operation.response("Account", "application/json", Account)
}
}
end
def update_credentials_operation do
%Operation{
tags: ["accounts"],
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),
responses: %{
200 => Operation.response("Account", "application/json", Account),
403 => Operation.response("Error", "application/json", ApiError)
}
}
end
def relationships_operation do
%Operation{
tags: ["accounts"],
summary: "Check relationships to other accounts",
operationId: "AccountController.relationships",
description: "Find out whether a given account is followed, blocked, muted, etc.",
security: [%{"oAuth" => ["read:follows"]}],
parameters: [
Operation.parameter(
:id,
:query,
%Schema{
oneOf: [%Schema{type: :array, items: %Schema{type: :string}}, %Schema{type: :string}]
},
"Account IDs",
example: "123"
)
],
responses: %{
200 => Operation.response("Account", "application/json", array_of_relationships())
}
}
end
def show_operation do
%Operation{
tags: ["accounts"],
summary: "Account",
operationId: "AccountController.show",
description: "View information about a profile.",
parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
responses: %{
200 => Operation.response("Account", "application/json", Account),
404 => Operation.response("Error", "application/json", ApiError)
}
}
end
def statuses_operation do
%Operation{
tags: ["accounts"],
summary: "Statuses",
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)",
parameters:
[
%Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
Operation.parameter(:pinned, :query, BooleanLike, "Include only pinned statuses"),
Operation.parameter(:tagged, :query, :string, "With tag"),
Operation.parameter(
:only_media,
:query,
BooleanLike,
"Include only statuses with media attached"
),
Operation.parameter(
:with_muted,
:query,
BooleanLike,
"Include statuses from muted acccounts."
),
Operation.parameter(:exclude_reblogs, :query, BooleanLike, "Exclude reblogs"),
Operation.parameter(:exclude_replies, :query, BooleanLike, "Exclude replies"),
Operation.parameter(
:exclude_visibilities,
:query,
%Schema{type: :array, items: VisibilityScope},
"Exclude visibilities"
)
] ++ pagination_params(),
responses: %{
200 => Operation.response("Statuses", "application/json", array_of_statuses()),
404 => Operation.response("Error", "application/json", ApiError)
}
}
end
def followers_operation do
%Operation{
tags: ["accounts"],
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(),
responses: %{
200 => Operation.response("Accounts", "application/json", array_of_accounts())
}
}
end
def following_operation do
%Operation{
tags: ["accounts"],
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(),
responses: %{200 => Operation.response("Accounts", "application/json", array_of_accounts())}
}
end
def lists_operation do
%Operation{
tags: ["accounts"],
summary: "Lists containing this account",
operationId: "AccountController.lists",
security: [%{"oAuth" => ["read:lists"]}],
description: "User lists that you have added this account to.",
parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
responses: %{200 => Operation.response("Lists", "application/json", array_of_lists())}
}
end
def follow_operation do
%Operation{
tags: ["accounts"],
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."
)
],
responses: %{
200 => Operation.response("Relationship", "application/json", AccountRelationship),
400 => Operation.response("Error", "application/json", ApiError),
404 => Operation.response("Error", "application/json", ApiError)
}
}
end
def unfollow_operation do
%Operation{
tags: ["accounts"],
summary: "Unfollow",
operationId: "AccountController.unfollow",
security: [%{"oAuth" => ["follow", "write:follows"]}],
description: "Unfollow the given account",
parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
responses: %{
200 => Operation.response("Relationship", "application/json", AccountRelationship),
400 => Operation.response("Error", "application/json", ApiError),
404 => Operation.response("Error", "application/json", ApiError)
}
}
end
def mute_operation do
%Operation{
tags: ["accounts"],
summary: "Mute",
operationId: "AccountController.mute",
security: [%{"oAuth" => ["follow", "write:mutes"]}],
requestBody: request_body("Parameters", mute_request()),
description:
"Mute the given account. Clients should filter statuses and notifications from this account, if received (e.g. due to a boost in the Home timeline).",
parameters: [
%Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
Operation.parameter(
:notifications,
:query,
%Schema{allOf: [BooleanLike], default: true},
"Mute notifications in addition to statuses? Defaults to `true`."
)
],
responses: %{
200 => Operation.response("Relationship", "application/json", AccountRelationship)
}
}
end
def unmute_operation do
%Operation{
tags: ["accounts"],
summary: "Unmute",
operationId: "AccountController.unmute",
security: [%{"oAuth" => ["follow", "write:mutes"]}],
description: "Unmute the given account.",
parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
responses: %{
200 => Operation.response("Relationship", "application/json", AccountRelationship)
}
}
end
def block_operation do
%Operation{
tags: ["accounts"],
summary: "Block",
operationId: "AccountController.block",
security: [%{"oAuth" => ["follow", "write:blocks"]}],
description:
"Block the given account. Clients should filter statuses from this account if received (e.g. due to a boost in the Home timeline)",
parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
responses: %{
200 => Operation.response("Relationship", "application/json", AccountRelationship)
}
}
end
def unblock_operation do
%Operation{
tags: ["accounts"],
summary: "Unblock",
operationId: "AccountController.unblock",
security: [%{"oAuth" => ["follow", "write:blocks"]}],
description: "Unblock the given account.",
parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
responses: %{
200 => Operation.response("Relationship", "application/json", AccountRelationship)
}
}
end
def follow_by_uri_operation do
%Operation{
tags: ["accounts"],
summary: "Follow by URI",
operationId: "AccountController.follows",
security: [%{"oAuth" => ["follow", "write:follows"]}],
requestBody: request_body("Parameters", follow_by_uri_request(), required: true),
responses: %{
200 => Operation.response("Account", "application/json", AccountRelationship),
400 => Operation.response("Error", "application/json", ApiError),
404 => Operation.response("Error", "application/json", ApiError)
}
}
end
def mutes_operation do
%Operation{
tags: ["accounts"],
summary: "Muted accounts",
operationId: "AccountController.mutes",
description: "Accounts the user has muted.",
security: [%{"oAuth" => ["follow", "read:mutes"]}],
responses: %{
200 => Operation.response("Accounts", "application/json", array_of_accounts())
}
}
end
def blocks_operation do
%Operation{
tags: ["accounts"],
summary: "Blocked users",
operationId: "AccountController.blocks",
description: "View your blocks. See also accounts/:id/{block,unblock}",
security: [%{"oAuth" => ["read:blocks"]}],
responses: %{
200 => Operation.response("Accounts", "application/json", array_of_accounts())
}
}
end
def endorsements_operation do
%Operation{
tags: ["accounts"],
summary: "Endorsements",
operationId: "AccountController.endorsements",
description: "Not implemented",
security: [%{"oAuth" => ["read:accounts"]}],
responses: %{
200 => empty_array_response()
}
}
end
def identity_proofs_operation do
%Operation{
tags: ["accounts"],
summary: "Identity proofs",
operationId: "AccountController.identity_proofs",
description: "Not implemented",
responses: %{
200 => empty_array_response()
}
}
end
defp create_request do
%Schema{
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
},
password: %Schema{
type: :string,
description: "The password to be used for login",
format: :password
},
agreement: %Schema{
type: :boolean,
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",
"password" => "secret",
"agreement" => "true",
"bio" => "☕️"
}
}
end
defp create_response do
%Schema{
title: "AccountCreateResponse",
description: "Response schema for an account",
type: :object,
properties: %{
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"}
},
example: %{
"access_token" => "i9hAVVzGld86Pl5JtLtizKoXVvtTlSCJvwaugCxvZzk",
"created_at" => 1_585_918_714,
"scope" => ["read", "write", "follow", "push"],
"token_type" => "Bearer"
}
}
end
defp update_creadentials_request do
%Schema{
title: "AccountUpdateCredentialsRequest",
description: "POST body for creating an account",
type: :object,
properties: %{
bot: %Schema{
type: :boolean,
+ 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,
+ nullable: true,
description: "Whether manual approval of follow requests is required."
},
fields_attributes: %Schema{
+ nullable: true,
oneOf: [
%Schema{type: :array, items: attribute_field()},
%Schema{type: :object, additionalProperties: %Schema{type: attribute_field()}}
]
},
# 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,
+ 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{
+ type: :boolean,
+ nullable: true,
+ description: "user's followers will be hidden"
+ },
+ hide_follows: %Schema{
+ type: :boolean,
+ nullable: true,
+ description: "user's follows will be hidden"
+ },
hide_followers_count: %Schema{
type: :boolean,
+ nullable: true,
description: "user's follower count will be hidden"
},
hide_follows_count: %Schema{
type: :boolean,
+ nullable: true,
description: "user's follow count will be hidden"
},
hide_favorites: %Schema{
type: :boolean,
+ nullable: true,
description: "user's favorites timeline will be hidden"
},
show_role: %Schema{
type: :boolean,
+ 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,
+ nullable: true,
description: "Skip filtering out broken threads"
},
allow_following_move: %Schema{
type: :boolean,
+ nullable: true,
description: "Allows automatically follow moved following accounts"
},
pleroma_background_image: %Schema{
type: :string,
+ nullable: true,
description: "Sets the background image of the user.",
format: :binary
},
discoverable: %Schema{
type: :boolean,
+ nullable: true,
description:
"Discovery of this account in search results and other services is allowed."
},
actor_type: ActorType
},
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
def array_of_accounts do
%Schema{
title: "ArrayOfAccounts",
type: :array,
items: Account,
example: [Account.schema().example]
}
end
defp array_of_relationships do
%Schema{
title: "ArrayOfRelationships",
description: "Response schema for account relationships",
type: :array,
items: AccountRelationship,
example: [
%{
"id" => "1",
"following" => true,
"showing_reblogs" => true,
"followed_by" => true,
"blocking" => false,
"blocked_by" => true,
"muting" => false,
"muting_notifications" => false,
"requested" => false,
"domain_blocking" => false,
"subscribing" => false,
"endorsed" => true
},
%{
"id" => "2",
"following" => true,
"showing_reblogs" => true,
"followed_by" => true,
"blocking" => false,
"blocked_by" => true,
"muting" => true,
"muting_notifications" => false,
"requested" => true,
"domain_blocking" => false,
"subscribing" => false,
"endorsed" => false
},
%{
"id" => "3",
"following" => true,
"showing_reblogs" => true,
"followed_by" => true,
"blocking" => true,
"blocked_by" => false,
"muting" => true,
"muting_notifications" => false,
"requested" => false,
"domain_blocking" => true,
"subscribing" => true,
"endorsed" => false
}
]
}
end
defp follow_by_uri_request do
%Schema{
title: "AccountFollowsRequest",
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]
}
end
defp mute_request do
%Schema{
title: "AccountMuteRequest",
description: "POST body for muting an account",
type: :object,
properties: %{
notifications: %Schema{
type: :boolean,
+ nullable: true,
description: "Mute notifications in addition to statuses? Defaults to true.",
default: true
}
},
example: %{
"notifications" => true
}
}
end
defp array_of_lists do
%Schema{
title: "ArrayOfLists",
description: "Response schema for lists",
type: :array,
items: List,
example: [
%{"id" => "123", "title" => "my list"},
%{"id" => "1337", "title" => "anotehr list"}
]
}
end
defp array_of_statuses do
%Schema{
title: "ArrayOfStatuses",
type: :array,
items: Status
}
end
defp attribute_field do
%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: %{
"name" => "Website",
"value" => "https://pleroma.com"
}
}
end
end
diff --git a/lib/pleroma/web/api_spec/operations/app_operation.ex b/lib/pleroma/web/api_spec/operations/app_operation.ex
index f6ccd073f..ae01cbbec 100644
--- a/lib/pleroma/web/api_spec/operations/app_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/app_operation.ex
@@ -1,144 +1,148 @@
# 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.AppOperation do
alias OpenApiSpex.Operation
alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.Helpers
@spec open_api_operation(atom) :: Operation.t()
def open_api_operation(action) do
operation = String.to_existing_atom("#{action}_operation")
apply(__MODULE__, operation, [])
end
@spec create_operation() :: Operation.t()
def create_operation do
%Operation{
tags: ["apps"],
summary: "Create an application",
description: "Create a new application to obtain OAuth2 credentials",
operationId: "AppController.create",
requestBody: Helpers.request_body("Parameters", create_request(), required: true),
responses: %{
200 => Operation.response("App", "application/json", create_response()),
422 =>
Operation.response(
"Unprocessable Entity",
"application/json",
%Schema{
type: :object,
description:
"If a required parameter is missing or improperly formatted, the request will fail.",
properties: %{
error: %Schema{type: :string}
},
example: %{
"error" => "Validation failed: Redirect URI must be an absolute URI."
}
}
)
}
}
end
def verify_credentials_operation do
%Operation{
tags: ["apps"],
summary: "Verify your app works",
description: "Confirm that the app's OAuth2 credentials work.",
operationId: "AppController.verify_credentials",
security: [%{"oAuth" => ["read"]}],
responses: %{
200 =>
Operation.response("App", "application/json", %Schema{
type: :object,
description:
"If the Authorization header was provided with a valid token, you should see your app returned as an Application entity.",
properties: %{
name: %Schema{type: :string},
vapid_key: %Schema{type: :string},
website: %Schema{type: :string, nullable: true}
},
example: %{
"name" => "My App",
"vapid_key" =>
"BCk-QqERU0q-CfYZjcuB6lnyyOYfJ2AifKqfeGIm7Z-HiTU5T9eTG5GxVA0_OH5mMlI4UkkDTpaZwozy0TzdZ2M=",
"website" => "https://myapp.com/"
}
}),
422 =>
Operation.response(
"Unauthorized",
"application/json",
%Schema{
type: :object,
description:
"If the Authorization header contains an invalid token, is malformed, or is not present, an error will be returned indicating an authorization failure.",
properties: %{
error: %Schema{type: :string}
},
example: %{
"error" => "The access token is invalid."
}
}
)
}
}
end
defp create_request do
%Schema{
title: "AppCreateRequest",
description: "POST body for creating an app",
type: :object,
properties: %{
client_name: %Schema{type: :string, description: "A name for your application."},
redirect_uris: %Schema{
type: :string,
description:
"Where the user should be redirected after authorization. To display the authorization code to the user instead of redirecting to a web page, use `urn:ietf:wg:oauth:2.0:oob` in this parameter."
},
scopes: %Schema{
type: :string,
description: "Space separated list of scopes",
default: "read"
},
- website: %Schema{type: :string, description: "A URL to the homepage of your app"}
+ website: %Schema{
+ type: :string,
+ nullable: true,
+ description: "A URL to the homepage of your app"
+ }
},
required: [:client_name, :redirect_uris],
example: %{
"client_name" => "My App",
"redirect_uris" => "https://myapp.com/auth/callback",
"website" => "https://myapp.com/"
}
}
end
defp create_response do
%Schema{
title: "AppCreateResponse",
description: "Response schema for an app",
type: :object,
properties: %{
id: %Schema{type: :string},
name: %Schema{type: :string},
client_id: %Schema{type: :string},
client_secret: %Schema{type: :string},
redirect_uri: %Schema{type: :string},
vapid_key: %Schema{type: :string},
website: %Schema{type: :string, nullable: true}
},
example: %{
"id" => "123",
"name" => "My App",
"client_id" => "TWhM-tNSuncnqN7DBJmoyeLnk6K3iJJ71KKXxgL1hPM",
"client_secret" => "ZEaFUFmF0umgBX1qKJDjaU99Q31lDkOU8NutzTOoliw",
"vapid_key" =>
"BCk-QqERU0q-CfYZjcuB6lnyyOYfJ2AifKqfeGIm7Z-HiTU5T9eTG5GxVA0_OH5mMlI4UkkDTpaZwozy0TzdZ2M=",
"website" => "https://myapp.com/"
}
}
end
end
diff --git a/lib/pleroma/web/api_spec/operations/filter_operation.ex b/lib/pleroma/web/api_spec/operations/filter_operation.ex
index 53e57b46b..7310c1c4d 100644
--- a/lib/pleroma/web/api_spec/operations/filter_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/filter_operation.ex
@@ -1,227 +1,229 @@
# 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.FilterOperation do
alias OpenApiSpex.Operation
alias OpenApiSpex.Schema
alias 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: ["apps"],
summary: "View all filters",
operationId: "FilterController.index",
security: [%{"oAuth" => ["read:filters"]}],
responses: %{
200 => Operation.response("Filters", "application/json", array_of_filters())
}
}
end
def create_operation do
%Operation{
tags: ["apps"],
summary: "Create a filter",
operationId: "FilterController.create",
requestBody: Helpers.request_body("Parameters", create_request(), required: true),
security: [%{"oAuth" => ["write:filters"]}],
responses: %{200 => Operation.response("Filter", "application/json", filter())}
}
end
def show_operation do
%Operation{
tags: ["apps"],
summary: "View all filters",
parameters: [id_param()],
operationId: "FilterController.show",
security: [%{"oAuth" => ["read:filters"]}],
responses: %{
200 => Operation.response("Filter", "application/json", filter())
}
}
end
def update_operation do
%Operation{
tags: ["apps"],
summary: "Update a filter",
parameters: [id_param()],
operationId: "FilterController.update",
requestBody: Helpers.request_body("Parameters", update_request(), required: true),
security: [%{"oAuth" => ["write:filters"]}],
responses: %{
200 => Operation.response("Filter", "application/json", filter())
}
}
end
def delete_operation do
%Operation{
tags: ["apps"],
summary: "Remove a filter",
parameters: [id_param()],
operationId: "FilterController.delete",
security: [%{"oAuth" => ["write:filters"]}],
responses: %{
200 =>
Operation.response("Filter", "application/json", %Schema{
type: :object,
description: "Empty object"
})
}
}
end
defp id_param do
Operation.parameter(:id, :path, :string, "Filter ID", example: "123", required: true)
end
defp filter do
%Schema{
title: "Filter",
type: :object,
properties: %{
id: %Schema{type: :string},
phrase: %Schema{type: :string, description: "The text to be filtered"},
context: %Schema{
type: :array,
items: %Schema{type: :string, enum: ["home", "notifications", "public", "thread"]},
description: "The contexts in which the filter should be applied."
},
expires_at: %Schema{
type: :string,
format: :"date-time",
description:
"When the filter should no longer be applied. String (ISO 8601 Datetime), or null if the filter does not expire.",
nullable: true
},
irreversible: %Schema{
type: :boolean,
description:
"Should matching entities in home and notifications be dropped by the server?"
},
whole_word: %Schema{
type: :boolean,
description: "Should the filter consider word boundaries?"
}
},
example: %{
"id" => "5580",
"phrase" => "@twitter.com",
"context" => [
"home",
"notifications",
"public",
"thread"
],
"whole_word" => false,
"expires_at" => nil,
"irreversible" => true
}
}
end
defp array_of_filters do
%Schema{
title: "ArrayOfFilters",
description: "Array of Filters",
type: :array,
items: filter(),
example: [
%{
"id" => "5580",
"phrase" => "@twitter.com",
"context" => [
"home",
"notifications",
"public",
"thread"
],
"whole_word" => false,
"expires_at" => nil,
"irreversible" => true
},
%{
"id" => "6191",
"phrase" => ":eurovision2019:",
"context" => [
"home"
],
"whole_word" => true,
"expires_at" => "2019-05-21T13:47:31.333Z",
"irreversible" => false
}
]
}
end
defp create_request do
%Schema{
title: "FilterCreateRequest",
allOf: [
update_request(),
%Schema{
type: :object,
properties: %{
irreversible: %Schema{
type: :bolean,
description:
"Should the server irreversibly drop matching entities from home and notifications?",
default: false
}
}
}
],
example: %{
"phrase" => "knights",
"context" => ["home"]
}
}
end
defp update_request do
%Schema{
title: "FilterUpdateRequest",
type: :object,
properties: %{
phrase: %Schema{type: :string, description: "The text to be filtered"},
context: %Schema{
type: :array,
items: %Schema{type: :string, enum: ["home", "notifications", "public", "thread"]},
description:
"Array of enumerable strings `home`, `notifications`, `public`, `thread`. At least one context must be specified."
},
irreversible: %Schema{
- type: :bolean,
+ type: :boolean,
+ nullable: true,
description:
"Should the server irreversibly drop matching entities from home and notifications?"
},
whole_word: %Schema{
- type: :bolean,
+ type: :boolean,
+ nullable: true,
description: "Consider word boundaries?",
default: true
}
# TODO: probably should implement filter expiration
# expires_in: %Schema{
# type: :string,
# format: :"date-time",
# description:
# "ISO 8601 Datetime for when the filter expires. Otherwise,
# null for a filter that doesn't expire."
# }
},
required: [:phrase, :context],
example: %{
"phrase" => "knights",
"context" => ["home"]
}
}
end
end
diff --git a/lib/pleroma/web/api_spec/operations/marker_operation.ex b/lib/pleroma/web/api_spec/operations/marker_operation.ex
index 06620492a..714ef1f99 100644
--- a/lib/pleroma/web/api_spec/operations/marker_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/marker_operation.ex
@@ -1,140 +1,142 @@
# 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.MarkerOperation do
alias OpenApiSpex.Operation
alias OpenApiSpex.Schema
alias 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: ["Markers"],
summary: "Get saved timeline position",
security: [%{"oAuth" => ["read:statuses"]}],
operationId: "MarkerController.index",
parameters: [
Operation.parameter(
:timeline,
:query,
%Schema{
type: :array,
items: %Schema{type: :string, enum: ["home", "notifications"]}
},
"Array of markers to fetch. If not provided, an empty object will be returned."
)
],
responses: %{
200 => Operation.response("Marker", "application/json", response()),
403 => Operation.response("Error", "application/json", api_error())
}
}
end
def upsert_operation do
%Operation{
tags: ["Markers"],
summary: "Save position in timeline",
operationId: "MarkerController.upsert",
requestBody: Helpers.request_body("Parameters", upsert_request(), required: true),
security: [%{"oAuth" => ["follow", "write:blocks"]}],
responses: %{
200 => Operation.response("Marker", "application/json", response()),
403 => Operation.response("Error", "application/json", api_error())
}
}
end
defp marker do
%Schema{
title: "Marker",
description: "Schema for a marker",
type: :object,
properties: %{
last_read_id: %Schema{type: :string},
version: %Schema{type: :integer},
updated_at: %Schema{type: :string},
pleroma: %Schema{
type: :object,
properties: %{
unread_count: %Schema{type: :integer}
}
}
},
example: %{
"last_read_id" => "35098814",
"version" => 361,
"updated_at" => "2019-11-26T22:37:25.239Z",
"pleroma" => %{"unread_count" => 5}
}
}
end
defp response do
%Schema{
title: "MarkersResponse",
description: "Response schema for markers",
type: :object,
properties: %{
notifications: %Schema{allOf: [marker()], nullable: true},
home: %Schema{allOf: [marker()], nullable: true}
},
items: %Schema{type: :string},
example: %{
"notifications" => %{
"last_read_id" => "35098814",
"version" => 361,
"updated_at" => "2019-11-26T22:37:25.239Z",
"pleroma" => %{"unread_count" => 0}
},
"home" => %{
"last_read_id" => "103206604258487607",
"version" => 468,
"updated_at" => "2019-11-26T22:37:25.235Z",
"pleroma" => %{"unread_count" => 10}
}
}
}
end
defp upsert_request do
%Schema{
title: "MarkersUpsertRequest",
description: "Request schema for marker upsert",
type: :object,
properties: %{
notifications: %Schema{
type: :object,
+ nullable: true,
properties: %{
- last_read_id: %Schema{type: :string}
+ last_read_id: %Schema{nullable: true, type: :string}
}
},
home: %Schema{
type: :object,
+ nullable: true,
properties: %{
- last_read_id: %Schema{type: :string}
+ last_read_id: %Schema{nullable: true, type: :string}
}
}
},
example: %{
"home" => %{
"last_read_id" => "103194548672408537",
"version" => 462,
"updated_at" => "2019-11-24T19:39:39.337Z"
}
}
}
end
defp api_error do
%Schema{
type: :object,
properties: %{error: %Schema{type: :string}}
}
end
end
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex
index 435991037..90922c064 100644
--- a/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex
@@ -1,185 +1,187 @@
# 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.PleromaAccountOperation do
alias OpenApiSpex.Operation
alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.Schemas.AccountRelationship
alias Pleroma.Web.ApiSpec.Schemas.ApiError
alias Pleroma.Web.ApiSpec.Schemas.FlakeID
alias Pleroma.Web.ApiSpec.StatusOperation
import Pleroma.Web.ApiSpec.Helpers
def open_api_operation(action) do
operation = String.to_existing_atom("#{action}_operation")
apply(__MODULE__, operation, [])
end
def confirmation_resend_operation do
%Operation{
tags: ["Accounts"],
summary: "Resend confirmation email. Expects `email` or `nickname`",
operationId: "PleromaAPI.AccountController.confirmation_resend",
parameters: [
Operation.parameter(:email, :query, :string, "Email of that needs to be verified",
example: "cofe@cofe.io"
),
Operation.parameter(
:nickname,
:query,
:string,
"Nickname of user that needs to be verified",
example: "cofefe"
)
],
responses: %{
204 => no_content_response()
}
}
end
def update_avatar_operation do
%Operation{
tags: ["Accounts"],
summary: "Set/clear user avatar image",
operationId: "PleromaAPI.AccountController.update_avatar",
requestBody:
request_body("Parameters", update_avatar_or_background_request(), required: true),
security: [%{"oAuth" => ["write:accounts"]}],
responses: %{
200 => update_response(),
403 => Operation.response("Forbidden", "application/json", ApiError)
}
}
end
def update_banner_operation do
%Operation{
tags: ["Accounts"],
summary: "Set/clear user banner image",
operationId: "PleromaAPI.AccountController.update_banner",
requestBody: request_body("Parameters", update_banner_request(), required: true),
security: [%{"oAuth" => ["write:accounts"]}],
responses: %{
200 => update_response()
}
}
end
def update_background_operation do
%Operation{
tags: ["Accounts"],
summary: "Set/clear user background image",
operationId: "PleromaAPI.AccountController.update_background",
security: [%{"oAuth" => ["write:accounts"]}],
requestBody:
request_body("Parameters", update_avatar_or_background_request(), required: true),
responses: %{
200 => update_response()
}
}
end
def favourites_operation do
%Operation{
tags: ["Accounts"],
summary: "Returns favorites timeline of any user",
operationId: "PleromaAPI.AccountController.favourites",
parameters: [id_param() | pagination_params()],
security: [%{"oAuth" => ["read:favourites"]}],
responses: %{
200 =>
Operation.response(
"Array of Statuses",
"application/json",
StatusOperation.array_of_statuses()
),
403 => Operation.response("Forbidden", "application/json", ApiError),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
def subscribe_operation do
%Operation{
tags: ["Accounts"],
summary: "Subscribe to receive notifications for all statuses posted by a user",
operationId: "PleromaAPI.AccountController.subscribe",
parameters: [id_param()],
security: [%{"oAuth" => ["follow", "write:follows"]}],
responses: %{
200 => Operation.response("Relationship", "application/json", AccountRelationship),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
def unsubscribe_operation do
%Operation{
tags: ["Accounts"],
summary: "Unsubscribe to stop receiving notifications from user statuses",
operationId: "PleromaAPI.AccountController.unsubscribe",
parameters: [id_param()],
security: [%{"oAuth" => ["follow", "write:follows"]}],
responses: %{
200 => Operation.response("Relationship", "application/json", AccountRelationship),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
defp id_param do
Operation.parameter(:id, :path, FlakeID, "Account ID",
example: "9umDrYheeY451cQnEe",
required: true
)
end
defp update_avatar_or_background_request do
%Schema{
title: "PleromaAccountUpdateAvatarOrBackgroundRequest",
type: :object,
properties: %{
img: %Schema{
+ nullable: true,
type: :string,
format: :binary,
description: "Image encoded using `multipart/form-data` or an empty string to clear"
}
}
}
end
defp update_banner_request do
%Schema{
title: "PleromaAccountUpdateBannerRequest",
type: :object,
properties: %{
banner: %Schema{
type: :string,
+ nullable: true,
format: :binary,
description: "Image encoded using `multipart/form-data` or an empty string to clear"
}
}
}
end
defp update_response do
Operation.response("PleromaAccountUpdateResponse", "application/json", %Schema{
type: :object,
properties: %{
url: %Schema{
type: :string,
format: :uri,
nullable: true,
description: "Image URL"
}
},
example: %{
"url" =>
"https://cofe.party/media/9d0add56-bcb6-4c0f-8225-cbbd0b6dd773/13eadb6972c9ccd3f4ffa3b8196f0e0d38b4d2f27594457c52e52946c054cd9a.gif"
}
})
end
end
diff --git a/lib/pleroma/web/api_spec/operations/report_operation.ex b/lib/pleroma/web/api_spec/operations/report_operation.ex
index da4d50703..882177c96 100644
--- a/lib/pleroma/web/api_spec/operations/report_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/report_operation.ex
@@ -1,78 +1,81 @@
# 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.ReportOperation do
alias OpenApiSpex.Operation
alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.Helpers
alias Pleroma.Web.ApiSpec.Schemas.ApiError
def open_api_operation(action) do
operation = String.to_existing_atom("#{action}_operation")
apply(__MODULE__, operation, [])
end
def create_operation do
%Operation{
tags: ["reports"],
summary: "File a report",
description: "Report problematic users to your moderators",
operationId: "ReportController.create",
security: [%{"oAuth" => ["follow", "write:reports"]}],
requestBody: Helpers.request_body("Parameters", create_request(), required: true),
responses: %{
200 => Operation.response("Report", "application/json", create_response()),
400 => Operation.response("Report", "application/json", ApiError)
}
}
end
defp create_request do
%Schema{
title: "ReportCreateRequest",
description: "POST body for creating a report",
type: :object,
properties: %{
account_id: %Schema{type: :string, description: "ID of the account to report"},
status_ids: %Schema{
type: :array,
+ nullable: true,
items: %Schema{type: :string},
description: "Array of Statuses to attach to the report, for context"
},
comment: %Schema{
type: :string,
+ nullable: true,
description: "Reason for the report"
},
forward: %Schema{
type: :boolean,
+ nullable: true,
default: false,
description:
"If the account is remote, should the report be forwarded to the remote admin?"
}
},
required: [:account_id],
example: %{
"account_id" => "123",
"status_ids" => ["1337"],
"comment" => "bad status!",
"forward" => "false"
}
}
end
defp create_response do
%Schema{
title: "ReportResponse",
type: :object,
properties: %{
id: %Schema{type: :string, description: "Report ID"},
action_taken: %Schema{type: :boolean, description: "Is action taken?"}
},
example: %{
"id" => "123",
"action_taken" => false
}
}
end
end
diff --git a/lib/pleroma/web/api_spec/operations/status_operation.ex b/lib/pleroma/web/api_spec/operations/status_operation.ex
index 561db3bce..fc2909d8c 100644
--- a/lib/pleroma/web/api_spec/operations/status_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/status_operation.ex
@@ -1,499 +1,521 @@
# 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.StatusOperation do
alias OpenApiSpex.Operation
alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.AccountOperation
alias Pleroma.Web.ApiSpec.Schemas.ApiError
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
alias Pleroma.Web.ApiSpec.Schemas.FlakeID
alias Pleroma.Web.ApiSpec.Schemas.ScheduledStatus
alias Pleroma.Web.ApiSpec.Schemas.Status
alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
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: ["Statuses"],
summary: "Get multiple statuses by IDs",
security: [%{"oAuth" => ["read:statuses"]}],
parameters: [
Operation.parameter(
:ids,
:query,
%Schema{type: :array, items: FlakeID},
"Array of status IDs"
)
],
operationId: "StatusController.index",
responses: %{
200 => Operation.response("Array of Status", "application/json", array_of_statuses())
}
}
end
def create_operation do
%Operation{
tags: ["Statuses"],
summary: "Publish new status",
security: [%{"oAuth" => ["write:statuses"]}],
description: "Post a new status",
operationId: "StatusController.create",
requestBody: request_body("Parameters", create_request(), required: true),
responses: %{
200 =>
Operation.response(
"Status. When `scheduled_at` is present, ScheduledStatus is returned instead",
"application/json",
%Schema{oneOf: [Status, ScheduledStatus]}
),
422 => Operation.response("Bad Request", "application/json", ApiError)
}
}
end
def show_operation do
%Operation{
tags: ["Statuses"],
summary: "View specific status",
description: "View information about a status",
operationId: "StatusController.show",
security: [%{"oAuth" => ["read:statuses"]}],
parameters: [id_param()],
responses: %{
200 => status_response(),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
def delete_operation do
%Operation{
tags: ["Statuses"],
summary: "Delete status",
security: [%{"oAuth" => ["write:statuses"]}],
description: "Delete one of your own statuses",
operationId: "StatusController.delete",
parameters: [id_param()],
responses: %{
200 => empty_object_response(),
403 => Operation.response("Forbidden", "application/json", ApiError),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
def reblog_operation do
%Operation{
tags: ["Statuses"],
summary: "Boost",
security: [%{"oAuth" => ["write:statuses"]}],
description: "Share a status",
operationId: "StatusController.reblog",
parameters: [id_param()],
requestBody:
request_body("Parameters", %Schema{
type: :object,
properties: %{
visibility: %Schema{allOf: [VisibilityScope], default: "public"}
}
}),
responses: %{
200 => status_response(),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
def unreblog_operation do
%Operation{
tags: ["Statuses"],
summary: "Undo boost",
security: [%{"oAuth" => ["write:statuses"]}],
description: "Undo a reshare of a status",
operationId: "StatusController.unreblog",
parameters: [id_param()],
responses: %{
200 => status_response(),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
def favourite_operation do
%Operation{
tags: ["Statuses"],
summary: "Favourite",
security: [%{"oAuth" => ["write:favourites"]}],
description: "Add a status to your favourites list",
operationId: "StatusController.favourite",
parameters: [id_param()],
responses: %{
200 => status_response(),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
def unfavourite_operation do
%Operation{
tags: ["Statuses"],
summary: "Undo favourite",
security: [%{"oAuth" => ["write:favourites"]}],
description: "Remove a status from your favourites list",
operationId: "StatusController.unfavourite",
parameters: [id_param()],
responses: %{
200 => status_response(),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
def pin_operation do
%Operation{
tags: ["Statuses"],
summary: "Pin to profile",
security: [%{"oAuth" => ["write:accounts"]}],
description: "Feature one of your own public statuses at the top of your profile",
operationId: "StatusController.pin",
parameters: [id_param()],
responses: %{
200 => status_response(),
400 => Operation.response("Error", "application/json", ApiError)
}
}
end
def unpin_operation do
%Operation{
tags: ["Statuses"],
summary: "Unpin to profile",
security: [%{"oAuth" => ["write:accounts"]}],
description: "Unfeature a status from the top of your profile",
operationId: "StatusController.unpin",
parameters: [id_param()],
responses: %{
200 => status_response(),
400 => Operation.response("Error", "application/json", ApiError)
}
}
end
def bookmark_operation do
%Operation{
tags: ["Statuses"],
summary: "Bookmark",
security: [%{"oAuth" => ["write:bookmarks"]}],
description: "Privately bookmark a status",
operationId: "StatusController.bookmark",
parameters: [id_param()],
responses: %{
200 => status_response()
}
}
end
def unbookmark_operation do
%Operation{
tags: ["Statuses"],
summary: "Undo bookmark",
security: [%{"oAuth" => ["write:bookmarks"]}],
description: "Remove a status from your private bookmarks",
operationId: "StatusController.unbookmark",
parameters: [id_param()],
responses: %{
200 => status_response()
}
}
end
def mute_conversation_operation do
%Operation{
tags: ["Statuses"],
summary: "Mute conversation",
security: [%{"oAuth" => ["write:mutes"]}],
description: "Do not receive notifications for the thread that this status is part of.",
operationId: "StatusController.mute_conversation",
parameters: [id_param()],
responses: %{
200 => status_response(),
400 => Operation.response("Error", "application/json", ApiError)
}
}
end
def unmute_conversation_operation do
%Operation{
tags: ["Statuses"],
summary: "Unmute conversation",
security: [%{"oAuth" => ["write:mutes"]}],
description:
"Start receiving notifications again for the thread that this status is part of",
operationId: "StatusController.unmute_conversation",
parameters: [id_param()],
responses: %{
200 => status_response(),
400 => Operation.response("Error", "application/json", ApiError)
}
}
end
def card_operation do
%Operation{
tags: ["Statuses"],
deprecated: true,
summary: "Preview card",
description: "Deprecated in favor of card property inlined on Status entity",
operationId: "StatusController.card",
parameters: [id_param()],
security: [%{"oAuth" => ["read:statuses"]}],
responses: %{
200 =>
Operation.response("Card", "application/json", %Schema{
type: :object,
nullable: true,
properties: %{
type: %Schema{type: :string, enum: ["link", "photo", "video", "rich"]},
provider_name: %Schema{type: :string, nullable: true},
provider_url: %Schema{type: :string, format: :uri},
url: %Schema{type: :string, format: :uri},
image: %Schema{type: :string, nullable: true, format: :uri},
title: %Schema{type: :string},
description: %Schema{type: :string}
}
})
}
}
end
def favourited_by_operation do
%Operation{
tags: ["Statuses"],
summary: "Favourited by",
description: "View who favourited a given status",
operationId: "StatusController.favourited_by",
security: [%{"oAuth" => ["read:accounts"]}],
parameters: [id_param()],
responses: %{
200 =>
Operation.response(
"Array of Accounts",
"application/json",
AccountOperation.array_of_accounts()
),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
def reblogged_by_operation do
%Operation{
tags: ["Statuses"],
summary: "Boosted by",
description: "View who boosted a given status",
operationId: "StatusController.reblogged_by",
security: [%{"oAuth" => ["read:accounts"]}],
parameters: [id_param()],
responses: %{
200 =>
Operation.response(
"Array of Accounts",
"application/json",
AccountOperation.array_of_accounts()
),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
def context_operation do
%Operation{
tags: ["Statuses"],
summary: "Parent and child statuses",
description: "View statuses above and below this status in the thread",
operationId: "StatusController.context",
security: [%{"oAuth" => ["read:statuses"]}],
parameters: [id_param()],
responses: %{
200 => Operation.response("Context", "application/json", context())
}
}
end
def favourites_operation do
%Operation{
tags: ["Statuses"],
summary: "Favourited statuses",
description: "Statuses the user has favourited",
operationId: "StatusController.favourites",
parameters: pagination_params(),
security: [%{"oAuth" => ["read:favourites"]}],
responses: %{
200 => Operation.response("Array of Statuses", "application/json", array_of_statuses())
}
}
end
def bookmarks_operation do
%Operation{
tags: ["Statuses"],
summary: "Bookmarked statuses",
description: "Statuses the user has bookmarked",
operationId: "StatusController.bookmarks",
parameters: [
Operation.parameter(:with_relationships, :query, BooleanLike, "Include relationships")
| pagination_params()
],
security: [%{"oAuth" => ["read:bookmarks"]}],
responses: %{
200 => Operation.response("Array of Statuses", "application/json", array_of_statuses())
}
}
end
def array_of_statuses do
%Schema{type: :array, items: Status, example: [Status.schema().example]}
end
defp create_request do
%Schema{
title: "StatusCreateRequest",
type: :object,
properties: %{
status: %Schema{
type: :string,
+ nullable: true,
description:
"Text content of the status. If `media_ids` is provided, this becomes optional. Attaching a `poll` is optional while `status` is provided."
},
media_ids: %Schema{
+ nullable: true,
type: :array,
items: %Schema{type: :string},
description: "Array of Attachment ids to be attached as media."
},
poll: %Schema{
+ nullable: true,
type: :object,
required: [:options],
properties: %{
options: %Schema{
type: :array,
items: %Schema{type: :string},
description: "Array of possible answers. Must be provided with `poll[expires_in]`."
},
expires_in: %Schema{
type: :integer,
+ nullable: true,
description:
"Duration the poll should be open, in seconds. Must be provided with `poll[options]`"
},
- multiple: %Schema{type: :boolean, description: "Allow multiple choices?"},
+ multiple: %Schema{
+ type: :boolean,
+ nullable: true,
+ description: "Allow multiple choices?"
+ },
hide_totals: %Schema{
type: :boolean,
+ nullable: true,
description: "Hide vote counts until the poll ends?"
}
}
},
in_reply_to_id: %Schema{
+ nullable: true,
allOf: [FlakeID],
description: "ID of the status being replied to, if status is a reply"
},
sensitive: %Schema{
type: :boolean,
+ nullable: true,
description: "Mark status and attached media as sensitive?"
},
spoiler_text: %Schema{
type: :string,
+ nullable: true,
description:
"Text to be shown as a warning or subject before the actual content. Statuses are generally collapsed behind this field."
},
scheduled_at: %Schema{
type: :string,
format: :"date-time",
nullable: true,
description:
"ISO 8601 Datetime at which to schedule a status. Providing this paramter will cause ScheduledStatus to be returned instead of Status. Must be at least 5 minutes in the future."
},
- language: %Schema{type: :string, description: "ISO 639 language code for this status."},
+ language: %Schema{
+ type: :string,
+ nullable: true,
+ description: "ISO 639 language code for this status."
+ },
# Pleroma-specific properties:
preview: %Schema{
type: :boolean,
+ nullable: true,
description:
"If set to `true` the post won't be actually posted, but the status entitiy would still be rendered back. This could be useful for previewing rich text/custom emoji, for example"
},
content_type: %Schema{
type: :string,
+ nullable: true,
description:
"The MIME type of the status, it is transformed into HTML by the backend. You can get the list of the supported MIME types with the nodeinfo endpoint."
},
to: %Schema{
type: :array,
+ nullable: true,
items: %Schema{type: :string},
description:
"A list of nicknames (like `lain@soykaf.club` or `lain` on the local server) that will be used to determine who is going to be addressed by this post. Using this will disable the implicit addressing by mentioned names in the `status` body, only the people in the `to` list will be addressed. The normal rules for for post visibility are not affected by this and will still apply"
},
visibility: %Schema{
+ nullable: true,
anyOf: [
VisibilityScope,
%Schema{type: :string, description: "`list:LIST_ID`", example: "LIST:123"}
],
description:
"Visibility of the posted status. Besides standard MastoAPI values (`direct`, `private`, `unlisted` or `public`) it can be used to address a List by setting it to `list:LIST_ID`"
},
expires_in: %Schema{
+ nullable: true,
type: :integer,
description:
"The number of seconds the posted activity should expire in. When a posted activity expires it will be deleted from the server, and a delete request for it will be federated. This needs to be longer than an hour."
},
in_reply_to_conversation_id: %Schema{
+ nullable: true,
type: :string,
description:
"Will reply to a given conversation, addressing only the people who are part of the recipient set of that conversation. Sets the visibility to `direct`."
}
},
example: %{
"status" => "What time is it?",
"sensitive" => "false",
"poll" => %{
"options" => ["Cofe", "Adventure"],
"expires_in" => 420
}
}
}
end
defp id_param do
Operation.parameter(:id, :path, FlakeID, "Status ID",
example: "9umDrYheeY451cQnEe",
required: true
)
end
defp status_response do
Operation.response("Status", "application/json", Status)
end
defp context do
%Schema{
title: "StatusContext",
description:
"Represents the tree around a given status. Used for reconstructing threads of statuses.",
type: :object,
required: [:ancestors, :descendants],
properties: %{
ancestors: array_of_statuses(),
descendants: array_of_statuses()
},
example: %{
"ancestors" => [Status.schema().example],
"descendants" => [Status.schema().example]
}
}
end
end
diff --git a/lib/pleroma/web/api_spec/operations/subscription_operation.ex b/lib/pleroma/web/api_spec/operations/subscription_operation.ex
index 663b8fa11..cf6dcb068 100644
--- a/lib/pleroma/web/api_spec/operations/subscription_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/subscription_operation.ex
@@ -1,188 +1,226 @@
# 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.SubscriptionOperation do
alias OpenApiSpex.Operation
alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.Helpers
alias Pleroma.Web.ApiSpec.Schemas.ApiError
alias Pleroma.Web.ApiSpec.Schemas.PushSubscription
def open_api_operation(action) do
operation = String.to_existing_atom("#{action}_operation")
apply(__MODULE__, operation, [])
end
def create_operation do
%Operation{
tags: ["Push Subscriptions"],
summary: "Subscribe to push notifications",
description:
"Add a Web Push API subscription to receive notifications. Each access token can have one push subscription. If you create a new subscription, the old subscription is deleted.",
operationId: "SubscriptionController.create",
security: [%{"oAuth" => ["push"]}],
requestBody: Helpers.request_body("Parameters", create_request(), required: true),
responses: %{
200 => Operation.response("Push Subscription", "application/json", PushSubscription),
400 => Operation.response("Error", "application/json", ApiError),
403 => Operation.response("Error", "application/json", ApiError)
}
}
end
def show_operation do
%Operation{
tags: ["Push Subscriptions"],
summary: "Get current subscription",
description: "View the PushSubscription currently associated with this access token.",
operationId: "SubscriptionController.show",
security: [%{"oAuth" => ["push"]}],
responses: %{
200 => Operation.response("Push Subscription", "application/json", PushSubscription),
403 => Operation.response("Error", "application/json", ApiError),
404 => Operation.response("Error", "application/json", ApiError)
}
}
end
def update_operation do
%Operation{
tags: ["Push Subscriptions"],
summary: "Change types of notifications",
description:
"Updates the current push subscription. Only the data part can be updated. To change fundamentals, a new subscription must be created instead.",
operationId: "SubscriptionController.update",
security: [%{"oAuth" => ["push"]}],
requestBody: Helpers.request_body("Parameters", update_request(), required: true),
responses: %{
200 => Operation.response("Push Subscription", "application/json", PushSubscription),
403 => Operation.response("Error", "application/json", ApiError)
}
}
end
def delete_operation do
%Operation{
tags: ["Push Subscriptions"],
summary: "Remove current subscription",
description: "Removes the current Web Push API subscription.",
operationId: "SubscriptionController.delete",
security: [%{"oAuth" => ["push"]}],
responses: %{
200 => Operation.response("Empty object", "application/json", %Schema{type: :object}),
403 => Operation.response("Error", "application/json", ApiError),
404 => Operation.response("Error", "application/json", ApiError)
}
}
end
defp create_request do
%Schema{
title: "SubscriptionCreateRequest",
description: "POST body for creating a push subscription",
type: :object,
properties: %{
subscription: %Schema{
type: :object,
properties: %{
endpoint: %Schema{
type: :string,
description: "Endpoint URL that is called when a notification event occurs."
},
keys: %Schema{
type: :object,
properties: %{
p256dh: %Schema{
type: :string,
description:
"User agent public key. Base64 encoded string of public key of ECDH key using `prime256v1` curve."
},
auth: %Schema{
type: :string,
description: "Auth secret. Base64 encoded string of 16 bytes of random data."
}
},
required: [:p256dh, :auth]
}
},
required: [:endpoint, :keys]
},
data: %Schema{
+ nullable: true,
type: :object,
properties: %{
alerts: %Schema{
+ nullable: true,
type: :object,
properties: %{
- follow: %Schema{type: :boolean, description: "Receive follow notifications?"},
+ follow: %Schema{
+ type: :boolean,
+ nullable: true,
+ description: "Receive follow notifications?"
+ },
favourite: %Schema{
type: :boolean,
+ nullable: true,
description: "Receive favourite notifications?"
},
- reblog: %Schema{type: :boolean, description: "Receive reblog notifications?"},
- mention: %Schema{type: :boolean, description: "Receive mention notifications?"},
- poll: %Schema{type: :boolean, description: "Receive poll notifications?"}
+ reblog: %Schema{
+ type: :boolean,
+ nullable: true,
+ description: "Receive reblog notifications?"
+ },
+ mention: %Schema{
+ type: :boolean,
+ nullable: true,
+ description: "Receive mention notifications?"
+ },
+ poll: %Schema{
+ type: :boolean,
+ nullable: true,
+ description: "Receive poll notifications?"
+ }
}
}
}
}
},
required: [:subscription],
example: %{
"subscription" => %{
"endpoint" => "https://example.com/example/1234",
"keys" => %{
"auth" => "8eDyX_uCN0XRhSbY5hs7Hg==",
"p256dh" =>
"BCIWgsnyXDv1VkhqL2P7YRBvdeuDnlwAPT2guNhdIoW3IP7GmHh1SMKPLxRf7x8vJy6ZFK3ol2ohgn_-0yP7QQA="
}
},
"data" => %{
"alerts" => %{
"follow" => true,
"mention" => true,
"poll" => false
}
}
}
}
end
defp update_request do
%Schema{
title: "SubscriptionUpdateRequest",
type: :object,
properties: %{
data: %Schema{
+ nullable: true,
type: :object,
properties: %{
alerts: %Schema{
+ nullable: true,
type: :object,
properties: %{
- follow: %Schema{type: :boolean, description: "Receive follow notifications?"},
+ follow: %Schema{
+ type: :boolean,
+ nullable: true,
+ description: "Receive follow notifications?"
+ },
favourite: %Schema{
type: :boolean,
+ nullable: true,
description: "Receive favourite notifications?"
},
- reblog: %Schema{type: :boolean, description: "Receive reblog notifications?"},
- mention: %Schema{type: :boolean, description: "Receive mention notifications?"},
- poll: %Schema{type: :boolean, description: "Receive poll notifications?"}
+ reblog: %Schema{
+ type: :boolean,
+ nullable: true,
+ description: "Receive reblog notifications?"
+ },
+ mention: %Schema{
+ type: :boolean,
+ nullable: true,
+ description: "Receive mention notifications?"
+ },
+ poll: %Schema{
+ type: :boolean,
+ nullable: true,
+ description: "Receive poll notifications?"
+ }
}
}
}
}
},
example: %{
"data" => %{
"alerts" => %{
"follow" => true,
"favourite" => true,
"reblog" => true,
"mention" => true,
"poll" => true
}
}
}
}
end
end

File Metadata

Mime Type
text/x-diff
Expires
Mon, Nov 2, 1:08 AM (12 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1803477
Default Alt Text
(76 KB)

Event Timeline