aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorlain <lain@soykaf.club>2020-04-09 13:25:27 +0200
committerlain <lain@soykaf.club>2020-04-09 13:25:27 +0200
commitd35e114acddf339ed398aeab02bf94abe229ac36 (patch)
treee35bbf60afa823fd1fdf2b0366249a31f040cd29 /lib
parent8e637ae1a7b75fa08679ae9cf424650fc105de85 (diff)
parentb87b798ca1660224a3192c32b035c19b18e11587 (diff)
downloadpleroma-d35e114acddf339ed398aeab02bf94abe229ac36.tar.gz
Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into remake-remodel-dms
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/formatter.ex26
-rw-r--r--lib/pleroma/gun/conn.ex4
-rw-r--r--lib/pleroma/user.ex20
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/types/object_id.ex12
-rw-r--r--lib/pleroma/web/admin_api/admin_api_controller.ex17
-rw-r--r--lib/pleroma/web/api_spec.ex44
-rw-r--r--lib/pleroma/web/api_spec/helpers.ex27
-rw-r--r--lib/pleroma/web/api_spec/operations/app_operation.ex96
-rw-r--r--lib/pleroma/web/api_spec/schemas/app_create_request.ex33
-rw-r--r--lib/pleroma/web/api_spec/schemas/app_create_response.ex33
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/app_controller.ex9
-rw-r--r--lib/pleroma/web/oauth/scopes.ex7
-rw-r--r--lib/pleroma/web/router.ex11
13 files changed, 307 insertions, 32 deletions
diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex
index e2a658cb3..c44e7fc8b 100644
--- a/lib/pleroma/formatter.ex
+++ b/lib/pleroma/formatter.ex
@@ -35,9 +35,19 @@ defmodule Pleroma.Formatter do
nickname_text = get_nickname_text(nickname, opts)
link =
- ~s(<span class="h-card"><a data-user="#{id}" class="u-url mention" href="#{ap_id}" rel="ugc">@<span>#{
- nickname_text
- }</span></a></span>)
+ Phoenix.HTML.Tag.content_tag(
+ :span,
+ Phoenix.HTML.Tag.content_tag(
+ :a,
+ ["@", Phoenix.HTML.Tag.content_tag(:span, nickname_text)],
+ "data-user": id,
+ class: "u-url mention",
+ href: ap_id,
+ rel: "ugc"
+ ),
+ class: "h-card"
+ )
+ |> Phoenix.HTML.safe_to_string()
{link, %{acc | mentions: MapSet.put(acc.mentions, {"@" <> nickname, user})}}
@@ -49,7 +59,15 @@ defmodule Pleroma.Formatter do
def hashtag_handler("#" <> tag = tag_text, _buffer, _opts, acc) do
tag = String.downcase(tag)
url = "#{Pleroma.Web.base_url()}/tag/#{tag}"
- link = ~s(<a class="hashtag" data-tag="#{tag}" href="#{url}" rel="tag ugc">#{tag_text}</a>)
+
+ link =
+ Phoenix.HTML.Tag.content_tag(:a, tag_text,
+ class: "hashtag",
+ "data-tag": tag,
+ href: url,
+ rel: "tag ugc"
+ )
+ |> Phoenix.HTML.safe_to_string()
{link, %{acc | tags: MapSet.put(acc.tags, {tag_text, tag})}}
end
diff --git a/lib/pleroma/gun/conn.ex b/lib/pleroma/gun/conn.ex
index 20823a765..cd25a2e74 100644
--- a/lib/pleroma/gun/conn.ex
+++ b/lib/pleroma/gun/conn.ex
@@ -49,8 +49,10 @@ defmodule Pleroma.Gun.Conn do
key = "#{uri.scheme}:#{uri.host}:#{uri.port}"
+ max_connections = pool_opts[:max_connections] || 250
+
conn_pid =
- if Connections.count(name) < opts[:max_connection] do
+ if Connections.count(name) < max_connections do
do_open(uri, opts)
else
close_least_used_and_do_open(name, uri, opts)
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index ff828aa17..71c8c3a4e 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -16,6 +16,7 @@ defmodule Pleroma.User do
alias Pleroma.Conversation.Participation
alias Pleroma.Delivery
alias Pleroma.FollowingRelationship
+ alias Pleroma.Formatter
alias Pleroma.HTML
alias Pleroma.Keys
alias Pleroma.Notification
@@ -452,7 +453,7 @@ defmodule Pleroma.User do
fields =
raw_fields
- |> Enum.map(fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end)
+ |> Enum.map(fn f -> Map.update!(f, "value", &parse_fields(&1)) end)
changeset
|> put_change(:raw_fields, raw_fields)
@@ -462,6 +463,12 @@ defmodule Pleroma.User do
end
end
+ defp parse_fields(value) do
+ value
+ |> Formatter.linkify(mentions_format: :full)
+ |> elem(0)
+ end
+
defp put_change_if_present(changeset, map_field, value_function) do
if value = get_change(changeset, map_field) do
with {:ok, new_value} <- value_function.(value) do
@@ -1979,17 +1986,6 @@ defmodule Pleroma.User do
def fields(%{fields: fields}), do: fields
- def sanitized_fields(%User{} = user) do
- user
- |> User.fields()
- |> Enum.map(fn %{"name" => name, "value" => value} ->
- %{
- "name" => name,
- "value" => Pleroma.HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly)
- }
- end)
- end
-
def validate_fields(changeset, remote? \\ false) do
limit_name = if remote?, do: :max_remote_account_fields, else: :max_account_fields
limit = Pleroma.Config.get([:instance, limit_name], 0)
diff --git a/lib/pleroma/web/activity_pub/object_validators/types/object_id.ex b/lib/pleroma/web/activity_pub/object_validators/types/object_id.ex
index ee10be0b0..f6e749b33 100644
--- a/lib/pleroma/web/activity_pub/object_validators/types/object_id.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/types/object_id.ex
@@ -6,14 +6,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.ObjectID do
def cast(object) when is_binary(object) do
# Host has to be present and scheme has to be an http scheme (for now)
case URI.parse(object) do
- %URI{host: nil} ->
- :error
-
- %URI{scheme: scheme} when scheme in ["https", "http"] ->
- {:ok, object}
-
- _ ->
- :error
+ %URI{host: nil} -> :error
+ %URI{host: ""} -> :error
+ %URI{scheme: scheme} when scheme in ["https", "http"] -> {:ok, object}
+ _ -> :error
end
end
diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex
index ca5439920..fdbd24acb 100644
--- a/lib/pleroma/web/admin_api/admin_api_controller.ex
+++ b/lib/pleroma/web/admin_api/admin_api_controller.ex
@@ -576,9 +576,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
@doc "Sends registration invite via email"
def email_invite(%{assigns: %{user: user}} = conn, %{"email" => email} = params) do
- with true <-
- Config.get([:instance, :invites_enabled]) &&
- !Config.get([:instance, :registrations_open]),
+ with {_, false} <- {:registrations_open, Config.get([:instance, :registrations_open])},
+ {_, true} <- {:invites_enabled, Config.get([:instance, :invites_enabled])},
{:ok, invite_token} <- UserInviteToken.create_invite(),
email <-
Pleroma.Emails.UserEmail.user_invitation_email(
@@ -589,6 +588,18 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
),
{:ok, _} <- Pleroma.Emails.Mailer.deliver(email) do
json_response(conn, :no_content, "")
+ else
+ {:registrations_open, _} ->
+ errors(
+ conn,
+ {:error, "To send invites you need to set the `registrations_open` option to false."}
+ )
+
+ {:invites_enabled, _} ->
+ errors(
+ conn,
+ {:error, "To send invites you need to set the `invites_enabled` option to true."}
+ )
end
end
diff --git a/lib/pleroma/web/api_spec.ex b/lib/pleroma/web/api_spec.ex
new file mode 100644
index 000000000..41e48a085
--- /dev/null
+++ b/lib/pleroma/web/api_spec.ex
@@ -0,0 +1,44 @@
+# 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 do
+ alias OpenApiSpex.OpenApi
+ alias Pleroma.Web.Endpoint
+ alias Pleroma.Web.Router
+
+ @behaviour OpenApi
+
+ @impl OpenApi
+ def spec do
+ %OpenApi{
+ servers: [
+ # Populate the Server info from a phoenix endpoint
+ OpenApiSpex.Server.from_endpoint(Endpoint)
+ ],
+ info: %OpenApiSpex.Info{
+ title: "Pleroma",
+ description: Application.spec(:pleroma, :description) |> to_string(),
+ version: Application.spec(:pleroma, :vsn) |> to_string()
+ },
+ # populate the paths from a phoenix router
+ paths: OpenApiSpex.Paths.from_router(Router),
+ components: %OpenApiSpex.Components{
+ securitySchemes: %{
+ "oAuth" => %OpenApiSpex.SecurityScheme{
+ type: "oauth2",
+ flows: %OpenApiSpex.OAuthFlows{
+ password: %OpenApiSpex.OAuthFlow{
+ authorizationUrl: "/oauth/authorize",
+ tokenUrl: "/oauth/token",
+ scopes: %{"read" => "read"}
+ }
+ }
+ }
+ }
+ }
+ }
+ # discover request/response schemas from path specs
+ |> OpenApiSpex.resolve_schema_modules()
+ end
+end
diff --git a/lib/pleroma/web/api_spec/helpers.ex b/lib/pleroma/web/api_spec/helpers.ex
new file mode 100644
index 000000000..35cf4c0d8
--- /dev/null
+++ b/lib/pleroma/web/api_spec/helpers.ex
@@ -0,0 +1,27 @@
+# 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.Helpers do
+ def request_body(description, schema_ref, opts \\ []) do
+ media_types = ["application/json", "multipart/form-data"]
+
+ content =
+ media_types
+ |> Enum.map(fn type ->
+ {type,
+ %OpenApiSpex.MediaType{
+ schema: schema_ref,
+ example: opts[:example],
+ examples: opts[:examples]
+ }}
+ end)
+ |> Enum.into(%{})
+
+ %OpenApiSpex.RequestBody{
+ description: description,
+ content: content,
+ required: opts[:required] || false
+ }
+ end
+end
diff --git a/lib/pleroma/web/api_spec/operations/app_operation.ex b/lib/pleroma/web/api_spec/operations/app_operation.ex
new file mode 100644
index 000000000..26d8dbd42
--- /dev/null
+++ b/lib/pleroma/web/api_spec/operations/app_operation.ex
@@ -0,0 +1,96 @@
+# 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
+ alias Pleroma.Web.ApiSpec.Schemas.AppCreateRequest
+ alias Pleroma.Web.ApiSpec.Schemas.AppCreateResponse
+
+ @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", AppCreateRequest, required: true),
+ responses: %{
+ 200 => Operation.response("App", "application/json", AppCreateResponse),
+ 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
+end
diff --git a/lib/pleroma/web/api_spec/schemas/app_create_request.ex b/lib/pleroma/web/api_spec/schemas/app_create_request.ex
new file mode 100644
index 000000000..8a83abef3
--- /dev/null
+++ b/lib/pleroma/web/api_spec/schemas/app_create_request.ex
@@ -0,0 +1,33 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.Schemas.AppCreateRequest do
+ alias OpenApiSpex.Schema
+ require OpenApiSpex
+
+ OpenApiSpex.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. If none is provided, defaults to `read`."
+ },
+ website: %Schema{type: :string, 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
diff --git a/lib/pleroma/web/api_spec/schemas/app_create_response.ex b/lib/pleroma/web/api_spec/schemas/app_create_response.ex
new file mode 100644
index 000000000..f290fb031
--- /dev/null
+++ b/lib/pleroma/web/api_spec/schemas/app_create_response.ex
@@ -0,0 +1,33 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.Schemas.AppCreateResponse do
+ alias OpenApiSpex.Schema
+
+ require OpenApiSpex
+
+ OpenApiSpex.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
diff --git a/lib/pleroma/web/mastodon_api/controllers/app_controller.ex b/lib/pleroma/web/mastodon_api/controllers/app_controller.ex
index 5e2871f18..005c60444 100644
--- a/lib/pleroma/web/mastodon_api/controllers/app_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/app_controller.ex
@@ -14,17 +14,20 @@ defmodule Pleroma.Web.MastodonAPI.AppController do
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
plug(OAuthScopesPlug, %{scopes: ["read"]} when action == :verify_credentials)
+ plug(OpenApiSpex.Plug.CastAndValidate)
@local_mastodon_name "Mastodon-Local"
+ defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.AppOperation
+
@doc "POST /api/v1/apps"
- def create(conn, params) do
+ def create(%{body_params: params} = conn, _params) do
scopes = Scopes.fetch_scopes(params, ["read"])
app_attrs =
params
- |> Map.drop(["scope", "scopes"])
- |> Map.put("scopes", scopes)
+ |> Map.take([:client_name, :redirect_uris, :website])
+ |> Map.put(:scopes, scopes)
with cs <- App.register_changeset(%App{}, app_attrs),
false <- cs.changes[:client_name] == @local_mastodon_name,
diff --git a/lib/pleroma/web/oauth/scopes.ex b/lib/pleroma/web/oauth/scopes.ex
index 8ecf901f3..1023f16d4 100644
--- a/lib/pleroma/web/oauth/scopes.ex
+++ b/lib/pleroma/web/oauth/scopes.ex
@@ -15,7 +15,12 @@ defmodule Pleroma.Web.OAuth.Scopes do
Note: `scopes` is used by Mastodon — supporting it but sticking to
OAuth's standard `scope` wherever we control it
"""
- @spec fetch_scopes(map(), list()) :: list()
+ @spec fetch_scopes(map() | struct(), list()) :: list()
+
+ def fetch_scopes(%Pleroma.Web.ApiSpec.Schemas.AppCreateRequest{scopes: scopes}, default) do
+ parse_scopes(scopes, default)
+ end
+
def fetch_scopes(params, default) do
parse_scopes(params["scope"] || params["scopes"], default)
end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 5a0902739..3ecd59cd1 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -29,6 +29,7 @@ defmodule Pleroma.Web.Router do
plug(Pleroma.Plugs.SetUserSessionIdPlug)
plug(Pleroma.Plugs.EnsureUserKeyPlug)
plug(Pleroma.Plugs.IdempotencyPlug)
+ plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec)
end
pipeline :authenticated_api do
@@ -44,6 +45,7 @@ defmodule Pleroma.Web.Router do
plug(Pleroma.Plugs.SetUserSessionIdPlug)
plug(Pleroma.Plugs.EnsureAuthenticatedPlug)
plug(Pleroma.Plugs.IdempotencyPlug)
+ plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec)
end
pipeline :admin_api do
@@ -61,6 +63,7 @@ defmodule Pleroma.Web.Router do
plug(Pleroma.Plugs.EnsureAuthenticatedPlug)
plug(Pleroma.Plugs.UserIsAdminPlug)
plug(Pleroma.Plugs.IdempotencyPlug)
+ plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec)
end
pipeline :mastodon_html do
@@ -94,10 +97,12 @@ defmodule Pleroma.Web.Router do
pipeline :config do
plug(:accepts, ["json", "xml"])
+ plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec)
end
pipeline :pleroma_api do
plug(:accepts, ["html", "json"])
+ plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec)
end
pipeline :mailbox_preview do
@@ -500,6 +505,12 @@ defmodule Pleroma.Web.Router do
)
end
+ scope "/api" do
+ pipe_through(:api)
+
+ get("/openapi", OpenApiSpex.Plug.RenderSpec, [])
+ end
+
scope "/api", Pleroma.Web, as: :authenticated_twitter_api do
pipe_through(:authenticated_api)