diff options
author | lain <lain@soykaf.club> | 2020-05-15 13:33:04 +0200 |
---|---|---|
committer | lain <lain@soykaf.club> | 2020-05-15 13:33:04 +0200 |
commit | f012c3a202ef43d1a8a1dc88f08057b7a41d3d78 (patch) | |
tree | a3847182efa357bce56c12d6253492dc0cc2b894 /lib | |
parent | 1d18721a3c60aa0acc7d1ba858a92277e544a54a (diff) | |
parent | 081d1d3f48f2264ee329f7ff7af7c2f88fe0a654 (diff) | |
download | pleroma-f012c3a202ef43d1a8a1dc88f08057b7a41d3d78.tar.gz |
Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into remake-remodel-dms
Diffstat (limited to 'lib')
18 files changed, 386 insertions, 44 deletions
diff --git a/lib/pleroma/bbs/authenticator.ex b/lib/pleroma/bbs/authenticator.ex index d4494b003..815de7002 100644 --- a/lib/pleroma/bbs/authenticator.ex +++ b/lib/pleroma/bbs/authenticator.ex @@ -4,6 +4,7 @@ defmodule Pleroma.BBS.Authenticator do use Sshd.PasswordAuthenticator + alias Pleroma.Plugs.AuthenticationPlug alias Pleroma.User def authenticate(username, password) do @@ -11,7 +12,7 @@ defmodule Pleroma.BBS.Authenticator do password = to_string(password) with %User{} = user <- User.get_by_nickname(username) do - Pbkdf2.verify_pass(password, user.password_hash) + AuthenticationPlug.checkpw(password, user.password_hash) else _e -> false end diff --git a/lib/pleroma/constants.ex b/lib/pleroma/constants.ex index 3a9eec5ea..06174f624 100644 --- a/lib/pleroma/constants.ex +++ b/lib/pleroma/constants.ex @@ -17,7 +17,8 @@ defmodule Pleroma.Constants do "announcement_count", "emoji", "context_id", - "deleted_activity_id" + "deleted_activity_id", + "pleroma_internal" ] ) diff --git a/lib/pleroma/docs/json.ex b/lib/pleroma/docs/json.ex index 74f8b2615..d1cf1f487 100644 --- a/lib/pleroma/docs/json.ex +++ b/lib/pleroma/docs/json.ex @@ -18,7 +18,6 @@ defmodule Pleroma.Docs.JSON do with config <- Pleroma.Config.Loader.read("config/description.exs") do config[:pleroma][:config_description] |> Pleroma.Docs.Generator.convert_to_strings() - |> Jason.encode!() end end end diff --git a/lib/pleroma/plugs/authentication_plug.ex b/lib/pleroma/plugs/authentication_plug.ex index ae4a235bd..2cdf6c951 100644 --- a/lib/pleroma/plugs/authentication_plug.ex +++ b/lib/pleroma/plugs/authentication_plug.ex @@ -16,6 +16,11 @@ defmodule Pleroma.Plugs.AuthenticationPlug do :crypt.crypt(password, password_hash) == password_hash end + def checkpw(password, "$2" <> _ = password_hash) do + # Handle bcrypt passwords for Mastodon migration + Bcrypt.verify_pass(password, password_hash) + end + def checkpw(password, "$pbkdf2" <> _ = password_hash) do Pbkdf2.verify_pass(password, password_hash) end @@ -36,7 +41,7 @@ defmodule Pleroma.Plugs.AuthenticationPlug do } = conn, _ ) do - if Pbkdf2.verify_pass(password, password_hash) do + if checkpw(password, password_hash) do conn |> assign(:user, auth_user) |> OAuthScopesPlug.skip_plug() diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index 762d813d9..1be1a3a5b 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -134,7 +134,7 @@ defmodule Pleroma.Upload do end end - defp prepare_upload(%{"img" => "data:image/" <> image_data}, opts) do + defp prepare_upload(%{img: "data:image/" <> image_data}, opts) do parsed = Regex.named_captures(~r/(?<filetype>jpeg|png|gif);base64,(?<data>.*)/, image_data) data = Base.decode64!(parsed["data"], ignore: :whitespace) hash = String.downcase(Base.encode16(:crypto.hash(:sha256, data))) diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex index 9821173d0..451dc92d6 100644 --- a/lib/pleroma/web/admin_api/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/admin_api_controller.ex @@ -37,7 +37,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do require Logger - @descriptions_json Pleroma.Docs.JSON.compile() + @descriptions Pleroma.Docs.JSON.compile() @users_page_size 50 plug( @@ -897,9 +897,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do end def config_descriptions(conn, _params) do - conn - |> Plug.Conn.put_resp_content_type("application/json") - |> Plug.Conn.send_resp(200, @descriptions_json) + descriptions = Enum.filter(@descriptions, &whitelisted_config?/1) + + json(conn, descriptions) end def config_show(conn, %{"only_db" => true}) do @@ -954,7 +954,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do def config_update(conn, %{"configs" => configs}) do with :ok <- configurable_from_database(conn) do {_errors, results} = - Enum.map(configs, fn + configs + |> Enum.filter(&whitelisted_config?/1) + |> Enum.map(fn %{"group" => group, "key" => key, "delete" => true} = params -> ConfigDB.delete(%{group: group, key: key, subkeys: params["subkeys"]}) @@ -1016,6 +1018,28 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do end end + defp whitelisted_config?(group, key) do + if whitelisted_configs = Config.get(:database_config_whitelist) do + Enum.any?(whitelisted_configs, fn + {whitelisted_group} -> + group == inspect(whitelisted_group) + + {whitelisted_group, whitelisted_key} -> + group == inspect(whitelisted_group) && key == inspect(whitelisted_key) + end) + else + true + end + end + + defp whitelisted_config?(%{"group" => group, "key" => key}) do + whitelisted_config?(group, key) + end + + defp whitelisted_config?(%{:group => group} = config) do + whitelisted_config?(group, config[:key]) + end + def reload_emoji(conn, _params) do Pleroma.Emoji.reload() diff --git a/lib/pleroma/web/api_spec/helpers.ex b/lib/pleroma/web/api_spec/helpers.ex index 183df43ee..f0b558aa5 100644 --- a/lib/pleroma/web/api_spec/helpers.ex +++ b/lib/pleroma/web/api_spec/helpers.ex @@ -54,4 +54,8 @@ defmodule Pleroma.Web.ApiSpec.Helpers do def empty_array_response do Operation.response("Empty array", "application/json", %Schema{type: :array, example: []}) end + + def no_content_response do + Operation.response("No Content", "application/json", %Schema{type: :string, example: ""}) + end end 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 @@ -367,15 +367,18 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do 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 @@ -392,23 +395,33 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do }, 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", @@ -447,28 +460,34 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do 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()}} @@ -488,47 +507,65 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do # 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." }, @@ -624,7 +661,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do 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] } @@ -638,6 +675,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do properties: %{ notifications: %Schema{ type: :boolean, + nullable: true, description: "Mute notifications in addition to statuses? Defaults to true.", default: true } 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 @@ -105,7 +105,11 @@ defmodule Pleroma.Web.ApiSpec.AppOperation do 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: %{ 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 @@ -199,12 +199,14 @@ defmodule Pleroma.Web.ApiSpec.FilterOperation do "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 } 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 @@ -110,14 +110,16 @@ defmodule Pleroma.Web.ApiSpec.MarkerOperation do 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} } } }, diff --git a/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex new file mode 100644 index 000000000..90922c064 --- /dev/null +++ b/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex @@ -0,0 +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 @@ -37,15 +37,18 @@ defmodule Pleroma.Web.ApiSpec.ReportOperation do 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?" diff --git a/lib/pleroma/web/api_spec/operations/status_operation.ex b/lib/pleroma/web/api_spec/operations/status_operation.ex index a6bb87560..fc2909d8c 100644 --- a/lib/pleroma/web/api_spec/operations/status_operation.ex +++ b/lib/pleroma/web/api_spec/operations/status_operation.ex @@ -360,7 +360,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do } end - defp array_of_statuses do + def array_of_statuses do %Schema{type: :array, items: Status, example: [Status.schema().example]} end @@ -371,15 +371,18 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do 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: %{ @@ -390,26 +393,35 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do }, 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." }, @@ -420,25 +432,33 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do 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"} @@ -447,11 +467,13 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do "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`." 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 @@ -109,19 +109,38 @@ defmodule Pleroma.Web.ApiSpec.SubscriptionOperation do 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?" + } } } } @@ -154,19 +173,38 @@ defmodule Pleroma.Web.ApiSpec.SubscriptionOperation do 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?" + } } } } diff --git a/lib/pleroma/web/auth/totp_authenticator.ex b/lib/pleroma/web/auth/totp_authenticator.ex index 04e489c83..ce8a76219 100644 --- a/lib/pleroma/web/auth/totp_authenticator.ex +++ b/lib/pleroma/web/auth/totp_authenticator.ex @@ -5,6 +5,7 @@ defmodule Pleroma.Web.Auth.TOTPAuthenticator do alias Pleroma.MFA alias Pleroma.MFA.TOTP + alias Pleroma.Plugs.AuthenticationPlug alias Pleroma.User @doc "Verify code or check backup code." @@ -30,7 +31,7 @@ defmodule Pleroma.Web.Auth.TOTPAuthenticator do code ) when is_list(codes) and is_binary(code) do - hash_code = Enum.find(codes, fn hash -> Pbkdf2.verify_pass(code, hash) end) + hash_code = Enum.find(codes, fn hash -> AuthenticationPlug.checkpw(code, hash) end) if hash_code do MFA.invalidate_backup_code(user, hash_code) diff --git a/lib/pleroma/web/mongooseim/mongoose_im_controller.ex b/lib/pleroma/web/mongooseim/mongoose_im_controller.ex index 0814b3bc3..6cbbe8fd8 100644 --- a/lib/pleroma/web/mongooseim/mongoose_im_controller.ex +++ b/lib/pleroma/web/mongooseim/mongoose_im_controller.ex @@ -5,6 +5,7 @@ defmodule Pleroma.Web.MongooseIM.MongooseIMController do use Pleroma.Web, :controller + alias Pleroma.Plugs.AuthenticationPlug alias Pleroma.Plugs.RateLimiter alias Pleroma.Repo alias Pleroma.User @@ -27,7 +28,7 @@ defmodule Pleroma.Web.MongooseIM.MongooseIMController do def check_password(conn, %{"user" => username, "pass" => password}) do with %User{password_hash: password_hash, deactivated: false} <- Repo.get_by(User, nickname: username, local: true), - true <- Pbkdf2.verify_pass(password, password_hash) do + true <- AuthenticationPlug.checkpw(password, password_hash) do conn |> json(true) else diff --git a/lib/pleroma/web/pleroma_api/controllers/account_controller.ex b/lib/pleroma/web/pleroma_api/controllers/account_controller.ex index be7477867..07078d415 100644 --- a/lib/pleroma/web/pleroma_api/controllers/account_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/account_controller.ex @@ -19,6 +19,13 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do require Pleroma.Constants plug( + OpenApiSpex.Plug.PutApiSpec, + [module: Pleroma.Web.ApiSpec] when action == :confirmation_resend + ) + + plug(Pleroma.Web.ApiSpec.CastAndValidate) + + plug( :skip_plug, [OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug] when action == :confirmation_resend ) @@ -49,9 +56,11 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do plug(:assign_account_by_id when action in [:favourites, :subscribe, :unsubscribe]) plug(:put_view, Pleroma.Web.MastodonAPI.AccountView) + defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaAccountOperation + @doc "POST /api/v1/pleroma/accounts/confirmation_resend" def confirmation_resend(conn, params) do - nickname_or_email = params["email"] || params["nickname"] + nickname_or_email = params[:email] || params[:nickname] with %User{} = user <- User.get_by_nickname_or_email(nickname_or_email), {:ok, _} <- User.try_send_confirmation_email(user) do @@ -60,7 +69,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do end @doc "PATCH /api/v1/pleroma/accounts/update_avatar" - def update_avatar(%{assigns: %{user: user}} = conn, %{"img" => ""}) do + def update_avatar(%{assigns: %{user: user}, body_params: %{img: ""}} = conn, _) do {:ok, _user} = user |> Changeset.change(%{avatar: nil}) @@ -69,7 +78,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do json(conn, %{url: nil}) end - def update_avatar(%{assigns: %{user: user}} = conn, params) do + def update_avatar(%{assigns: %{user: user}, body_params: params} = conn, _params) do {:ok, %{data: data}} = ActivityPub.upload(params, type: :avatar) {:ok, _user} = user |> Changeset.change(%{avatar: data}) |> User.update_and_set_cache() %{"url" => [%{"href" => href} | _]} = data @@ -78,14 +87,14 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do end @doc "PATCH /api/v1/pleroma/accounts/update_banner" - def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) do + def update_banner(%{assigns: %{user: user}, body_params: %{banner: ""}} = conn, _) do with {:ok, _user} <- User.update_banner(user, %{}) do json(conn, %{url: nil}) end end - def update_banner(%{assigns: %{user: user}} = conn, params) do - with {:ok, object} <- ActivityPub.upload(%{"img" => params["banner"]}, type: :banner), + def update_banner(%{assigns: %{user: user}, body_params: params} = conn, _) do + with {:ok, object} <- ActivityPub.upload(%{img: params[:banner]}, type: :banner), {:ok, _user} <- User.update_banner(user, object.data) do %{"url" => [%{"href" => href} | _]} = object.data @@ -94,13 +103,13 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do end @doc "PATCH /api/v1/pleroma/accounts/update_background" - def update_background(%{assigns: %{user: user}} = conn, %{"img" => ""}) do + def update_background(%{assigns: %{user: user}, body_params: %{img: ""}} = conn, _) do with {:ok, _user} <- User.update_background(user, %{}) do json(conn, %{url: nil}) end end - def update_background(%{assigns: %{user: user}} = conn, params) do + def update_background(%{assigns: %{user: user}, body_params: params} = conn, _) do with {:ok, object} <- ActivityPub.upload(params, type: :background), {:ok, _user} <- User.update_background(user, object.data) do %{"url" => [%{"href" => href} | _]} = object.data @@ -117,6 +126,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do def favourites(%{assigns: %{user: for_user, account: user}} = conn, params) do params = params + |> Map.new(fn {key, value} -> {to_string(key), value} end) |> Map.put("type", "Create") |> Map.put("favorited_by", user.ap_id) |> Map.put("blocking_user", for_user) |