forked from AkkomaGang/akkoma
Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into remake-remodel-dms
This commit is contained in:
commit
d35e114acd
26 changed files with 482 additions and 106 deletions
|
@ -392,6 +392,19 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
- `email`
|
- `email`
|
||||||
- `name`, optional
|
- `name`, optional
|
||||||
|
|
||||||
|
- Response:
|
||||||
|
- On success: `204`, empty response
|
||||||
|
- On failure:
|
||||||
|
- 400 Bad Request, JSON:
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"error": "Appropriate error message here"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
## `GET /api/pleroma/admin/users/:nickname/password_reset`
|
## `GET /api/pleroma/admin/users/:nickname/password_reset`
|
||||||
|
|
||||||
### Get a password reset token for a given nickname
|
### Get a password reset token for a given nickname
|
||||||
|
|
|
@ -35,9 +35,19 @@ def mention_handler("@" <> nickname, buffer, opts, acc) do
|
||||||
nickname_text = get_nickname_text(nickname, opts)
|
nickname_text = get_nickname_text(nickname, opts)
|
||||||
|
|
||||||
link =
|
link =
|
||||||
~s(<span class="h-card"><a data-user="#{id}" class="u-url mention" href="#{ap_id}" rel="ugc">@<span>#{
|
Phoenix.HTML.Tag.content_tag(
|
||||||
nickname_text
|
:span,
|
||||||
}</span></a></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})}}
|
{link, %{acc | mentions: MapSet.put(acc.mentions, {"@" <> nickname, user})}}
|
||||||
|
|
||||||
|
@ -49,7 +59,15 @@ def mention_handler("@" <> nickname, buffer, opts, acc) do
|
||||||
def hashtag_handler("#" <> tag = tag_text, _buffer, _opts, acc) do
|
def hashtag_handler("#" <> tag = tag_text, _buffer, _opts, acc) do
|
||||||
tag = String.downcase(tag)
|
tag = String.downcase(tag)
|
||||||
url = "#{Pleroma.Web.base_url()}/tag/#{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})}}
|
{link, %{acc | tags: MapSet.put(acc.tags, {tag_text, tag})}}
|
||||||
end
|
end
|
||||||
|
|
|
@ -49,8 +49,10 @@ def open(%URI{} = uri, name, opts) do
|
||||||
|
|
||||||
key = "#{uri.scheme}:#{uri.host}:#{uri.port}"
|
key = "#{uri.scheme}:#{uri.host}:#{uri.port}"
|
||||||
|
|
||||||
|
max_connections = pool_opts[:max_connections] || 250
|
||||||
|
|
||||||
conn_pid =
|
conn_pid =
|
||||||
if Connections.count(name) < opts[:max_connection] do
|
if Connections.count(name) < max_connections do
|
||||||
do_open(uri, opts)
|
do_open(uri, opts)
|
||||||
else
|
else
|
||||||
close_least_used_and_do_open(name, uri, opts)
|
close_least_used_and_do_open(name, uri, opts)
|
||||||
|
|
|
@ -16,6 +16,7 @@ defmodule Pleroma.User do
|
||||||
alias Pleroma.Conversation.Participation
|
alias Pleroma.Conversation.Participation
|
||||||
alias Pleroma.Delivery
|
alias Pleroma.Delivery
|
||||||
alias Pleroma.FollowingRelationship
|
alias Pleroma.FollowingRelationship
|
||||||
|
alias Pleroma.Formatter
|
||||||
alias Pleroma.HTML
|
alias Pleroma.HTML
|
||||||
alias Pleroma.Keys
|
alias Pleroma.Keys
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
|
@ -452,7 +453,7 @@ defp put_fields(changeset) do
|
||||||
|
|
||||||
fields =
|
fields =
|
||||||
raw_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
|
changeset
|
||||||
|> put_change(:raw_fields, raw_fields)
|
|> put_change(:raw_fields, raw_fields)
|
||||||
|
@ -462,6 +463,12 @@ defp put_fields(changeset) do
|
||||||
end
|
end
|
||||||
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
|
defp put_change_if_present(changeset, map_field, value_function) do
|
||||||
if value = get_change(changeset, map_field) do
|
if value = get_change(changeset, map_field) do
|
||||||
with {:ok, new_value} <- value_function.(value) do
|
with {:ok, new_value} <- value_function.(value) do
|
||||||
|
@ -1979,17 +1986,6 @@ def fields(%{fields: nil}), do: []
|
||||||
|
|
||||||
def fields(%{fields: fields}), do: fields
|
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
|
def validate_fields(changeset, remote? \\ false) do
|
||||||
limit_name = if remote?, do: :max_remote_account_fields, else: :max_account_fields
|
limit_name = if remote?, do: :max_remote_account_fields, else: :max_account_fields
|
||||||
limit = Pleroma.Config.get([:instance, limit_name], 0)
|
limit = Pleroma.Config.get([:instance, limit_name], 0)
|
||||||
|
|
|
@ -6,14 +6,10 @@ def type, do: :string
|
||||||
def cast(object) when is_binary(object) do
|
def cast(object) when is_binary(object) do
|
||||||
# Host has to be present and scheme has to be an http scheme (for now)
|
# Host has to be present and scheme has to be an http scheme (for now)
|
||||||
case URI.parse(object) do
|
case URI.parse(object) do
|
||||||
%URI{host: nil} ->
|
%URI{host: nil} -> :error
|
||||||
:error
|
%URI{host: ""} -> :error
|
||||||
|
%URI{scheme: scheme} when scheme in ["https", "http"] -> {:ok, object}
|
||||||
%URI{scheme: scheme} when scheme in ["https", "http"] ->
|
_ -> :error
|
||||||
{:ok, object}
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
:error
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -576,9 +576,8 @@ def relay_unfollow(%{assigns: %{user: admin}} = conn, %{"relay_url" => target})
|
||||||
|
|
||||||
@doc "Sends registration invite via email"
|
@doc "Sends registration invite via email"
|
||||||
def email_invite(%{assigns: %{user: user}} = conn, %{"email" => email} = params) do
|
def email_invite(%{assigns: %{user: user}} = conn, %{"email" => email} = params) do
|
||||||
with true <-
|
with {_, false} <- {:registrations_open, Config.get([:instance, :registrations_open])},
|
||||||
Config.get([:instance, :invites_enabled]) &&
|
{_, true} <- {:invites_enabled, Config.get([:instance, :invites_enabled])},
|
||||||
!Config.get([:instance, :registrations_open]),
|
|
||||||
{:ok, invite_token} <- UserInviteToken.create_invite(),
|
{:ok, invite_token} <- UserInviteToken.create_invite(),
|
||||||
email <-
|
email <-
|
||||||
Pleroma.Emails.UserEmail.user_invitation_email(
|
Pleroma.Emails.UserEmail.user_invitation_email(
|
||||||
|
@ -589,6 +588,18 @@ def email_invite(%{assigns: %{user: user}} = conn, %{"email" => email} = params)
|
||||||
),
|
),
|
||||||
{:ok, _} <- Pleroma.Emails.Mailer.deliver(email) do
|
{:ok, _} <- Pleroma.Emails.Mailer.deliver(email) do
|
||||||
json_response(conn, :no_content, "")
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
44
lib/pleroma/web/api_spec.ex
Normal file
44
lib/pleroma/web/api_spec.ex
Normal file
|
@ -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
|
27
lib/pleroma/web/api_spec/helpers.ex
Normal file
27
lib/pleroma/web/api_spec/helpers.ex
Normal file
|
@ -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
|
96
lib/pleroma/web/api_spec/operations/app_operation.ex
Normal file
96
lib/pleroma/web/api_spec/operations/app_operation.ex
Normal file
|
@ -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
|
33
lib/pleroma/web/api_spec/schemas/app_create_request.ex
Normal file
33
lib/pleroma/web/api_spec/schemas/app_create_request.ex
Normal file
|
@ -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
|
33
lib/pleroma/web/api_spec/schemas/app_create_response.ex
Normal file
33
lib/pleroma/web/api_spec/schemas/app_create_response.ex
Normal file
|
@ -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
|
|
@ -14,17 +14,20 @@ defmodule Pleroma.Web.MastodonAPI.AppController do
|
||||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
|
|
||||||
plug(OAuthScopesPlug, %{scopes: ["read"]} when action == :verify_credentials)
|
plug(OAuthScopesPlug, %{scopes: ["read"]} when action == :verify_credentials)
|
||||||
|
plug(OpenApiSpex.Plug.CastAndValidate)
|
||||||
|
|
||||||
@local_mastodon_name "Mastodon-Local"
|
@local_mastodon_name "Mastodon-Local"
|
||||||
|
|
||||||
|
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.AppOperation
|
||||||
|
|
||||||
@doc "POST /api/v1/apps"
|
@doc "POST /api/v1/apps"
|
||||||
def create(conn, params) do
|
def create(%{body_params: params} = conn, _params) do
|
||||||
scopes = Scopes.fetch_scopes(params, ["read"])
|
scopes = Scopes.fetch_scopes(params, ["read"])
|
||||||
|
|
||||||
app_attrs =
|
app_attrs =
|
||||||
params
|
params
|
||||||
|> Map.drop(["scope", "scopes"])
|
|> Map.take([:client_name, :redirect_uris, :website])
|
||||||
|> Map.put("scopes", scopes)
|
|> Map.put(:scopes, scopes)
|
||||||
|
|
||||||
with cs <- App.register_changeset(%App{}, app_attrs),
|
with cs <- App.register_changeset(%App{}, app_attrs),
|
||||||
false <- cs.changes[:client_name] == @local_mastodon_name,
|
false <- cs.changes[:client_name] == @local_mastodon_name,
|
||||||
|
|
|
@ -15,7 +15,12 @@ defmodule Pleroma.Web.OAuth.Scopes do
|
||||||
Note: `scopes` is used by Mastodon — supporting it but sticking to
|
Note: `scopes` is used by Mastodon — supporting it but sticking to
|
||||||
OAuth's standard `scope` wherever we control it
|
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
|
def fetch_scopes(params, default) do
|
||||||
parse_scopes(params["scope"] || params["scopes"], default)
|
parse_scopes(params["scope"] || params["scopes"], default)
|
||||||
end
|
end
|
||||||
|
|
|
@ -29,6 +29,7 @@ defmodule Pleroma.Web.Router do
|
||||||
plug(Pleroma.Plugs.SetUserSessionIdPlug)
|
plug(Pleroma.Plugs.SetUserSessionIdPlug)
|
||||||
plug(Pleroma.Plugs.EnsureUserKeyPlug)
|
plug(Pleroma.Plugs.EnsureUserKeyPlug)
|
||||||
plug(Pleroma.Plugs.IdempotencyPlug)
|
plug(Pleroma.Plugs.IdempotencyPlug)
|
||||||
|
plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec)
|
||||||
end
|
end
|
||||||
|
|
||||||
pipeline :authenticated_api do
|
pipeline :authenticated_api do
|
||||||
|
@ -44,6 +45,7 @@ defmodule Pleroma.Web.Router do
|
||||||
plug(Pleroma.Plugs.SetUserSessionIdPlug)
|
plug(Pleroma.Plugs.SetUserSessionIdPlug)
|
||||||
plug(Pleroma.Plugs.EnsureAuthenticatedPlug)
|
plug(Pleroma.Plugs.EnsureAuthenticatedPlug)
|
||||||
plug(Pleroma.Plugs.IdempotencyPlug)
|
plug(Pleroma.Plugs.IdempotencyPlug)
|
||||||
|
plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec)
|
||||||
end
|
end
|
||||||
|
|
||||||
pipeline :admin_api do
|
pipeline :admin_api do
|
||||||
|
@ -61,6 +63,7 @@ defmodule Pleroma.Web.Router do
|
||||||
plug(Pleroma.Plugs.EnsureAuthenticatedPlug)
|
plug(Pleroma.Plugs.EnsureAuthenticatedPlug)
|
||||||
plug(Pleroma.Plugs.UserIsAdminPlug)
|
plug(Pleroma.Plugs.UserIsAdminPlug)
|
||||||
plug(Pleroma.Plugs.IdempotencyPlug)
|
plug(Pleroma.Plugs.IdempotencyPlug)
|
||||||
|
plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec)
|
||||||
end
|
end
|
||||||
|
|
||||||
pipeline :mastodon_html do
|
pipeline :mastodon_html do
|
||||||
|
@ -94,10 +97,12 @@ defmodule Pleroma.Web.Router do
|
||||||
|
|
||||||
pipeline :config do
|
pipeline :config do
|
||||||
plug(:accepts, ["json", "xml"])
|
plug(:accepts, ["json", "xml"])
|
||||||
|
plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec)
|
||||||
end
|
end
|
||||||
|
|
||||||
pipeline :pleroma_api do
|
pipeline :pleroma_api do
|
||||||
plug(:accepts, ["html", "json"])
|
plug(:accepts, ["html", "json"])
|
||||||
|
plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec)
|
||||||
end
|
end
|
||||||
|
|
||||||
pipeline :mailbox_preview do
|
pipeline :mailbox_preview do
|
||||||
|
@ -500,6 +505,12 @@ defmodule Pleroma.Web.Router do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
scope "/api" do
|
||||||
|
pipe_through(:api)
|
||||||
|
|
||||||
|
get("/openapi", OpenApiSpex.Plug.RenderSpec, [])
|
||||||
|
end
|
||||||
|
|
||||||
scope "/api", Pleroma.Web, as: :authenticated_twitter_api do
|
scope "/api", Pleroma.Web, as: :authenticated_twitter_api do
|
||||||
pipe_through(:authenticated_api)
|
pipe_through(:authenticated_api)
|
||||||
|
|
||||||
|
|
3
mix.exs
3
mix.exs
|
@ -179,7 +179,8 @@ defp deps do
|
||||||
git: "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git",
|
git: "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git",
|
||||||
ref: "e0f16822d578866e186a0974d65ad58cddc1e2ab"},
|
ref: "e0f16822d578866e186a0974d65ad58cddc1e2ab"},
|
||||||
{:mox, "~> 0.5", only: :test},
|
{:mox, "~> 0.5", only: :test},
|
||||||
{:restarter, path: "./restarter"}
|
{:restarter, path: "./restarter"},
|
||||||
|
{:open_api_spex, "~> 3.6"}
|
||||||
] ++ oauth_deps()
|
] ++ oauth_deps()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
1
mix.lock
1
mix.lock
|
@ -74,6 +74,7 @@
|
||||||
"nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm", "589b5af56f4afca65217a1f3eb3fee7e79b09c40c742fddc1c312b3ac0b3399f"},
|
"nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm", "589b5af56f4afca65217a1f3eb3fee7e79b09c40c742fddc1c312b3ac0b3399f"},
|
||||||
"nodex": {:git, "https://git.pleroma.social/pleroma/nodex", "cb6730f943cfc6aad674c92161be23a8411f15d1", [ref: "cb6730f943cfc6aad674c92161be23a8411f15d1"]},
|
"nodex": {:git, "https://git.pleroma.social/pleroma/nodex", "cb6730f943cfc6aad674c92161be23a8411f15d1", [ref: "cb6730f943cfc6aad674c92161be23a8411f15d1"]},
|
||||||
"oban": {:hex, :oban, "0.12.1", "695e9490c6e0edfca616d80639528e448bd29b3bff7b7dd10a56c79b00a5d7fb", [:mix], [{:ecto_sql, "~> 3.1", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.14", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c1d58d69b8b5a86e7167abbb8cc92764a66f25f12f6172052595067fc6a30a17"},
|
"oban": {:hex, :oban, "0.12.1", "695e9490c6e0edfca616d80639528e448bd29b3bff7b7dd10a56c79b00a5d7fb", [:mix], [{:ecto_sql, "~> 3.1", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.14", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c1d58d69b8b5a86e7167abbb8cc92764a66f25f12f6172052595067fc6a30a17"},
|
||||||
|
"open_api_spex": {:hex, :open_api_spex, "3.6.0", "64205aba9f2607f71b08fd43e3351b9c5e9898ec5ef49fc0ae35890da502ade9", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.1", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm", "126ba3473966277132079cb1d5bf1e3df9e36fe2acd00166e75fd125cecb59c5"},
|
||||||
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"},
|
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"},
|
||||||
"pbkdf2_elixir": {:hex, :pbkdf2_elixir, "0.12.4", "8dd29ed783f2e12195d7e0a4640effc0a7c37e6537da491f1db01839eee6d053", [:mix], [], "hexpm", "595d09db74cb093b1903381c9de423276a931a2480a46a1a5dc7f932a2a6375b"},
|
"pbkdf2_elixir": {:hex, :pbkdf2_elixir, "0.12.4", "8dd29ed783f2e12195d7e0a4640effc0a7c37e6537da491f1db01839eee6d053", [:mix], [], "hexpm", "595d09db74cb093b1903381c9de423276a931a2480a46a1a5dc7f932a2a6375b"},
|
||||||
"phoenix": {:hex, :phoenix, "1.4.13", "67271ad69b51f3719354604f4a3f968f83aa61c19199343656c9caee057ff3b8", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ab765a0feddb81fc62e2116c827b5f068df85159c162bee760745276ad7ddc1b"},
|
"phoenix": {:hex, :phoenix, "1.4.13", "67271ad69b51f3719354604f4a3f968f83aa61c19199343656c9caee057ff3b8", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ab765a0feddb81fc62e2116c827b5f068df85159c162bee760745276ad7ddc1b"},
|
||||||
|
|
|
@ -150,13 +150,13 @@ test "gives a replacement for user links, using local nicknames in user links te
|
||||||
assert length(mentions) == 3
|
assert length(mentions) == 3
|
||||||
|
|
||||||
expected_text =
|
expected_text =
|
||||||
~s(<span class="h-card"><a data-user="#{gsimg.id}" class="u-url mention" href="#{
|
~s(<span class="h-card"><a class="u-url mention" data-user="#{gsimg.id}" href="#{
|
||||||
gsimg.ap_id
|
gsimg.ap_id
|
||||||
}" rel="ugc">@<span>gsimg</span></a></span> According to <span class="h-card"><a data-user="#{
|
}" rel="ugc">@<span>gsimg</span></a></span> According to <span class="h-card"><a class="u-url mention" data-user="#{
|
||||||
archaeme.id
|
archaeme.id
|
||||||
}" class="u-url mention" href="#{"https://archeme/@archa_eme_"}" rel="ugc">@<span>archa_eme_</span></a></span>, that is @daggsy. Also hello <span class="h-card"><a data-user="#{
|
}" href="#{"https://archeme/@archa_eme_"}" rel="ugc">@<span>archa_eme_</span></a></span>, that is @daggsy. Also hello <span class="h-card"><a class="u-url mention" data-user="#{
|
||||||
archaeme_remote.id
|
archaeme_remote.id
|
||||||
}" class="u-url mention" href="#{archaeme_remote.ap_id}" rel="ugc">@<span>archaeme</span></a></span>)
|
}" href="#{archaeme_remote.ap_id}" rel="ugc">@<span>archaeme</span></a></span>)
|
||||||
|
|
||||||
assert expected_text == text
|
assert expected_text == text
|
||||||
end
|
end
|
||||||
|
@ -171,7 +171,7 @@ test "gives a replacement for user links when the user is using Osada" do
|
||||||
assert length(mentions) == 1
|
assert length(mentions) == 1
|
||||||
|
|
||||||
expected_text =
|
expected_text =
|
||||||
~s(<span class="h-card"><a data-user="#{mike.id}" class="u-url mention" href="#{
|
~s(<span class="h-card"><a class="u-url mention" data-user="#{mike.id}" href="#{
|
||||||
mike.ap_id
|
mike.ap_id
|
||||||
}" rel="ugc">@<span>mike</span></a></span> test)
|
}" rel="ugc">@<span>mike</span></a></span> test)
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ test "gives a replacement for single-character local nicknames" do
|
||||||
assert length(mentions) == 1
|
assert length(mentions) == 1
|
||||||
|
|
||||||
expected_text =
|
expected_text =
|
||||||
~s(<span class="h-card"><a data-user="#{o.id}" class="u-url mention" href="#{o.ap_id}" rel="ugc">@<span>o</span></a></span> hi)
|
~s(<span class="h-card"><a class="u-url mention" data-user="#{o.id}" href="#{o.ap_id}" rel="ugc">@<span>o</span></a></span> hi)
|
||||||
|
|
||||||
assert expected_text == text
|
assert expected_text == text
|
||||||
end
|
end
|
||||||
|
@ -209,17 +209,13 @@ test "given the 'safe_mention' option, it will only mention people in the beginn
|
||||||
assert mentions == [{"@#{user.nickname}", user}, {"@#{other_user.nickname}", other_user}]
|
assert mentions == [{"@#{user.nickname}", user}, {"@#{other_user.nickname}", other_user}]
|
||||||
|
|
||||||
assert expected_text ==
|
assert expected_text ==
|
||||||
~s(<span class="h-card"><a data-user="#{user.id}" class="u-url mention" href="#{
|
~s(<span class="h-card"><a class="u-url mention" data-user="#{user.id}" href="#{
|
||||||
user.ap_id
|
user.ap_id
|
||||||
}" rel="ugc">@<span>#{user.nickname}</span></a></span> <span class="h-card"><a data-user="#{
|
}" rel="ugc">@<span>#{user.nickname}</span></a></span> <span class="h-card"><a class="u-url mention" data-user="#{
|
||||||
other_user.id
|
other_user.id
|
||||||
}" class="u-url mention" href="#{other_user.ap_id}" rel="ugc">@<span>#{
|
}" href="#{other_user.ap_id}" rel="ugc">@<span>#{other_user.nickname}</span></a></span> hey dudes i hate <span class="h-card"><a class="u-url mention" data-user="#{
|
||||||
other_user.nickname
|
|
||||||
}</span></a></span> hey dudes i hate <span class="h-card"><a data-user="#{
|
|
||||||
third_user.id
|
third_user.id
|
||||||
}" class="u-url mention" href="#{third_user.ap_id}" rel="ugc">@<span>#{
|
}" href="#{third_user.ap_id}" rel="ugc">@<span>#{third_user.nickname}</span></a></span>)
|
||||||
third_user.nickname
|
|
||||||
}</span></a></span>)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "given the 'safe_mention' option, it will still work without any mention" do
|
test "given the 'safe_mention' option, it will still work without any mention" do
|
||||||
|
|
|
@ -1404,7 +1404,7 @@ test "preserves hosts in user links text" do
|
||||||
bio = "A.k.a. @nick@domain.com"
|
bio = "A.k.a. @nick@domain.com"
|
||||||
|
|
||||||
expected_text =
|
expected_text =
|
||||||
~s(A.k.a. <span class="h-card"><a data-user="#{remote_user.id}" class="u-url mention" href="#{
|
~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{
|
||||||
remote_user.ap_id
|
remote_user.ap_id
|
||||||
}" rel="ugc">@<span>nick@domain.com</span></a></span>)
|
}" rel="ugc">@<span>nick@domain.com</span></a></span>)
|
||||||
|
|
||||||
|
|
|
@ -625,6 +625,39 @@ test "it returns 403 if requested by a non-admin" do
|
||||||
|
|
||||||
assert json_response(conn, :forbidden)
|
assert json_response(conn, :forbidden)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "email with +", %{conn: conn, admin: admin} do
|
||||||
|
recipient_email = "foo+bar@baz.com"
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json;charset=utf-8")
|
||||||
|
|> post("/api/pleroma/admin/users/email_invite", %{email: recipient_email})
|
||||||
|
|> json_response(:no_content)
|
||||||
|
|
||||||
|
token_record =
|
||||||
|
Pleroma.UserInviteToken
|
||||||
|
|> Repo.all()
|
||||||
|
|> List.last()
|
||||||
|
|
||||||
|
assert token_record
|
||||||
|
refute token_record.used
|
||||||
|
|
||||||
|
notify_email = Config.get([:instance, :notify_email])
|
||||||
|
instance_name = Config.get([:instance, :name])
|
||||||
|
|
||||||
|
email =
|
||||||
|
Pleroma.Emails.UserEmail.user_invitation_email(
|
||||||
|
admin,
|
||||||
|
token_record,
|
||||||
|
recipient_email
|
||||||
|
)
|
||||||
|
|
||||||
|
Swoosh.TestAssertions.assert_email_sent(
|
||||||
|
from: {instance_name, notify_email},
|
||||||
|
to: recipient_email,
|
||||||
|
html_body: email.html_body
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do
|
describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do
|
||||||
|
@ -637,7 +670,8 @@ test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn} do
|
||||||
|
|
||||||
conn = post(conn, "/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
|
conn = post(conn, "/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
|
||||||
|
|
||||||
assert json_response(conn, :internal_server_error)
|
assert json_response(conn, :bad_request) ==
|
||||||
|
"To send invites you need to set the `invites_enabled` option to true."
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns 500 if `registrations_open` is enabled", %{conn: conn} do
|
test "it returns 500 if `registrations_open` is enabled", %{conn: conn} do
|
||||||
|
@ -646,7 +680,8 @@ test "it returns 500 if `registrations_open` is enabled", %{conn: conn} do
|
||||||
|
|
||||||
conn = post(conn, "/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
|
conn = post(conn, "/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
|
||||||
|
|
||||||
assert json_response(conn, :internal_server_error)
|
assert json_response(conn, :bad_request) ==
|
||||||
|
"To send invites you need to set the `registrations_open` option to false."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
45
test/web/api_spec/app_operation_test.exs
Normal file
45
test/web/api_spec/app_operation_test.exs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# 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.AppOperationTest do
|
||||||
|
use Pleroma.Web.ConnCase, async: true
|
||||||
|
|
||||||
|
alias Pleroma.Web.ApiSpec
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.AppCreateRequest
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.AppCreateResponse
|
||||||
|
|
||||||
|
import OpenApiSpex.TestAssertions
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
test "AppCreateRequest example matches schema" do
|
||||||
|
api_spec = ApiSpec.spec()
|
||||||
|
schema = AppCreateRequest.schema()
|
||||||
|
assert_schema(schema.example, "AppCreateRequest", api_spec)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "AppCreateResponse example matches schema" do
|
||||||
|
api_spec = ApiSpec.spec()
|
||||||
|
schema = AppCreateResponse.schema()
|
||||||
|
assert_schema(schema.example, "AppCreateResponse", api_spec)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "AppController produces a AppCreateResponse", %{conn: conn} do
|
||||||
|
api_spec = ApiSpec.spec()
|
||||||
|
app_attrs = build(:oauth_app)
|
||||||
|
|
||||||
|
json =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> post(
|
||||||
|
"/api/v1/apps",
|
||||||
|
Jason.encode!(%{
|
||||||
|
client_name: app_attrs.client_name,
|
||||||
|
redirect_uris: app_attrs.redirect_uris
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
assert_schema(json, "AppCreateResponse", api_spec)
|
||||||
|
end
|
||||||
|
end
|
|
@ -159,11 +159,11 @@ test "works for text/markdown with mentions" do
|
||||||
{output, _, _} = Utils.format_input(text, "text/markdown")
|
{output, _, _} = Utils.format_input(text, "text/markdown")
|
||||||
|
|
||||||
assert output ==
|
assert output ==
|
||||||
~s(<p><strong>hello world</strong></p><p><em>another <span class="h-card"><a data-user="#{
|
~s(<p><strong>hello world</strong></p><p><em>another <span class="h-card"><a class="u-url mention" data-user="#{
|
||||||
user.id
|
user.id
|
||||||
}" class="u-url mention" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> and <span class="h-card"><a data-user="#{
|
}" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> and <span class="h-card"><a class="u-url mention" data-user="#{
|
||||||
user.id
|
user.id
|
||||||
}" class="u-url mention" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> <a href="http://google.com" rel="ugc">google.com</a> paragraph</em></p>)
|
}" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> <a href="http://google.com" rel="ugc">google.com</a> paragraph</em></p>)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -82,9 +82,9 @@ test "updates the user's bio", %{conn: conn} do
|
||||||
assert user_data = json_response(conn, 200)
|
assert user_data = json_response(conn, 200)
|
||||||
|
|
||||||
assert user_data["note"] ==
|
assert user_data["note"] ==
|
||||||
~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe">#cofe</a> with <span class="h-card"><a data-user="#{
|
~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe">#cofe</a> with <span class="h-card"><a class="u-url mention" data-user="#{
|
||||||
user2.id
|
user2.id
|
||||||
}" class="u-url mention" href="#{user2.ap_id}" rel="ugc">@<span>#{user2.nickname}</span></a></span><br/><br/>suya..)
|
}" href="#{user2.ap_id}" rel="ugc">@<span>#{user2.nickname}</span></a></span><br/><br/>suya..)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "updates the user's locking status", %{conn: conn} do
|
test "updates the user's locking status", %{conn: conn} do
|
||||||
|
@ -273,7 +273,7 @@ test "updates profile emojos", %{user: user, conn: conn} do
|
||||||
test "update fields", %{conn: conn} do
|
test "update fields", %{conn: conn} do
|
||||||
fields = [
|
fields = [
|
||||||
%{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "<script>bar</script>"},
|
%{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "<script>bar</script>"},
|
||||||
%{"name" => "link", "value" => "cofe.io"}
|
%{"name" => "link.io", "value" => "cofe.io"}
|
||||||
]
|
]
|
||||||
|
|
||||||
account_data =
|
account_data =
|
||||||
|
@ -283,7 +283,10 @@ test "update fields", %{conn: conn} do
|
||||||
|
|
||||||
assert account_data["fields"] == [
|
assert account_data["fields"] == [
|
||||||
%{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "bar"},
|
%{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "bar"},
|
||||||
%{"name" => "link", "value" => ~S(<a href="http://cofe.io" rel="ugc">cofe.io</a>)}
|
%{
|
||||||
|
"name" => "link.io",
|
||||||
|
"value" => ~S(<a href="http://cofe.io" rel="ugc">cofe.io</a>)
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
assert account_data["source"]["fields"] == [
|
assert account_data["source"]["fields"] == [
|
||||||
|
@ -291,14 +294,16 @@ test "update fields", %{conn: conn} do
|
||||||
"name" => "<a href=\"http://google.com\">foo</a>",
|
"name" => "<a href=\"http://google.com\">foo</a>",
|
||||||
"value" => "<script>bar</script>"
|
"value" => "<script>bar</script>"
|
||||||
},
|
},
|
||||||
%{"name" => "link", "value" => "cofe.io"}
|
%{"name" => "link.io", "value" => "cofe.io"}
|
||||||
]
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "update fields via x-www-form-urlencoded", %{conn: conn} do
|
||||||
fields =
|
fields =
|
||||||
[
|
[
|
||||||
"fields_attributes[1][name]=link",
|
"fields_attributes[1][name]=link",
|
||||||
"fields_attributes[1][value]=cofe.io",
|
"fields_attributes[1][value]=http://cofe.io",
|
||||||
"fields_attributes[0][name]=<a href=\"http://google.com\">foo</a>",
|
"fields_attributes[0][name]=foo",
|
||||||
"fields_attributes[0][value]=bar"
|
"fields_attributes[0][value]=bar"
|
||||||
]
|
]
|
||||||
|> Enum.join("&")
|
|> Enum.join("&")
|
||||||
|
@ -310,51 +315,20 @@ test "update fields", %{conn: conn} do
|
||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
assert account["fields"] == [
|
assert account["fields"] == [
|
||||||
%{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "bar"},
|
%{"name" => "foo", "value" => "bar"},
|
||||||
%{"name" => "link", "value" => ~S(<a href="http://cofe.io" rel="ugc">cofe.io</a>)}
|
%{
|
||||||
|
"name" => "link",
|
||||||
|
"value" => ~S(<a href="http://cofe.io" rel="ugc">http://cofe.io</a>)
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
assert account["source"]["fields"] == [
|
assert account["source"]["fields"] == [
|
||||||
%{
|
%{"name" => "foo", "value" => "bar"},
|
||||||
"name" => "<a href=\"http://google.com\">foo</a>",
|
%{"name" => "link", "value" => "http://cofe.io"}
|
||||||
"value" => "bar"
|
|
||||||
},
|
|
||||||
%{"name" => "link", "value" => "cofe.io"}
|
|
||||||
]
|
]
|
||||||
|
end
|
||||||
|
|
||||||
name_limit = Pleroma.Config.get([:instance, :account_field_name_length])
|
test "update fields with empty name", %{conn: conn} do
|
||||||
value_limit = Pleroma.Config.get([:instance, :account_field_value_length])
|
|
||||||
|
|
||||||
long_value = Enum.map(0..value_limit, fn _ -> "x" end) |> Enum.join()
|
|
||||||
|
|
||||||
fields = [%{"name" => "<b>foo<b>", "value" => long_value}]
|
|
||||||
|
|
||||||
assert %{"error" => "Invalid request"} ==
|
|
||||||
conn
|
|
||||||
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
|
||||||
|> json_response(403)
|
|
||||||
|
|
||||||
long_name = Enum.map(0..name_limit, fn _ -> "x" end) |> Enum.join()
|
|
||||||
|
|
||||||
fields = [%{"name" => long_name, "value" => "bar"}]
|
|
||||||
|
|
||||||
assert %{"error" => "Invalid request"} ==
|
|
||||||
conn
|
|
||||||
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
|
||||||
|> json_response(403)
|
|
||||||
|
|
||||||
Pleroma.Config.put([:instance, :max_account_fields], 1)
|
|
||||||
|
|
||||||
fields = [
|
|
||||||
%{"name" => "<b>foo<b>", "value" => "<i>bar</i>"},
|
|
||||||
%{"name" => "link", "value" => "cofe.io"}
|
|
||||||
]
|
|
||||||
|
|
||||||
assert %{"error" => "Invalid request"} ==
|
|
||||||
conn
|
|
||||||
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
|
||||||
|> json_response(403)
|
|
||||||
|
|
||||||
fields = [
|
fields = [
|
||||||
%{"name" => "foo", "value" => ""},
|
%{"name" => "foo", "value" => ""},
|
||||||
%{"name" => "", "value" => "bar"}
|
%{"name" => "", "value" => "bar"}
|
||||||
|
@ -369,5 +343,39 @@ test "update fields", %{conn: conn} do
|
||||||
%{"name" => "foo", "value" => ""}
|
%{"name" => "foo", "value" => ""}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "update fields when invalid request", %{conn: conn} do
|
||||||
|
name_limit = Pleroma.Config.get([:instance, :account_field_name_length])
|
||||||
|
value_limit = Pleroma.Config.get([:instance, :account_field_value_length])
|
||||||
|
|
||||||
|
long_name = Enum.map(0..name_limit, fn _ -> "x" end) |> Enum.join()
|
||||||
|
long_value = Enum.map(0..value_limit, fn _ -> "x" end) |> Enum.join()
|
||||||
|
|
||||||
|
fields = [%{"name" => "foo", "value" => long_value}]
|
||||||
|
|
||||||
|
assert %{"error" => "Invalid request"} ==
|
||||||
|
conn
|
||||||
|
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
||||||
|
|> json_response(403)
|
||||||
|
|
||||||
|
fields = [%{"name" => long_name, "value" => "bar"}]
|
||||||
|
|
||||||
|
assert %{"error" => "Invalid request"} ==
|
||||||
|
conn
|
||||||
|
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
||||||
|
|> json_response(403)
|
||||||
|
|
||||||
|
Pleroma.Config.put([:instance, :max_account_fields], 1)
|
||||||
|
|
||||||
|
fields = [
|
||||||
|
%{"name" => "foo", "value" => "bar"},
|
||||||
|
%{"name" => "link", "value" => "cofe.io"}
|
||||||
|
]
|
||||||
|
|
||||||
|
assert %{"error" => "Invalid request"} ==
|
||||||
|
conn
|
||||||
|
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
||||||
|
|> json_response(403)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -794,7 +794,9 @@ test "blocking / unblocking a user" do
|
||||||
|
|
||||||
test "Account registration via Application", %{conn: conn} do
|
test "Account registration via Application", %{conn: conn} do
|
||||||
conn =
|
conn =
|
||||||
post(conn, "/api/v1/apps", %{
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> post("/api/v1/apps", %{
|
||||||
client_name: "client_name",
|
client_name: "client_name",
|
||||||
redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
|
redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
|
||||||
scopes: "read, write, follow"
|
scopes: "read, write, follow"
|
||||||
|
|
|
@ -16,8 +16,7 @@ test "apps/verify_credentials", %{conn: conn} do
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|> assign(:user, token.user)
|
|> put_req_header("authorization", "Bearer #{token.token}")
|
||||||
|> assign(:token, token)
|
|
||||||
|> get("/api/v1/apps/verify_credentials")
|
|> get("/api/v1/apps/verify_credentials")
|
||||||
|
|
||||||
app = Repo.preload(token, :app).app
|
app = Repo.preload(token, :app).app
|
||||||
|
@ -37,6 +36,7 @@ test "creates an oauth app", %{conn: conn} do
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> assign(:user, user)
|
|> assign(:user, user)
|
||||||
|> post("/api/v1/apps", %{
|
|> post("/api/v1/apps", %{
|
||||||
client_name: app_attrs.client_name,
|
client_name: app_attrs.client_name,
|
||||||
|
|
|
@ -26,7 +26,7 @@ test "list of notifications" do
|
||||||
|> get("/api/v1/notifications")
|
|> get("/api/v1/notifications")
|
||||||
|
|
||||||
expected_response =
|
expected_response =
|
||||||
"hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
|
"hi <span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{user.id}\" href=\"#{
|
||||||
user.ap_id
|
user.ap_id
|
||||||
}\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
|
}\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ test "getting a single notification" do
|
||||||
conn = get(conn, "/api/v1/notifications/#{notification.id}")
|
conn = get(conn, "/api/v1/notifications/#{notification.id}")
|
||||||
|
|
||||||
expected_response =
|
expected_response =
|
||||||
"hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
|
"hi <span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{user.id}\" href=\"#{
|
||||||
user.ap_id
|
user.ap_id
|
||||||
}\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
|
}\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ test "it registers a new user and parses mentions in the bio" do
|
||||||
{:ok, user2} = TwitterAPI.register_user(data2)
|
{:ok, user2} = TwitterAPI.register_user(data2)
|
||||||
|
|
||||||
expected_text =
|
expected_text =
|
||||||
~s(<span class="h-card"><a data-user="#{user1.id}" class="u-url mention" href="#{
|
~s(<span class="h-card"><a class="u-url mention" data-user="#{user1.id}" href="#{
|
||||||
user1.ap_id
|
user1.ap_id
|
||||||
}" rel="ugc">@<span>john</span></a></span> test)
|
}" rel="ugc">@<span>john</span></a></span> test)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue