Merge remote-tracking branch 'remotes/origin/develop' into follow-request-notifications
This commit is contained in:
commit
cf5ca7e45b
@ -202,4 +202,5 @@ Has theses additional parameters (which are the same as in Pleroma-API):
|
|||||||
- `bio`: optional
|
- `bio`: optional
|
||||||
- `captcha_solution`: optional, contains provider-specific captcha solution,
|
- `captcha_solution`: optional, contains provider-specific captcha solution,
|
||||||
- `captcha_token`: optional, contains provider-specific captcha token
|
- `captcha_token`: optional, contains provider-specific captcha token
|
||||||
|
- `captcha_answer_data`: optional, contains provider-specific captcha data
|
||||||
- `token`: invite token required when the registrations aren't public.
|
- `token`: invite token required when the registrations aren't public.
|
||||||
|
@ -73,7 +73,6 @@ defmodule Pleroma.Application do
|
|||||||
Pleroma.Repo,
|
Pleroma.Repo,
|
||||||
Config.TransferTask,
|
Config.TransferTask,
|
||||||
Pleroma.Emoji,
|
Pleroma.Emoji,
|
||||||
Pleroma.Captcha,
|
|
||||||
Pleroma.Plugs.RateLimiter.Supervisor
|
Pleroma.Plugs.RateLimiter.Supervisor
|
||||||
] ++
|
] ++
|
||||||
cachex_children() ++
|
cachex_children() ++
|
||||||
|
@ -3,53 +3,22 @@
|
|||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Captcha do
|
defmodule Pleroma.Captcha do
|
||||||
import Pleroma.Web.Gettext
|
|
||||||
|
|
||||||
alias Calendar.DateTime
|
alias Calendar.DateTime
|
||||||
alias Plug.Crypto.KeyGenerator
|
alias Plug.Crypto.KeyGenerator
|
||||||
alias Plug.Crypto.MessageEncryptor
|
alias Plug.Crypto.MessageEncryptor
|
||||||
|
|
||||||
use GenServer
|
|
||||||
|
|
||||||
@doc false
|
|
||||||
def start_link(_) do
|
|
||||||
GenServer.start_link(__MODULE__, [], name: __MODULE__)
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc false
|
|
||||||
def init(_) do
|
|
||||||
{:ok, nil}
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Ask the configured captcha service for a new captcha
|
Ask the configured captcha service for a new captcha
|
||||||
"""
|
"""
|
||||||
def new do
|
def new do
|
||||||
GenServer.call(__MODULE__, :new)
|
if not enabled?() do
|
||||||
end
|
%{type: :none}
|
||||||
|
|
||||||
@doc """
|
|
||||||
Ask the configured captcha service to validate the captcha
|
|
||||||
"""
|
|
||||||
def validate(token, captcha, answer_data) do
|
|
||||||
GenServer.call(__MODULE__, {:validate, token, captcha, answer_data})
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc false
|
|
||||||
def handle_call(:new, _from, state) do
|
|
||||||
enabled = Pleroma.Config.get([__MODULE__, :enabled])
|
|
||||||
|
|
||||||
if !enabled do
|
|
||||||
{:reply, %{type: :none}, state}
|
|
||||||
else
|
else
|
||||||
new_captcha = method().new()
|
new_captcha = method().new()
|
||||||
|
|
||||||
secret_key_base = Pleroma.Config.get!([Pleroma.Web.Endpoint, :secret_key_base])
|
|
||||||
|
|
||||||
# This make salt a little different for two keys
|
# This make salt a little different for two keys
|
||||||
token = new_captcha[:token]
|
{secret, sign_secret} = secret_pair(new_captcha[:token])
|
||||||
secret = KeyGenerator.generate(secret_key_base, token <> "_encrypt")
|
|
||||||
sign_secret = KeyGenerator.generate(secret_key_base, token <> "_sign")
|
|
||||||
# Basically copy what Phoenix.Token does here, add the time to
|
# Basically copy what Phoenix.Token does here, add the time to
|
||||||
# the actual data and make it a binary to then encrypt it
|
# the actual data and make it a binary to then encrypt it
|
||||||
encrypted_captcha_answer =
|
encrypted_captcha_answer =
|
||||||
@ -60,55 +29,73 @@ defmodule Pleroma.Captcha do
|
|||||||
|> :erlang.term_to_binary()
|
|> :erlang.term_to_binary()
|
||||||
|> MessageEncryptor.encrypt(secret, sign_secret)
|
|> MessageEncryptor.encrypt(secret, sign_secret)
|
||||||
|
|
||||||
{
|
|
||||||
:reply,
|
|
||||||
# Replace the answer with the encrypted answer
|
# Replace the answer with the encrypted answer
|
||||||
%{new_captcha | answer_data: encrypted_captcha_answer},
|
%{new_captcha | answer_data: encrypted_captcha_answer}
|
||||||
state
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc false
|
@doc """
|
||||||
def handle_call({:validate, token, captcha, answer_data}, _from, state) do
|
Ask the configured captcha service to validate the captcha
|
||||||
|
"""
|
||||||
|
def validate(token, captcha, answer_data) do
|
||||||
|
with {:ok, %{at: at, answer_data: answer_md5}} <- validate_answer_data(token, answer_data),
|
||||||
|
:ok <- validate_expiration(at),
|
||||||
|
:ok <- validate_usage(token),
|
||||||
|
:ok <- method().validate(token, captcha, answer_md5),
|
||||||
|
{:ok, _} <- mark_captcha_as_used(token) do
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def enabled?, do: Pleroma.Config.get([__MODULE__, :enabled], false)
|
||||||
|
|
||||||
|
defp seconds_valid, do: Pleroma.Config.get!([__MODULE__, :seconds_valid])
|
||||||
|
|
||||||
|
defp secret_pair(token) do
|
||||||
secret_key_base = Pleroma.Config.get!([Pleroma.Web.Endpoint, :secret_key_base])
|
secret_key_base = Pleroma.Config.get!([Pleroma.Web.Endpoint, :secret_key_base])
|
||||||
secret = KeyGenerator.generate(secret_key_base, token <> "_encrypt")
|
secret = KeyGenerator.generate(secret_key_base, token <> "_encrypt")
|
||||||
sign_secret = KeyGenerator.generate(secret_key_base, token <> "_sign")
|
sign_secret = KeyGenerator.generate(secret_key_base, token <> "_sign")
|
||||||
|
|
||||||
# If the time found is less than (current_time-seconds_valid) then the time has already passed
|
{secret, sign_secret}
|
||||||
# Later we check that the time found is more than the presumed invalidatation time, that means
|
end
|
||||||
# that the data is still valid and the captcha can be checked
|
|
||||||
seconds_valid = Pleroma.Config.get!([Pleroma.Captcha, :seconds_valid])
|
defp validate_answer_data(token, answer_data) do
|
||||||
valid_if_after = DateTime.subtract!(DateTime.now_utc(), seconds_valid)
|
{secret, sign_secret} = secret_pair(token)
|
||||||
|
|
||||||
result =
|
|
||||||
with false <- is_nil(answer_data),
|
with false <- is_nil(answer_data),
|
||||||
{:ok, data} <- MessageEncryptor.decrypt(answer_data, secret, sign_secret),
|
{:ok, data} <- MessageEncryptor.decrypt(answer_data, secret, sign_secret),
|
||||||
%{at: at, answer_data: answer_md5} <- :erlang.binary_to_term(data) do
|
%{at: at, answer_data: answer_md5} <- :erlang.binary_to_term(data) do
|
||||||
try do
|
{:ok, %{at: at, answer_data: answer_md5}}
|
||||||
if DateTime.before?(at, valid_if_after),
|
|
||||||
do: throw({:error, dgettext("errors", "CAPTCHA expired")})
|
|
||||||
|
|
||||||
if not is_nil(Cachex.get!(:used_captcha_cache, token)),
|
|
||||||
do: throw({:error, dgettext("errors", "CAPTCHA already used")})
|
|
||||||
|
|
||||||
res = method().validate(token, captcha, answer_md5)
|
|
||||||
# Throw if an error occurs
|
|
||||||
if res != :ok, do: throw(res)
|
|
||||||
|
|
||||||
# Mark this captcha as used
|
|
||||||
{:ok, _} =
|
|
||||||
Cachex.put(:used_captcha_cache, token, true, ttl: :timer.seconds(seconds_valid))
|
|
||||||
|
|
||||||
:ok
|
|
||||||
catch
|
|
||||||
:throw, e -> e
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
_ -> {:error, dgettext("errors", "Invalid answer data")}
|
_ -> {:error, :invalid_answer_data}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
{:reply, result, state}
|
defp validate_expiration(created_at) do
|
||||||
|
# If the time found is less than (current_time-seconds_valid) then the time has already passed
|
||||||
|
# Later we check that the time found is more than the presumed invalidatation time, that means
|
||||||
|
# that the data is still valid and the captcha can be checked
|
||||||
|
|
||||||
|
valid_if_after = DateTime.subtract!(DateTime.now_utc(), seconds_valid())
|
||||||
|
|
||||||
|
if DateTime.before?(created_at, valid_if_after) do
|
||||||
|
{:error, :expired}
|
||||||
|
else
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp validate_usage(token) do
|
||||||
|
if is_nil(Cachex.get!(:used_captcha_cache, token)) do
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
{:error, :already_used}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp mark_captcha_as_used(token) do
|
||||||
|
ttl = seconds_valid() |> :timer.seconds()
|
||||||
|
Cachex.put(:used_captcha_cache, token, true, ttl: ttl)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp method, do: Pleroma.Config.get!([__MODULE__, :method])
|
defp method, do: Pleroma.Config.get!([__MODULE__, :method])
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Captcha.Kocaptcha do
|
defmodule Pleroma.Captcha.Kocaptcha do
|
||||||
import Pleroma.Web.Gettext
|
|
||||||
alias Pleroma.Captcha.Service
|
alias Pleroma.Captcha.Service
|
||||||
@behaviour Service
|
@behaviour Service
|
||||||
|
|
||||||
@ -13,7 +12,7 @@ defmodule Pleroma.Captcha.Kocaptcha do
|
|||||||
|
|
||||||
case Tesla.get(endpoint <> "/new") do
|
case Tesla.get(endpoint <> "/new") do
|
||||||
{:error, _} ->
|
{:error, _} ->
|
||||||
%{error: dgettext("errors", "Kocaptcha service unavailable")}
|
%{error: :kocaptcha_service_unavailable}
|
||||||
|
|
||||||
{:ok, res} ->
|
{:ok, res} ->
|
||||||
json_resp = Jason.decode!(res.body)
|
json_resp = Jason.decode!(res.body)
|
||||||
@ -33,6 +32,6 @@ defmodule Pleroma.Captcha.Kocaptcha do
|
|||||||
if not is_nil(captcha) and
|
if not is_nil(captcha) and
|
||||||
:crypto.hash(:md5, captcha) |> Base.encode16() == String.upcase(answer_data),
|
:crypto.hash(:md5, captcha) |> Base.encode16() == String.upcase(answer_data),
|
||||||
do: :ok,
|
do: :ok,
|
||||||
else: {:error, dgettext("errors", "Invalid CAPTCHA")}
|
else: {:error, :invalid}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Captcha.Native do
|
defmodule Pleroma.Captcha.Native do
|
||||||
import Pleroma.Web.Gettext
|
|
||||||
alias Pleroma.Captcha.Service
|
alias Pleroma.Captcha.Service
|
||||||
@behaviour Service
|
@behaviour Service
|
||||||
|
|
||||||
@ -11,7 +10,7 @@ defmodule Pleroma.Captcha.Native do
|
|||||||
def new do
|
def new do
|
||||||
case Captcha.get() do
|
case Captcha.get() do
|
||||||
:error ->
|
:error ->
|
||||||
%{error: dgettext("errors", "Captcha error")}
|
%{error: :captcha_error}
|
||||||
|
|
||||||
{:ok, answer_data, img_binary} ->
|
{:ok, answer_data, img_binary} ->
|
||||||
%{
|
%{
|
||||||
@ -25,7 +24,7 @@ defmodule Pleroma.Captcha.Native do
|
|||||||
|
|
||||||
@impl Service
|
@impl Service
|
||||||
def validate(_token, captcha, captcha) when not is_nil(captcha), do: :ok
|
def validate(_token, captcha, captcha) when not is_nil(captcha), do: :ok
|
||||||
def validate(_token, _captcha, _answer), do: {:error, dgettext("errors", "Invalid CAPTCHA")}
|
def validate(_token, _captcha, _answer), do: {:error, :invalid}
|
||||||
|
|
||||||
defp token do
|
defp token do
|
||||||
10
|
10
|
||||||
|
@ -13,8 +13,9 @@ defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlug do
|
|||||||
def init(options), do: options
|
def init(options), do: options
|
||||||
|
|
||||||
defp key_id_from_conn(conn) do
|
defp key_id_from_conn(conn) do
|
||||||
with %{"keyId" => key_id} <- HTTPSignatures.signature_for_conn(conn) do
|
with %{"keyId" => key_id} <- HTTPSignatures.signature_for_conn(conn),
|
||||||
Signature.key_id_to_actor_id(key_id)
|
{:ok, ap_id} <- Signature.key_id_to_actor_id(key_id) do
|
||||||
|
ap_id
|
||||||
else
|
else
|
||||||
_ ->
|
_ ->
|
||||||
nil
|
nil
|
||||||
|
@ -8,6 +8,7 @@ defmodule Pleroma.Signature do
|
|||||||
alias Pleroma.Keys
|
alias Pleroma.Keys
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
alias Pleroma.Web.ActivityPub.ObjectValidators.Types
|
||||||
|
|
||||||
def key_id_to_actor_id(key_id) do
|
def key_id_to_actor_id(key_id) do
|
||||||
uri =
|
uri =
|
||||||
@ -21,12 +22,23 @@ defmodule Pleroma.Signature do
|
|||||||
uri
|
uri
|
||||||
end
|
end
|
||||||
|
|
||||||
URI.to_string(uri)
|
maybe_ap_id = URI.to_string(uri)
|
||||||
|
|
||||||
|
case Types.ObjectID.cast(maybe_ap_id) do
|
||||||
|
{:ok, ap_id} ->
|
||||||
|
{:ok, ap_id}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
case Pleroma.Web.WebFinger.finger(maybe_ap_id) do
|
||||||
|
%{"ap_id" => ap_id} -> {:ok, ap_id}
|
||||||
|
_ -> {:error, maybe_ap_id}
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_public_key(conn) do
|
def fetch_public_key(conn) do
|
||||||
with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn),
|
with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn),
|
||||||
actor_id <- key_id_to_actor_id(kid),
|
{:ok, actor_id} <- key_id_to_actor_id(kid),
|
||||||
{:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
|
{:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
|
||||||
{:ok, public_key}
|
{:ok, public_key}
|
||||||
else
|
else
|
||||||
@ -37,7 +49,7 @@ defmodule Pleroma.Signature do
|
|||||||
|
|
||||||
def refetch_public_key(conn) do
|
def refetch_public_key(conn) do
|
||||||
with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn),
|
with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn),
|
||||||
actor_id <- key_id_to_actor_id(kid),
|
{:ok, actor_id} <- key_id_to_actor_id(kid),
|
||||||
{:ok, _user} <- ActivityPub.make_user_from_ap_id(actor_id),
|
{:ok, _user} <- ActivityPub.make_user_from_ap_id(actor_id),
|
||||||
{:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
|
{:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
|
||||||
{:ok, public_key}
|
{:ok, public_key}
|
||||||
|
@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||||||
A module to handle coding from internal to wire ActivityPub and back.
|
A module to handle coding from internal to wire ActivityPub and back.
|
||||||
"""
|
"""
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
|
alias Pleroma.EarmarkRenderer
|
||||||
alias Pleroma.FollowingRelationship
|
alias Pleroma.FollowingRelationship
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.Object.Containment
|
alias Pleroma.Object.Containment
|
||||||
@ -43,6 +44,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||||||
|> fix_addressing
|
|> fix_addressing
|
||||||
|> fix_summary
|
|> fix_summary
|
||||||
|> fix_type(options)
|
|> fix_type(options)
|
||||||
|
|> fix_content
|
||||||
end
|
end
|
||||||
|
|
||||||
def fix_summary(%{"summary" => nil} = object) do
|
def fix_summary(%{"summary" => nil} = object) do
|
||||||
@ -357,6 +359,18 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||||||
|
|
||||||
def fix_type(object, _), do: object
|
def fix_type(object, _), do: object
|
||||||
|
|
||||||
|
defp fix_content(%{"mediaType" => "text/markdown", "content" => content} = object)
|
||||||
|
when is_binary(content) do
|
||||||
|
html_content =
|
||||||
|
content
|
||||||
|
|> Earmark.as_html!(%Earmark.Options{renderer: EarmarkRenderer})
|
||||||
|
|> Pleroma.HTML.filter_tags()
|
||||||
|
|
||||||
|
Map.merge(object, %{"content" => html_content, "mediaType" => "text/html"})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp fix_content(object), do: object
|
||||||
|
|
||||||
defp mastodon_follow_hack(%{"id" => id, "actor" => follower_id}, followed) do
|
defp mastodon_follow_hack(%{"id" => id, "actor" => follower_id}, followed) do
|
||||||
with true <- id =~ "follows",
|
with true <- id =~ "follows",
|
||||||
%User{local: true} = follower <- User.get_cached_by_ap_id(follower_id),
|
%User{local: true} = follower <- User.get_cached_by_ap_id(follower_id),
|
||||||
@ -1207,18 +1221,24 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||||||
|
|
||||||
def prepare_attachments(object) do
|
def prepare_attachments(object) do
|
||||||
attachments =
|
attachments =
|
||||||
(object["attachment"] || [])
|
object
|
||||||
|
|> Map.get("attachment", [])
|
||||||
|> Enum.map(fn data ->
|
|> Enum.map(fn data ->
|
||||||
[%{"mediaType" => media_type, "href" => href} | _] = data["url"]
|
[%{"mediaType" => media_type, "href" => href} | _] = data["url"]
|
||||||
%{"url" => href, "mediaType" => media_type, "name" => data["name"], "type" => "Document"}
|
|
||||||
|
%{
|
||||||
|
"url" => href,
|
||||||
|
"mediaType" => media_type,
|
||||||
|
"name" => data["name"],
|
||||||
|
"type" => "Document"
|
||||||
|
}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
Map.put(object, "attachment", attachments)
|
Map.put(object, "attachment", attachments)
|
||||||
end
|
end
|
||||||
|
|
||||||
def strip_internal_fields(object) do
|
def strip_internal_fields(object) do
|
||||||
object
|
Map.drop(object, Pleroma.Constants.object_internal_fields())
|
||||||
|> Map.drop(Pleroma.Constants.object_internal_fields())
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp strip_internal_tags(%{"tag" => tags} = object) do
|
defp strip_internal_tags(%{"tag" => tags} = object) do
|
||||||
|
@ -41,9 +41,17 @@ defmodule Pleroma.Web.ApiSpec.Helpers do
|
|||||||
Operation.parameter(
|
Operation.parameter(
|
||||||
:limit,
|
:limit,
|
||||||
:query,
|
:query,
|
||||||
%Schema{type: :integer, default: 20, maximum: 40},
|
%Schema{type: :integer, default: 20},
|
||||||
"Limit"
|
"Maximum number of items to return. Will be ignored if it's more than 40"
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def empty_object_response do
|
||||||
|
Operation.response("Empty object", "application/json", %Schema{type: :object, example: %{}})
|
||||||
|
end
|
||||||
|
|
||||||
|
def empty_array_response do
|
||||||
|
Operation.response("Empty array", "application/json", %Schema{type: :array, example: []})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -344,7 +344,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
|||||||
description: "Not implemented",
|
description: "Not implemented",
|
||||||
security: [%{"oAuth" => ["read:accounts"]}],
|
security: [%{"oAuth" => ["read:accounts"]}],
|
||||||
responses: %{
|
responses: %{
|
||||||
200 => Operation.response("Empry array", "application/json", %Schema{type: :array})
|
200 => empty_array_response()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
@ -356,7 +356,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
|||||||
operationId: "AccountController.identity_proofs",
|
operationId: "AccountController.identity_proofs",
|
||||||
description: "Not implemented",
|
description: "Not implemented",
|
||||||
responses: %{
|
responses: %{
|
||||||
200 => Operation.response("Empry array", "application/json", %Schema{type: :array})
|
200 => empty_array_response()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
defmodule Pleroma.Web.ApiSpec.DomainBlockOperation do
|
defmodule Pleroma.Web.ApiSpec.DomainBlockOperation do
|
||||||
alias OpenApiSpex.Operation
|
alias OpenApiSpex.Operation
|
||||||
alias OpenApiSpex.Schema
|
alias OpenApiSpex.Schema
|
||||||
alias Pleroma.Web.ApiSpec.Helpers
|
import Pleroma.Web.ApiSpec.Helpers
|
||||||
|
|
||||||
def open_api_operation(action) do
|
def open_api_operation(action) do
|
||||||
operation = String.to_existing_atom("#{action}_operation")
|
operation = String.to_existing_atom("#{action}_operation")
|
||||||
@ -46,9 +46,7 @@ defmodule Pleroma.Web.ApiSpec.DomainBlockOperation do
|
|||||||
operationId: "DomainBlockController.create",
|
operationId: "DomainBlockController.create",
|
||||||
requestBody: domain_block_request(),
|
requestBody: domain_block_request(),
|
||||||
security: [%{"oAuth" => ["follow", "write:blocks"]}],
|
security: [%{"oAuth" => ["follow", "write:blocks"]}],
|
||||||
responses: %{
|
responses: %{200 => empty_object_response()}
|
||||||
200 => Operation.response("Empty object", "application/json", %Schema{type: :object})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -67,7 +65,7 @@ defmodule Pleroma.Web.ApiSpec.DomainBlockOperation do
|
|||||||
end
|
end
|
||||||
|
|
||||||
defp domain_block_request do
|
defp domain_block_request do
|
||||||
Helpers.request_body(
|
request_body(
|
||||||
"Parameters",
|
"Parameters",
|
||||||
%Schema{
|
%Schema{
|
||||||
type: :object,
|
type: :object,
|
||||||
|
211
lib/pleroma/web/api_spec/operations/notification_operation.ex
Normal file
211
lib/pleroma/web/api_spec/operations/notification_operation.ex
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
# 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.NotificationOperation do
|
||||||
|
alias OpenApiSpex.Operation
|
||||||
|
alias OpenApiSpex.Operation
|
||||||
|
alias OpenApiSpex.Schema
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.Account
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.Status
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
|
||||||
|
|
||||||
|
import Pleroma.Web.ApiSpec.Helpers
|
||||||
|
|
||||||
|
def open_api_operation(action) do
|
||||||
|
operation = String.to_existing_atom("#{action}_operation")
|
||||||
|
apply(__MODULE__, operation, [])
|
||||||
|
end
|
||||||
|
|
||||||
|
def index_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Notifications"],
|
||||||
|
summary: "Get all notifications",
|
||||||
|
description:
|
||||||
|
"Notifications concerning the user. This API returns Link headers containing links to the next/previous page. However, the links can also be constructed dynamically using query params and `id` values.",
|
||||||
|
operationId: "NotificationController.index",
|
||||||
|
security: [%{"oAuth" => ["read:notifications"]}],
|
||||||
|
parameters:
|
||||||
|
[
|
||||||
|
Operation.parameter(
|
||||||
|
:exclude_types,
|
||||||
|
:query,
|
||||||
|
%Schema{type: :array, items: notification_type()},
|
||||||
|
"Array of types to exclude"
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:account_id,
|
||||||
|
:query,
|
||||||
|
%Schema{type: :string},
|
||||||
|
"Return only notifications received from this account"
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:exclude_visibilities,
|
||||||
|
:query,
|
||||||
|
%Schema{type: :array, items: VisibilityScope},
|
||||||
|
"Exclude the notifications for activities with the given visibilities"
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:include_types,
|
||||||
|
:query,
|
||||||
|
%Schema{type: :array, items: notification_type()},
|
||||||
|
"Include the notifications for activities with the given types"
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:with_muted,
|
||||||
|
:query,
|
||||||
|
BooleanLike,
|
||||||
|
"Include the notifications from muted users"
|
||||||
|
)
|
||||||
|
] ++ pagination_params(),
|
||||||
|
responses: %{
|
||||||
|
200 =>
|
||||||
|
Operation.response("Array of notifications", "application/json", %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: notification()
|
||||||
|
}),
|
||||||
|
404 => Operation.response("Error", "application/json", ApiError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Notifications"],
|
||||||
|
summary: "Get a single notification",
|
||||||
|
description: "View information about a notification with a given ID.",
|
||||||
|
operationId: "NotificationController.show",
|
||||||
|
security: [%{"oAuth" => ["read:notifications"]}],
|
||||||
|
parameters: [id_param()],
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("Notification", "application/json", notification())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def clear_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Notifications"],
|
||||||
|
summary: "Dismiss all notifications",
|
||||||
|
description: "Clear all notifications from the server.",
|
||||||
|
operationId: "NotificationController.clear",
|
||||||
|
security: [%{"oAuth" => ["write:notifications"]}],
|
||||||
|
responses: %{200 => empty_object_response()}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def dismiss_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Notifications"],
|
||||||
|
summary: "Dismiss a single notification",
|
||||||
|
description: "Clear a single notification from the server.",
|
||||||
|
operationId: "NotificationController.dismiss",
|
||||||
|
parameters: [id_param()],
|
||||||
|
security: [%{"oAuth" => ["write:notifications"]}],
|
||||||
|
responses: %{200 => empty_object_response()}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def dismiss_via_body_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Notifications"],
|
||||||
|
summary: "Dismiss a single notification",
|
||||||
|
deprecated: true,
|
||||||
|
description: "Clear a single notification from the server.",
|
||||||
|
operationId: "NotificationController.dismiss_via_body",
|
||||||
|
requestBody:
|
||||||
|
request_body(
|
||||||
|
"Parameters",
|
||||||
|
%Schema{type: :object, properties: %{id: %Schema{type: :string}}},
|
||||||
|
required: true
|
||||||
|
),
|
||||||
|
security: [%{"oAuth" => ["write:notifications"]}],
|
||||||
|
responses: %{200 => empty_object_response()}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy_multiple_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Notifications"],
|
||||||
|
summary: "Dismiss multiple notifications",
|
||||||
|
operationId: "NotificationController.destroy_multiple",
|
||||||
|
security: [%{"oAuth" => ["write:notifications"]}],
|
||||||
|
parameters: [
|
||||||
|
Operation.parameter(
|
||||||
|
:ids,
|
||||||
|
:query,
|
||||||
|
%Schema{type: :array, items: %Schema{type: :string}},
|
||||||
|
"Array of notification IDs to dismiss",
|
||||||
|
required: true
|
||||||
|
)
|
||||||
|
],
|
||||||
|
responses: %{200 => empty_object_response()}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp notification do
|
||||||
|
%Schema{
|
||||||
|
title: "Notification",
|
||||||
|
description: "Response schema for a notification",
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
id: %Schema{type: :string},
|
||||||
|
type: notification_type(),
|
||||||
|
created_at: %Schema{type: :string, format: :"date-time"},
|
||||||
|
account: %Schema{
|
||||||
|
allOf: [Account],
|
||||||
|
description: "The account that performed the action that generated the notification."
|
||||||
|
},
|
||||||
|
status: %Schema{
|
||||||
|
allOf: [Status],
|
||||||
|
description:
|
||||||
|
"Status that was the object of the notification, e.g. in mentions, reblogs, favourites, or polls.",
|
||||||
|
nullable: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
example: %{
|
||||||
|
"id" => "34975861",
|
||||||
|
"type" => "mention",
|
||||||
|
"created_at" => "2019-11-23T07:49:02.064Z",
|
||||||
|
"account" => Account.schema().example,
|
||||||
|
"status" => Status.schema().example
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp notification_type do
|
||||||
|
%Schema{
|
||||||
|
type: :string,
|
||||||
|
enum: [
|
||||||
|
"follow",
|
||||||
|
"favourite",
|
||||||
|
"reblog",
|
||||||
|
"mention",
|
||||||
|
"poll",
|
||||||
|
"pleroma:emoji_reaction",
|
||||||
|
"move",
|
||||||
|
"follow_request"
|
||||||
|
],
|
||||||
|
description: """
|
||||||
|
The type of event that resulted in the notification.
|
||||||
|
|
||||||
|
- `follow` - Someone followed you
|
||||||
|
- `mention` - Someone mentioned you in their status
|
||||||
|
- `reblog` - Someone boosted one of your statuses
|
||||||
|
- `favourite` - Someone favourited one of your statuses
|
||||||
|
- `poll` - A poll you have voted in or created has ended
|
||||||
|
- `move` - Someone moved their account
|
||||||
|
- `pleroma:emoji_reaction` - Someone reacted with emoji to your status
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp id_param do
|
||||||
|
Operation.parameter(:id, :path, :string, "Notification ID",
|
||||||
|
example: "123",
|
||||||
|
required: true
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
78
lib/pleroma/web/api_spec/operations/report_operation.ex
Normal file
78
lib/pleroma/web/api_spec/operations/report_operation.ex
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ApiSpec.ReportOperation do
|
||||||
|
alias OpenApiSpex.Operation
|
||||||
|
alias OpenApiSpex.Schema
|
||||||
|
alias Pleroma.Web.ApiSpec.Helpers
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
||||||
|
|
||||||
|
def open_api_operation(action) do
|
||||||
|
operation = String.to_existing_atom("#{action}_operation")
|
||||||
|
apply(__MODULE__, operation, [])
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["reports"],
|
||||||
|
summary: "File a report",
|
||||||
|
description: "Report problematic users to your moderators",
|
||||||
|
operationId: "ReportController.create",
|
||||||
|
security: [%{"oAuth" => ["follow", "write:reports"]}],
|
||||||
|
requestBody: Helpers.request_body("Parameters", create_request(), required: true),
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("Report", "application/json", create_response()),
|
||||||
|
400 => Operation.response("Report", "application/json", ApiError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp create_request do
|
||||||
|
%Schema{
|
||||||
|
title: "ReportCreateRequest",
|
||||||
|
description: "POST body for creating a report",
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
account_id: %Schema{type: :string, description: "ID of the account to report"},
|
||||||
|
status_ids: %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: %Schema{type: :string},
|
||||||
|
description: "Array of Statuses to attach to the report, for context"
|
||||||
|
},
|
||||||
|
comment: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "Reason for the report"
|
||||||
|
},
|
||||||
|
forward: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
default: false,
|
||||||
|
description:
|
||||||
|
"If the account is remote, should the report be forwarded to the remote admin?"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
required: [:account_id],
|
||||||
|
example: %{
|
||||||
|
"account_id" => "123",
|
||||||
|
"status_ids" => ["1337"],
|
||||||
|
"comment" => "bad status!",
|
||||||
|
"forward" => "false"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp create_response do
|
||||||
|
%Schema{
|
||||||
|
title: "ReportResponse",
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
id: %Schema{type: :string, description: "Report ID"},
|
||||||
|
action_taken: %Schema{type: :boolean, description: "Is action taken?"}
|
||||||
|
},
|
||||||
|
example: %{
|
||||||
|
"id" => "123",
|
||||||
|
"action_taken" => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
@ -382,9 +382,9 @@ defmodule Pleroma.Web.CommonAPI do
|
|||||||
ThreadMute.exists?(user.id, activity.data["context"])
|
ThreadMute.exists?(user.id, activity.data["context"])
|
||||||
end
|
end
|
||||||
|
|
||||||
def report(user, %{"account_id" => account_id} = data) do
|
def report(user, data) do
|
||||||
with {:ok, account} <- get_reported_account(account_id),
|
with {:ok, account} <- get_reported_account(data.account_id),
|
||||||
{:ok, {content_html, _, _}} <- make_report_content_html(data["comment"]),
|
{:ok, {content_html, _, _}} <- make_report_content_html(data[:comment]),
|
||||||
{:ok, statuses} <- get_report_statuses(account, data) do
|
{:ok, statuses} <- get_report_statuses(account, data) do
|
||||||
ActivityPub.flag(%{
|
ActivityPub.flag(%{
|
||||||
context: Utils.generate_context_id(),
|
context: Utils.generate_context_id(),
|
||||||
@ -392,13 +392,11 @@ defmodule Pleroma.Web.CommonAPI do
|
|||||||
account: account,
|
account: account,
|
||||||
statuses: statuses,
|
statuses: statuses,
|
||||||
content: content_html,
|
content: content_html,
|
||||||
forward: data["forward"] || false
|
forward: Map.get(data, :forward, false)
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def report(_user, _params), do: {:error, dgettext("errors", "Valid `account_id` required")}
|
|
||||||
|
|
||||||
defp get_reported_account(account_id) do
|
defp get_reported_account(account_id) do
|
||||||
case User.get_cached_by_id(account_id) do
|
case User.get_cached_by_id(account_id) do
|
||||||
%User{} = account -> {:ok, account}
|
%User{} = account -> {:ok, account}
|
||||||
|
@ -504,7 +504,8 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_report_statuses(%User{ap_id: actor}, %{"status_ids" => status_ids}) do
|
def get_report_statuses(%User{ap_id: actor}, %{status_ids: status_ids})
|
||||||
|
when is_list(status_ids) do
|
||||||
{:ok, Activity.all_by_actor_and_id(actor, status_ids)}
|
{:ok, Activity.all_by_actor_and_id(actor, status_ids)}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -94,24 +94,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||||||
|
|
||||||
@doc "POST /api/v1/accounts"
|
@doc "POST /api/v1/accounts"
|
||||||
def create(%{assigns: %{app: app}, body_params: params} = conn, _params) do
|
def create(%{assigns: %{app: app}, body_params: params} = conn, _params) do
|
||||||
params =
|
|
||||||
params
|
|
||||||
|> Map.take([
|
|
||||||
:email,
|
|
||||||
:bio,
|
|
||||||
:captcha_solution,
|
|
||||||
:captcha_token,
|
|
||||||
:captcha_answer_data,
|
|
||||||
:token,
|
|
||||||
:password,
|
|
||||||
:fullname
|
|
||||||
])
|
|
||||||
|> Map.put(:nickname, params.username)
|
|
||||||
|> Map.put(:fullname, Map.get(params, :fullname, params.username))
|
|
||||||
|> Map.put(:confirm, params.password)
|
|
||||||
|> Map.put(:trusted_app, app.trusted)
|
|
||||||
|
|
||||||
with :ok <- validate_email_param(params),
|
with :ok <- validate_email_param(params),
|
||||||
|
:ok <- TwitterAPI.validate_captcha(app, params),
|
||||||
{:ok, user} <- TwitterAPI.register_user(params, need_confirmation: true),
|
{:ok, user} <- TwitterAPI.register_user(params, need_confirmation: true),
|
||||||
{:ok, token} <- Token.create_token(app, user, %{scopes: app.scopes}) do
|
{:ok, token} <- Token.create_token(app, user, %{scopes: app.scopes}) do
|
||||||
json(conn, %{
|
json(conn, %{
|
||||||
@ -121,7 +105,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||||||
created_at: Token.Utils.format_created_at(token)
|
created_at: Token.Utils.format_created_at(token)
|
||||||
})
|
})
|
||||||
else
|
else
|
||||||
{:error, errors} -> json_response(conn, :bad_request, errors)
|
{:error, error} -> json_response(conn, :bad_request, %{error: error})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -133,11 +117,11 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||||||
render_error(conn, :forbidden, "Invalid credentials")
|
render_error(conn, :forbidden, "Invalid credentials")
|
||||||
end
|
end
|
||||||
|
|
||||||
defp validate_email_param(%{:email => email}) when not is_nil(email), do: :ok
|
defp validate_email_param(%{email: email}) when not is_nil(email), do: :ok
|
||||||
|
|
||||||
defp validate_email_param(_) do
|
defp validate_email_param(_) do
|
||||||
case Pleroma.Config.get([:instance, :account_activation_required]) do
|
case Pleroma.Config.get([:instance, :account_activation_required]) do
|
||||||
true -> {:error, %{"error" => "Missing parameters"}}
|
true -> {:error, dgettext("errors", "Missing parameter: %{name}", name: "email")}
|
||||||
_ -> :ok
|
_ -> :ok
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -13,6 +13,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
|
|||||||
|
|
||||||
@oauth_read_actions [:show, :index]
|
@oauth_read_actions [:show, :index]
|
||||||
|
|
||||||
|
plug(OpenApiSpex.Plug.CastAndValidate, render_error: Pleroma.Web.ApiSpec.RenderError)
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
OAuthScopesPlug,
|
OAuthScopesPlug,
|
||||||
%{scopes: ["read:notifications"]} when action in @oauth_read_actions
|
%{scopes: ["read:notifications"]} when action in @oauth_read_actions
|
||||||
@ -20,14 +22,16 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
|
|||||||
|
|
||||||
plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action not in @oauth_read_actions)
|
plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action not in @oauth_read_actions)
|
||||||
|
|
||||||
|
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.NotificationOperation
|
||||||
|
|
||||||
# GET /api/v1/notifications
|
# GET /api/v1/notifications
|
||||||
def index(conn, %{"account_id" => account_id} = params) do
|
def index(conn, %{account_id: account_id} = params) do
|
||||||
case Pleroma.User.get_cached_by_id(account_id) do
|
case Pleroma.User.get_cached_by_id(account_id) do
|
||||||
%{ap_id: account_ap_id} ->
|
%{ap_id: account_ap_id} ->
|
||||||
params =
|
params =
|
||||||
params
|
params
|
||||||
|> Map.delete("account_id")
|
|> Map.delete(:account_id)
|
||||||
|> Map.put("account_ap_id", account_ap_id)
|
|> Map.put(:account_ap_id, account_ap_id)
|
||||||
|
|
||||||
index(conn, params)
|
index(conn, params)
|
||||||
|
|
||||||
@ -39,6 +43,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def index(%{assigns: %{user: user}} = conn, params) do
|
def index(%{assigns: %{user: user}} = conn, params) do
|
||||||
|
params = Map.new(params, fn {k, v} -> {to_string(k), v} end)
|
||||||
notifications = MastodonAPI.get_notifications(user, params)
|
notifications = MastodonAPI.get_notifications(user, params)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
@ -51,7 +56,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
|
|||||||
end
|
end
|
||||||
|
|
||||||
# GET /api/v1/notifications/:id
|
# GET /api/v1/notifications/:id
|
||||||
def show(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
def show(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||||
with {:ok, notification} <- Notification.get(user, id) do
|
with {:ok, notification} <- Notification.get(user, id) do
|
||||||
render(conn, "show.json", notification: notification, for: user)
|
render(conn, "show.json", notification: notification, for: user)
|
||||||
else
|
else
|
||||||
@ -69,8 +74,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
|
|||||||
end
|
end
|
||||||
|
|
||||||
# POST /api/v1/notifications/:id/dismiss
|
# POST /api/v1/notifications/:id/dismiss
|
||||||
# POST /api/v1/notifications/dismiss (deprecated)
|
|
||||||
def dismiss(%{assigns: %{user: user}} = conn, %{"id" => id} = _params) do
|
def dismiss(%{assigns: %{user: user}} = conn, %{id: id} = _params) do
|
||||||
with {:ok, _notif} <- Notification.dismiss(user, id) do
|
with {:ok, _notif} <- Notification.dismiss(user, id) do
|
||||||
json(conn, %{})
|
json(conn, %{})
|
||||||
else
|
else
|
||||||
@ -81,8 +86,13 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# POST /api/v1/notifications/dismiss (deprecated)
|
||||||
|
def dismiss_via_body(%{body_params: params} = conn, _) do
|
||||||
|
dismiss(conn, params)
|
||||||
|
end
|
||||||
|
|
||||||
# DELETE /api/v1/notifications/destroy_multiple
|
# DELETE /api/v1/notifications/destroy_multiple
|
||||||
def destroy_multiple(%{assigns: %{user: user}} = conn, %{"ids" => ids} = _params) do
|
def destroy_multiple(%{assigns: %{user: user}} = conn, %{ids: ids} = _params) do
|
||||||
Notification.destroy_multiple(user, ids)
|
Notification.destroy_multiple(user, ids)
|
||||||
json(conn, %{})
|
json(conn, %{})
|
||||||
end
|
end
|
||||||
|
@ -9,10 +9,13 @@ defmodule Pleroma.Web.MastodonAPI.ReportController do
|
|||||||
|
|
||||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
|
|
||||||
|
plug(OpenApiSpex.Plug.CastAndValidate, render_error: Pleroma.Web.ApiSpec.RenderError)
|
||||||
plug(OAuthScopesPlug, %{scopes: ["write:reports"]} when action == :create)
|
plug(OAuthScopesPlug, %{scopes: ["write:reports"]} when action == :create)
|
||||||
|
|
||||||
|
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.ReportOperation
|
||||||
|
|
||||||
@doc "POST /api/v1/reports"
|
@doc "POST /api/v1/reports"
|
||||||
def create(%{assigns: %{user: user}} = conn, params) do
|
def create(%{assigns: %{user: user}, body_params: params} = conn, _) do
|
||||||
with {:ok, activity} <- Pleroma.Web.CommonAPI.report(user, params) do
|
with {:ok, activity} <- Pleroma.Web.CommonAPI.report(user, params) do
|
||||||
render(conn, "show.json", activity: activity)
|
render(conn, "show.json", activity: activity)
|
||||||
end
|
end
|
||||||
|
@ -396,7 +396,7 @@ defmodule Pleroma.Web.Router do
|
|||||||
post("/notifications/clear", NotificationController, :clear)
|
post("/notifications/clear", NotificationController, :clear)
|
||||||
delete("/notifications/destroy_multiple", NotificationController, :destroy_multiple)
|
delete("/notifications/destroy_multiple", NotificationController, :destroy_multiple)
|
||||||
# Deprecated: was removed in Mastodon v3, use `/notifications/:id/dismiss` instead
|
# Deprecated: was removed in Mastodon v3, use `/notifications/:id/dismiss` instead
|
||||||
post("/notifications/dismiss", NotificationController, :dismiss)
|
post("/notifications/dismiss", NotificationController, :dismiss_via_body)
|
||||||
|
|
||||||
post("/polls/:id/votes", PollController, :vote)
|
post("/polls/:id/votes", PollController, :vote)
|
||||||
|
|
||||||
|
@ -3,55 +3,28 @@
|
|||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
||||||
|
import Pleroma.Web.Gettext
|
||||||
|
|
||||||
alias Pleroma.Emails.Mailer
|
alias Pleroma.Emails.Mailer
|
||||||
alias Pleroma.Emails.UserEmail
|
alias Pleroma.Emails.UserEmail
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.UserInviteToken
|
alias Pleroma.UserInviteToken
|
||||||
|
|
||||||
require Pleroma.Constants
|
|
||||||
|
|
||||||
def register_user(params, opts \\ []) do
|
def register_user(params, opts \\ []) do
|
||||||
params =
|
params =
|
||||||
params
|
params
|
||||||
|> Map.take([
|
|> Map.take([:email, :token, :password])
|
||||||
:nickname,
|
|> Map.put(:bio, params |> Map.get(:bio, "") |> User.parse_bio())
|
||||||
:password,
|
|> Map.put(:nickname, params[:username])
|
||||||
:captcha_solution,
|
|> Map.put(:name, Map.get(params, :fullname, params[:username]))
|
||||||
:captcha_token,
|
|> Map.put(:password_confirmation, params[:password])
|
||||||
:captcha_answer_data,
|
|
||||||
:token,
|
|
||||||
:email,
|
|
||||||
:trusted_app
|
|
||||||
])
|
|
||||||
|> Map.put(:bio, User.parse_bio(params[:bio] || ""))
|
|
||||||
|> Map.put(:name, params.fullname)
|
|
||||||
|> Map.put(:password_confirmation, params[:confirm])
|
|
||||||
|
|
||||||
case validate_captcha(params) do
|
|
||||||
:ok ->
|
|
||||||
if Pleroma.Config.get([:instance, :registrations_open]) do
|
if Pleroma.Config.get([:instance, :registrations_open]) do
|
||||||
create_user(params, opts)
|
create_user(params, opts)
|
||||||
else
|
else
|
||||||
create_user_with_invite(params, opts)
|
create_user_with_invite(params, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
{:error, error} ->
|
|
||||||
# I have no idea how this error handling works
|
|
||||||
{:error, %{error: Jason.encode!(%{captcha: [error]})}}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp validate_captcha(params) do
|
|
||||||
if params[:trusted_app] || not Pleroma.Config.get([Pleroma.Captcha, :enabled]) do
|
|
||||||
:ok
|
|
||||||
else
|
|
||||||
Pleroma.Captcha.validate(
|
|
||||||
params.captcha_token,
|
|
||||||
params.captcha_solution,
|
|
||||||
params.captcha_answer_data
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp create_user_with_invite(params, opts) do
|
defp create_user_with_invite(params, opts) do
|
||||||
@ -75,16 +48,17 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
|||||||
|
|
||||||
{:error, changeset} ->
|
{:error, changeset} ->
|
||||||
errors =
|
errors =
|
||||||
Ecto.Changeset.traverse_errors(changeset, fn {msg, _opts} -> msg end)
|
changeset
|
||||||
|
|> Ecto.Changeset.traverse_errors(fn {msg, _opts} -> msg end)
|
||||||
|> Jason.encode!()
|
|> Jason.encode!()
|
||||||
|
|
||||||
{:error, %{error: errors}}
|
{:error, errors}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def password_reset(nickname_or_email) do
|
def password_reset(nickname_or_email) do
|
||||||
with true <- is_binary(nickname_or_email),
|
with true <- is_binary(nickname_or_email),
|
||||||
%User{local: true, email: email} = user when not is_nil(email) <-
|
%User{local: true, email: email} = user when is_binary(email) <-
|
||||||
User.get_by_nickname_or_email(nickname_or_email),
|
User.get_by_nickname_or_email(nickname_or_email),
|
||||||
{:ok, token_record} <- Pleroma.PasswordResetToken.create_token(user) do
|
{:ok, token_record} <- Pleroma.PasswordResetToken.create_token(user) do
|
||||||
user
|
user
|
||||||
@ -106,4 +80,58 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
|||||||
{:error, "unknown user"}
|
{:error, "unknown user"}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def validate_captcha(app, params) do
|
||||||
|
if app.trusted || not Pleroma.Captcha.enabled?() do
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
do_validate_captcha(params)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp do_validate_captcha(params) do
|
||||||
|
with :ok <- validate_captcha_presence(params),
|
||||||
|
:ok <-
|
||||||
|
Pleroma.Captcha.validate(
|
||||||
|
params[:captcha_token],
|
||||||
|
params[:captcha_solution],
|
||||||
|
params[:captcha_answer_data]
|
||||||
|
) do
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
{:error, :captcha_error} ->
|
||||||
|
captcha_error(dgettext("errors", "CAPTCHA Error"))
|
||||||
|
|
||||||
|
{:error, :invalid} ->
|
||||||
|
captcha_error(dgettext("errors", "Invalid CAPTCHA"))
|
||||||
|
|
||||||
|
{:error, :kocaptcha_service_unavailable} ->
|
||||||
|
captcha_error(dgettext("errors", "Kocaptcha service unavailable"))
|
||||||
|
|
||||||
|
{:error, :expired} ->
|
||||||
|
captcha_error(dgettext("errors", "CAPTCHA expired"))
|
||||||
|
|
||||||
|
{:error, :already_used} ->
|
||||||
|
captcha_error(dgettext("errors", "CAPTCHA already used"))
|
||||||
|
|
||||||
|
{:error, :invalid_answer_data} ->
|
||||||
|
captcha_error(dgettext("errors", "Invalid answer data"))
|
||||||
|
|
||||||
|
{:error, error} ->
|
||||||
|
captcha_error(error)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp validate_captcha_presence(params) do
|
||||||
|
[:captcha_solution, :captcha_token, :captcha_answer_data]
|
||||||
|
|> Enum.find_value(:ok, fn key ->
|
||||||
|
unless is_binary(params[key]) do
|
||||||
|
error = dgettext("errors", "Invalid CAPTCHA (Missing parameter: %{name})", name: key)
|
||||||
|
{:error, error}
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
# For some reason FE expects error message to be a serialized JSON
|
||||||
|
defp captcha_error(error), do: {:error, Jason.encode!(%{captcha: [error]})}
|
||||||
end
|
end
|
||||||
|
@ -1 +1 @@
|
|||||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link href=/static/css/vendors~app.b2603a50868c68a1c192.css rel=stylesheet><link href=/static/css/app.1055039ce3f2fe4dd110.css rel=stylesheet><link href=/static/fontello.1587147224637.css rel=stylesheet></head><body class=hidden><noscript>To use Pleroma, please enable JavaScript.</noscript><div id=app></div><script type=text/javascript src=/static/js/vendors~app.c5bbd3734647f0cc7eef.js></script><script type=text/javascript src=/static/js/app.def6476e8bc9b214218b.js></script></body></html>
|
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link href=/static/css/vendors~app.18fea621d430000acc27.css rel=stylesheet><link href=/static/css/app.613cef07981cd95ccceb.css rel=stylesheet><link href=/static/fontello.1588344944597.css rel=stylesheet></head><body class=hidden><noscript>To use Pleroma, please enable JavaScript.</noscript><div id=app></div><script type=text/javascript src=/static/js/vendors~app.5b7c43d835cad9e56363.js></script><script type=text/javascript src=/static/js/app.3de9191d7fd30b4bf68c.js></script></body></html>
|
@ -1,108 +0,0 @@
|
|||||||
.with-load-more-footer {
|
|
||||||
padding: 10px;
|
|
||||||
text-align: center;
|
|
||||||
border-top: 1px solid;
|
|
||||||
border-top-color: #222;
|
|
||||||
border-top-color: var(--border, #222);
|
|
||||||
}
|
|
||||||
.with-load-more-footer .error {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
.tab-switcher {
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
.tab-switcher .contents {
|
|
||||||
-ms-flex: 1 0 auto;
|
|
||||||
flex: 1 0 auto;
|
|
||||||
min-height: 0px;
|
|
||||||
}
|
|
||||||
.tab-switcher .contents .hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.tab-switcher .contents.scrollable-tabs {
|
|
||||||
-ms-flex-preferred-size: 0;
|
|
||||||
flex-basis: 0;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
.tab-switcher .tabs {
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
overflow-y: hidden;
|
|
||||||
overflow-x: auto;
|
|
||||||
padding-top: 5px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
.tab-switcher .tabs::after, .tab-switcher .tabs::before {
|
|
||||||
display: block;
|
|
||||||
content: "";
|
|
||||||
-ms-flex: 1 1 auto;
|
|
||||||
flex: 1 1 auto;
|
|
||||||
border-bottom: 1px solid;
|
|
||||||
border-bottom-color: #222;
|
|
||||||
border-bottom-color: var(--border, #222);
|
|
||||||
}
|
|
||||||
.tab-switcher .tabs .tab-wrapper {
|
|
||||||
height: 28px;
|
|
||||||
position: relative;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-ms-flex: 0 0 auto;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
}
|
|
||||||
.tab-switcher .tabs .tab-wrapper .tab {
|
|
||||||
width: 100%;
|
|
||||||
min-width: 1px;
|
|
||||||
position: relative;
|
|
||||||
border-bottom-left-radius: 0;
|
|
||||||
border-bottom-right-radius: 0;
|
|
||||||
padding: 6px 1em;
|
|
||||||
padding-bottom: 99px;
|
|
||||||
margin-bottom: -93px;
|
|
||||||
white-space: nowrap;
|
|
||||||
color: #b9b9ba;
|
|
||||||
color: var(--tabText, #b9b9ba);
|
|
||||||
background-color: #182230;
|
|
||||||
background-color: var(--tab, #182230);
|
|
||||||
}
|
|
||||||
.tab-switcher .tabs .tab-wrapper .tab:not(.active) {
|
|
||||||
z-index: 4;
|
|
||||||
}
|
|
||||||
.tab-switcher .tabs .tab-wrapper .tab:not(.active):hover {
|
|
||||||
z-index: 6;
|
|
||||||
}
|
|
||||||
.tab-switcher .tabs .tab-wrapper .tab.active {
|
|
||||||
background: transparent;
|
|
||||||
z-index: 5;
|
|
||||||
color: #b9b9ba;
|
|
||||||
color: var(--tabActiveText, #b9b9ba);
|
|
||||||
}
|
|
||||||
.tab-switcher .tabs .tab-wrapper .tab img {
|
|
||||||
max-height: 26px;
|
|
||||||
vertical-align: top;
|
|
||||||
margin-top: -5px;
|
|
||||||
}
|
|
||||||
.tab-switcher .tabs .tab-wrapper:not(.active)::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
z-index: 7;
|
|
||||||
border-bottom: 1px solid;
|
|
||||||
border-bottom-color: #222;
|
|
||||||
border-bottom-color: var(--border, #222);
|
|
||||||
}
|
|
||||||
.with-subscription-loading {
|
|
||||||
padding: 10px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.with-subscription-loading .error {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*# sourceMappingURL=app.1055039ce3f2fe4dd110.css.map*/
|
|
@ -1 +0,0 @@
|
|||||||
{"version":3,"sources":["webpack:///./src/hocs/with_load_more/with_load_more.scss","webpack:///./src/components/tab_switcher/tab_switcher.scss","webpack:///./src/hocs/with_subscription/with_subscription.scss"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA,C","file":"static/css/app.1055039ce3f2fe4dd110.css","sourcesContent":[".with-load-more-footer {\n padding: 10px;\n text-align: center;\n border-top: 1px solid;\n border-top-color: #222;\n border-top-color: var(--border, #222);\n}\n.with-load-more-footer .error {\n font-size: 14px;\n}",".tab-switcher {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-direction: column;\n flex-direction: column;\n}\n.tab-switcher .contents {\n -ms-flex: 1 0 auto;\n flex: 1 0 auto;\n min-height: 0px;\n}\n.tab-switcher .contents .hidden {\n display: none;\n}\n.tab-switcher .contents.scrollable-tabs {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n overflow-y: auto;\n}\n.tab-switcher .tabs {\n display: -ms-flexbox;\n display: flex;\n position: relative;\n width: 100%;\n overflow-y: hidden;\n overflow-x: auto;\n padding-top: 5px;\n box-sizing: border-box;\n}\n.tab-switcher .tabs::after, .tab-switcher .tabs::before {\n display: block;\n content: \"\";\n -ms-flex: 1 1 auto;\n flex: 1 1 auto;\n border-bottom: 1px solid;\n border-bottom-color: #222;\n border-bottom-color: var(--border, #222);\n}\n.tab-switcher .tabs .tab-wrapper {\n height: 28px;\n position: relative;\n display: -ms-flexbox;\n display: flex;\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n}\n.tab-switcher .tabs .tab-wrapper .tab {\n width: 100%;\n min-width: 1px;\n position: relative;\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n padding: 6px 1em;\n padding-bottom: 99px;\n margin-bottom: -93px;\n white-space: nowrap;\n color: #b9b9ba;\n color: var(--tabText, #b9b9ba);\n background-color: #182230;\n background-color: var(--tab, #182230);\n}\n.tab-switcher .tabs .tab-wrapper .tab:not(.active) {\n z-index: 4;\n}\n.tab-switcher .tabs .tab-wrapper .tab:not(.active):hover {\n z-index: 6;\n}\n.tab-switcher .tabs .tab-wrapper .tab.active {\n background: transparent;\n z-index: 5;\n color: #b9b9ba;\n color: var(--tabActiveText, #b9b9ba);\n}\n.tab-switcher .tabs .tab-wrapper .tab img {\n max-height: 26px;\n vertical-align: top;\n margin-top: -5px;\n}\n.tab-switcher .tabs .tab-wrapper:not(.active)::after {\n content: \"\";\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 7;\n border-bottom: 1px solid;\n border-bottom-color: #222;\n border-bottom-color: var(--border, #222);\n}",".with-subscription-loading {\n padding: 10px;\n text-align: center;\n}\n.with-subscription-loading .error {\n font-size: 14px;\n}"],"sourceRoot":""}
|
|
5
priv/static/static/css/app.613cef07981cd95ccceb.css
Normal file
5
priv/static/static/css/app.613cef07981cd95ccceb.css
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.with-load-more-footer{padding:10px;text-align:center;border-top:1px solid;border-top-color:#222;border-top-color:var(--border, #222)}.with-load-more-footer .error{font-size:14px}
|
||||||
|
.tab-switcher{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.tab-switcher .contents{-ms-flex:1 0 auto;flex:1 0 auto;min-height:0px}.tab-switcher .contents .hidden{display:none}.tab-switcher .contents.scrollable-tabs{-ms-flex-preferred-size:0;flex-basis:0;overflow-y:auto}.tab-switcher .tabs{display:-ms-flexbox;display:flex;position:relative;width:100%;overflow-y:hidden;overflow-x:auto;padding-top:5px;box-sizing:border-box}.tab-switcher .tabs::after,.tab-switcher .tabs::before{display:block;content:"";-ms-flex:1 1 auto;flex:1 1 auto;border-bottom:1px solid;border-bottom-color:#222;border-bottom-color:var(--border, #222)}.tab-switcher .tabs .tab-wrapper{height:28px;position:relative;display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto}.tab-switcher .tabs .tab-wrapper .tab{width:100%;min-width:1px;position:relative;border-bottom-left-radius:0;border-bottom-right-radius:0;padding:6px 1em;padding-bottom:99px;margin-bottom:-93px;white-space:nowrap;color:#b9b9ba;color:var(--tabText, #b9b9ba);background-color:#182230;background-color:var(--tab, #182230)}.tab-switcher .tabs .tab-wrapper .tab:not(.active){z-index:4}.tab-switcher .tabs .tab-wrapper .tab:not(.active):hover{z-index:6}.tab-switcher .tabs .tab-wrapper .tab.active{background:transparent;z-index:5;color:#b9b9ba;color:var(--tabActiveText, #b9b9ba)}.tab-switcher .tabs .tab-wrapper .tab img{max-height:26px;vertical-align:top;margin-top:-5px}.tab-switcher .tabs .tab-wrapper:not(.active)::after{content:"";position:absolute;left:0;right:0;bottom:0;z-index:7;border-bottom:1px solid;border-bottom-color:#222;border-bottom-color:var(--border, #222)}
|
||||||
|
.with-subscription-loading{padding:10px;text-align:center}.with-subscription-loading .error{font-size:14px}
|
||||||
|
|
||||||
|
/*# sourceMappingURL=app.613cef07981cd95ccceb.css.map*/
|
1
priv/static/static/css/app.613cef07981cd95ccceb.css.map
Normal file
1
priv/static/static/css/app.613cef07981cd95ccceb.css.map
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["webpack:///./src/hocs/with_load_more/with_load_more.scss","webpack:///./src/components/tab_switcher/tab_switcher.scss","webpack:///./src/hocs/with_subscription/with_subscription.scss"],"names":[],"mappings":"AAAA,uBAAuB,aAAa,kBAAkB,qBAAqB,sBAAsB,qCAAqC,8BAA8B,e;ACApK,cAAc,oBAAoB,aAAa,0BAA0B,sBAAsB,wBAAwB,kBAAkB,cAAc,eAAe,gCAAgC,aAAa,wCAAwC,0BAA0B,aAAa,gBAAgB,oBAAoB,oBAAoB,aAAa,kBAAkB,WAAW,kBAAkB,gBAAgB,gBAAgB,sBAAsB,uDAAuD,cAAc,WAAW,kBAAkB,cAAc,wBAAwB,yBAAyB,wCAAwC,iCAAiC,YAAY,kBAAkB,oBAAoB,aAAa,kBAAkB,cAAc,sCAAsC,WAAW,cAAc,kBAAkB,4BAA4B,6BAA6B,gBAAgB,oBAAoB,oBAAoB,mBAAmB,cAAc,8BAA8B,yBAAyB,qCAAqC,mDAAmD,UAAU,yDAAyD,UAAU,6CAA6C,uBAAuB,UAAU,cAAc,oCAAoC,0CAA0C,gBAAgB,mBAAmB,gBAAgB,qDAAqD,WAAW,kBAAkB,OAAO,QAAQ,SAAS,UAAU,wBAAwB,yBAAyB,wC;ACAtlD,2BAA2B,aAAa,kBAAkB,kCAAkC,e","file":"static/css/app.613cef07981cd95ccceb.css","sourcesContent":[".with-load-more-footer{padding:10px;text-align:center;border-top:1px solid;border-top-color:#222;border-top-color:var(--border, #222)}.with-load-more-footer .error{font-size:14px}",".tab-switcher{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.tab-switcher .contents{-ms-flex:1 0 auto;flex:1 0 auto;min-height:0px}.tab-switcher .contents .hidden{display:none}.tab-switcher .contents.scrollable-tabs{-ms-flex-preferred-size:0;flex-basis:0;overflow-y:auto}.tab-switcher .tabs{display:-ms-flexbox;display:flex;position:relative;width:100%;overflow-y:hidden;overflow-x:auto;padding-top:5px;box-sizing:border-box}.tab-switcher .tabs::after,.tab-switcher .tabs::before{display:block;content:\"\";-ms-flex:1 1 auto;flex:1 1 auto;border-bottom:1px solid;border-bottom-color:#222;border-bottom-color:var(--border, #222)}.tab-switcher .tabs .tab-wrapper{height:28px;position:relative;display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto}.tab-switcher .tabs .tab-wrapper .tab{width:100%;min-width:1px;position:relative;border-bottom-left-radius:0;border-bottom-right-radius:0;padding:6px 1em;padding-bottom:99px;margin-bottom:-93px;white-space:nowrap;color:#b9b9ba;color:var(--tabText, #b9b9ba);background-color:#182230;background-color:var(--tab, #182230)}.tab-switcher .tabs .tab-wrapper .tab:not(.active){z-index:4}.tab-switcher .tabs .tab-wrapper .tab:not(.active):hover{z-index:6}.tab-switcher .tabs .tab-wrapper .tab.active{background:transparent;z-index:5;color:#b9b9ba;color:var(--tabActiveText, #b9b9ba)}.tab-switcher .tabs .tab-wrapper .tab img{max-height:26px;vertical-align:top;margin-top:-5px}.tab-switcher .tabs .tab-wrapper:not(.active)::after{content:\"\";position:absolute;left:0;right:0;bottom:0;z-index:7;border-bottom:1px solid;border-bottom-color:#222;border-bottom-color:var(--border, #222)}",".with-subscription-loading{padding:10px;text-align:center}.with-subscription-loading .error{font-size:14px}"],"sourceRoot":""}
|
@ -1,11 +1,11 @@
|
|||||||
/*!
|
/*!
|
||||||
* Cropper.js v1.4.3
|
* Cropper.js v1.5.6
|
||||||
* https://fengyuanchen.github.io/cropperjs
|
* https://fengyuanchen.github.io/cropperjs
|
||||||
*
|
*
|
||||||
* Copyright 2015-present Chen Fengyuan
|
* Copyright 2015-present Chen Fengyuan
|
||||||
* Released under the MIT license
|
* Released under the MIT license
|
||||||
*
|
*
|
||||||
* Date: 2018-10-24T13:07:11.429Z
|
* Date: 2019-10-04T04:33:44.164Z
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.cropper-container {
|
.cropper-container {
|
||||||
@ -16,7 +16,6 @@
|
|||||||
-ms-touch-action: none;
|
-ms-touch-action: none;
|
||||||
touch-action: none;
|
touch-action: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
-ms-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
@ -56,14 +55,14 @@
|
|||||||
|
|
||||||
.cropper-modal {
|
.cropper-modal {
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
opacity: .5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cropper-view-box {
|
.cropper-view-box {
|
||||||
display: block;
|
display: block;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
outline-color: rgba(51, 153, 255, 0.75);
|
|
||||||
outline: 1px solid #39f;
|
outline: 1px solid #39f;
|
||||||
|
outline-color: rgba(51, 153, 255, 0.75);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@ -71,7 +70,7 @@
|
|||||||
.cropper-dashed {
|
.cropper-dashed {
|
||||||
border: 0 dashed #eee;
|
border: 0 dashed #eee;
|
||||||
display: block;
|
display: block;
|
||||||
opacity: .5;
|
opacity: 0.5;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,28 +96,28 @@
|
|||||||
display: block;
|
display: block;
|
||||||
height: 0;
|
height: 0;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
opacity: .75;
|
opacity: 0.75;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
width: 0;
|
width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cropper-center:before,
|
.cropper-center::before,
|
||||||
.cropper-center:after {
|
.cropper-center::after {
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
content: ' ';
|
content: ' ';
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cropper-center:before {
|
.cropper-center::before {
|
||||||
height: 1px;
|
height: 1px;
|
||||||
left: -3px;
|
left: -3px;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 7px;
|
width: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cropper-center:after {
|
.cropper-center::after {
|
||||||
height: 7px;
|
height: 7px;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: -3px;
|
top: -3px;
|
||||||
@ -130,7 +129,7 @@
|
|||||||
.cropper-point {
|
.cropper-point {
|
||||||
display: block;
|
display: block;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
opacity: .1;
|
opacity: 0.1;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@ -176,7 +175,7 @@
|
|||||||
.cropper-point {
|
.cropper-point {
|
||||||
background-color: #39f;
|
background-color: #39f;
|
||||||
height: 5px;
|
height: 5px;
|
||||||
opacity: .75;
|
opacity: 0.75;
|
||||||
width: 5px;
|
width: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,12 +251,12 @@
|
|||||||
@media (min-width: 1200px) {
|
@media (min-width: 1200px) {
|
||||||
.cropper-point.point-se {
|
.cropper-point.point-se {
|
||||||
height: 5px;
|
height: 5px;
|
||||||
opacity: .75;
|
opacity: 0.75;
|
||||||
width: 5px;
|
width: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cropper-point.point-se:before {
|
.cropper-point.point-se::before {
|
||||||
background-color: #39f;
|
background-color: #39f;
|
||||||
bottom: -50%;
|
bottom: -50%;
|
||||||
content: ' ';
|
content: ' ';
|
||||||
@ -304,4 +303,4 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*# sourceMappingURL=vendors~app.b2603a50868c68a1c192.css.map*/
|
/*# sourceMappingURL=vendors~app.18fea621d430000acc27.css.map*/
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Binary file not shown.
Binary file not shown.
BIN
priv/static/static/font/fontello.1588344944597.woff2
Normal file
BIN
priv/static/static/font/fontello.1588344944597.woff2
Normal file
Binary file not shown.
@ -1,11 +1,11 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Icons";
|
font-family: "Icons";
|
||||||
src: url("./font/fontello.1587147224637.eot");
|
src: url("./font/fontello.1588344944597.eot");
|
||||||
src: url("./font/fontello.1587147224637.eot") format("embedded-opentype"),
|
src: url("./font/fontello.1588344944597.eot") format("embedded-opentype"),
|
||||||
url("./font/fontello.1587147224637.woff2") format("woff2"),
|
url("./font/fontello.1588344944597.woff2") format("woff2"),
|
||||||
url("./font/fontello.1587147224637.woff") format("woff"),
|
url("./font/fontello.1588344944597.woff") format("woff"),
|
||||||
url("./font/fontello.1587147224637.ttf") format("truetype"),
|
url("./font/fontello.1588344944597.ttf") format("truetype"),
|
||||||
url("./font/fontello.1587147224637.svg") format("svg");
|
url("./font/fontello.1588344944597.svg") format("svg");
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
2
priv/static/static/js/2.0bcc7512986083cd9ecf.js
Normal file
2
priv/static/static/js/2.0bcc7512986083cd9ecf.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{584:function(t,e,i){var c=i(585);"string"==typeof c&&(c=[[t.i,c,""]]),c.locals&&(t.exports=c.locals);(0,i(4).default)("2eec4758",c,!0,{})},585:function(t,e,i){(t.exports=i(3)(!1)).push([t.i,".sticker-picker{width:100%}.sticker-picker .contents{min-height:250px}.sticker-picker .contents .sticker-picker-content{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:0 4px}.sticker-picker .contents .sticker-picker-content .sticker{display:-ms-flexbox;display:flex;-ms-flex:1 1 auto;flex:1 1 auto;margin:4px;width:56px;height:56px}.sticker-picker .contents .sticker-picker-content .sticker img{height:100%}.sticker-picker .contents .sticker-picker-content .sticker img:hover{filter:drop-shadow(0 0 5px var(--accent,#d8a070))}",""])},586:function(t,e,i){"use strict";i.r(e);var c=i(90),n={components:{TabSwitcher:i(52).a},data:function(){return{meta:{stickers:[]},path:""}},computed:{pack:function(){return this.$store.state.instance.stickers||[]}},methods:{clear:function(){this.meta={stickers:[]}},pick:function(t,e){var i=this,n=this.$store;fetch(t).then((function(t){t.blob().then((function(t){var a=new File([t],e,{mimetype:"image/png"}),r=new FormData;r.append("file",a),c.a.uploadMedia({store:n,formData:r}).then((function(t){i.$emit("uploaded",t),i.clear()}),(function(t){console.warn("Can't attach sticker"),console.warn(t),i.$emit("upload-failed","default")}))}))}))}}},a=i(0);var r=function(t){i(584)},s=Object(a.a)(n,(function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",{staticClass:"sticker-picker"},[i("tab-switcher",{staticClass:"tab-switcher",attrs:{"render-only-focused":!0,"scrollable-tabs":""}},t._l(t.pack,(function(e){return i("div",{key:e.path,staticClass:"sticker-picker-content",attrs:{"image-tooltip":e.meta.title,image:e.path+e.meta.tabIcon}},t._l(e.meta.stickers,(function(c){return i("div",{key:c,staticClass:"sticker",on:{click:function(i){return i.stopPropagation(),i.preventDefault(),t.pick(e.path+c,e.meta.title)}}},[i("img",{attrs:{src:e.path+c}})])})),0)})),0)],1)}),[],!1,r,null,null);e.default=s.exports}}]);
|
||||||
|
//# sourceMappingURL=2.0bcc7512986083cd9ecf.js.map
|
1
priv/static/static/js/2.0bcc7512986083cd9ecf.js.map
Normal file
1
priv/static/static/js/2.0bcc7512986083cd9ecf.js.map
Normal file
File diff suppressed because one or more lines are too long
@ -1,2 +0,0 @@
|
|||||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{579:function(t,e,i){var c=i(580);"string"==typeof c&&(c=[[t.i,c,""]]),c.locals&&(t.exports=c.locals);(0,i(4).default)("cc6cdea4",c,!0,{})},580:function(t,e,i){(t.exports=i(3)(!1)).push([t.i,".sticker-picker{width:100%}.sticker-picker .contents{min-height:250px}.sticker-picker .contents .sticker-picker-content{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:0 4px}.sticker-picker .contents .sticker-picker-content .sticker{display:-ms-flexbox;display:flex;-ms-flex:1 1 auto;flex:1 1 auto;margin:4px;width:56px;height:56px}.sticker-picker .contents .sticker-picker-content .sticker img{height:100%}.sticker-picker .contents .sticker-picker-content .sticker img:hover{filter:drop-shadow(0 0 5px var(--accent,#d8a070))}",""])},581:function(t,e,i){"use strict";i.r(e);var c=i(89),a={components:{TabSwitcher:i(51).a},data:function(){return{meta:{stickers:[]},path:""}},computed:{pack:function(){return this.$store.state.instance.stickers||[]}},methods:{clear:function(){this.meta={stickers:[]}},pick:function(t,e){var i=this,a=this.$store;fetch(t).then(function(t){t.blob().then(function(t){var n=new File([t],e,{mimetype:"image/png"}),s=new FormData;s.append("file",n),c.a.uploadMedia({store:a,formData:s}).then(function(t){i.$emit("uploaded",t),i.clear()},function(t){console.warn("Can't attach sticker"),console.warn(t),i.$emit("upload-failed","default")})})})}}},n=i(0);var s=function(t){i(579)},r=Object(n.a)(a,function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",{staticClass:"sticker-picker"},[i("tab-switcher",{staticClass:"tab-switcher",attrs:{"render-only-focused":!0,"scrollable-tabs":""}},t._l(t.pack,function(e){return i("div",{key:e.path,staticClass:"sticker-picker-content",attrs:{"image-tooltip":e.meta.title,image:e.path+e.meta.tabIcon}},t._l(e.meta.stickers,function(c){return i("div",{key:c,staticClass:"sticker",on:{click:function(i){i.stopPropagation(),i.preventDefault(),t.pick(e.path+c,e.meta.title)}}},[i("img",{attrs:{src:e.path+c}})])}),0)}),0)],1)},[],!1,s,null,null);e.default=r.exports}}]);
|
|
||||||
//# sourceMappingURL=2.f158cbd2b8770e467dfe.js.map
|
|
File diff suppressed because one or more lines are too long
2
priv/static/static/js/app.3de9191d7fd30b4bf68c.js
Normal file
2
priv/static/static/js/app.3de9191d7fd30b4bf68c.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/static/js/app.3de9191d7fd30b4bf68c.js.map
Normal file
1
priv/static/static/js/app.3de9191d7fd30b4bf68c.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
69
priv/static/static/js/vendors~app.5b7c43d835cad9e56363.js
Normal file
69
priv/static/static/js/vendors~app.5b7c43d835cad9e56363.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,183 +0,0 @@
|
|||||||
body {
|
|
||||||
background-color: #282c37;
|
|
||||||
font-family: sans-serif;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
margin: 50px auto;
|
|
||||||
max-width: 960px;
|
|
||||||
padding: 40px;
|
|
||||||
background-color: #313543;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
margin: 50px auto;
|
|
||||||
max-width: 960px;
|
|
||||||
padding: 40px;
|
|
||||||
background-color: #313543;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.activity {
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 1em;
|
|
||||||
padding-bottom: 2em;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar img {
|
|
||||||
float: left;
|
|
||||||
border-radius: 4px;
|
|
||||||
margin-right: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.activity-content img, video, audio {
|
|
||||||
padding: 1em;
|
|
||||||
max-width: 800px;
|
|
||||||
max-height: 800px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#selected {
|
|
||||||
background-color: #1b2735;
|
|
||||||
}
|
|
||||||
|
|
||||||
.counts dt, .counts dd {
|
|
||||||
float: left;
|
|
||||||
margin-left: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-card {
|
|
||||||
min-height: 48px;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
header a, .h-card a {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
header a:hover, .h-card a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.display-name {
|
|
||||||
padding-top: 4px;
|
|
||||||
display: block;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* keep emoji from being hilariously huge */
|
|
||||||
.display-name img {
|
|
||||||
max-height: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.display-name .nickname {
|
|
||||||
padding-top: 4px;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nickname:hover {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pull-right {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapse {
|
|
||||||
margin: 0;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
color: #9baec8;
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 20px;
|
|
||||||
margin-bottom: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
form {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: 100%;
|
|
||||||
padding: 10px;
|
|
||||||
margin-top: 20px;
|
|
||||||
background-color: rgba(0,0,0,.1);
|
|
||||||
color: white;
|
|
||||||
border: 0;
|
|
||||||
border-bottom: 2px solid #9baec8;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
input:focus {
|
|
||||||
border-bottom: 2px solid #4b8ed8;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"] {
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: 100%;
|
|
||||||
color: white;
|
|
||||||
background-color: #419bdd;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: none;
|
|
||||||
padding: 10px;
|
|
||||||
margin-top: 30px;
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert-danger {
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: 100%;
|
|
||||||
color: #D8000C;
|
|
||||||
background-color: #FFD2D2;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: none;
|
|
||||||
padding: 10px;
|
|
||||||
margin-top: 20px;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert-info {
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: 100%;
|
|
||||||
color: #00529B;
|
|
||||||
background-color: #BDE5F8;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: none;
|
|
||||||
padding: 10px;
|
|
||||||
margin-top: 20px;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.emoji {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
padding: 0;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -61,7 +61,7 @@ defmodule Pleroma.CaptchaTest do
|
|||||||
|
|
||||||
assert is_binary(answer)
|
assert is_binary(answer)
|
||||||
assert :ok = Native.validate(token, answer, answer)
|
assert :ok = Native.validate(token, answer, answer)
|
||||||
assert {:error, "Invalid CAPTCHA"} == Native.validate(token, answer, answer <> "foobar")
|
assert {:error, :invalid} == Native.validate(token, answer, answer <> "foobar")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -78,6 +78,7 @@ defmodule Pleroma.CaptchaTest do
|
|||||||
|
|
||||||
assert is_binary(answer)
|
assert is_binary(answer)
|
||||||
assert :ok = Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", answer)
|
assert :ok = Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", answer)
|
||||||
|
Cachex.del(:used_captcha_cache, token)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "doesn't validate invalid answer" do
|
test "doesn't validate invalid answer" do
|
||||||
@ -92,7 +93,7 @@ defmodule Pleroma.CaptchaTest do
|
|||||||
|
|
||||||
assert is_binary(answer)
|
assert is_binary(answer)
|
||||||
|
|
||||||
assert {:error, "Invalid answer data"} =
|
assert {:error, :invalid_answer_data} =
|
||||||
Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", answer <> "foobar")
|
Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", answer <> "foobar")
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -108,7 +109,7 @@ defmodule Pleroma.CaptchaTest do
|
|||||||
|
|
||||||
assert is_binary(answer)
|
assert is_binary(answer)
|
||||||
|
|
||||||
assert {:error, "Invalid answer data"} =
|
assert {:error, :invalid_answer_data} =
|
||||||
Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", nil)
|
Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", nil)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
112
test/fixtures/tesla_mock/craigmaloney.json
vendored
Normal file
112
test/fixtures/tesla_mock/craigmaloney.json
vendored
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1",
|
||||||
|
{
|
||||||
|
"CacheFile": "pt:CacheFile",
|
||||||
|
"Hashtag": "as:Hashtag",
|
||||||
|
"Infohash": "pt:Infohash",
|
||||||
|
"RsaSignature2017": "https://w3id.org/security#RsaSignature2017",
|
||||||
|
"category": "sc:category",
|
||||||
|
"commentsEnabled": {
|
||||||
|
"@id": "pt:commentsEnabled",
|
||||||
|
"@type": "sc:Boolean"
|
||||||
|
},
|
||||||
|
"downloadEnabled": {
|
||||||
|
"@id": "pt:downloadEnabled",
|
||||||
|
"@type": "sc:Boolean"
|
||||||
|
},
|
||||||
|
"expires": "sc:expires",
|
||||||
|
"fps": {
|
||||||
|
"@id": "pt:fps",
|
||||||
|
"@type": "sc:Number"
|
||||||
|
},
|
||||||
|
"language": "sc:inLanguage",
|
||||||
|
"licence": "sc:license",
|
||||||
|
"originallyPublishedAt": "sc:datePublished",
|
||||||
|
"position": {
|
||||||
|
"@id": "pt:position",
|
||||||
|
"@type": "sc:Number"
|
||||||
|
},
|
||||||
|
"pt": "https://joinpeertube.org/ns#",
|
||||||
|
"sc": "http://schema.org#",
|
||||||
|
"sensitive": "as:sensitive",
|
||||||
|
"size": {
|
||||||
|
"@id": "pt:size",
|
||||||
|
"@type": "sc:Number"
|
||||||
|
},
|
||||||
|
"startTimestamp": {
|
||||||
|
"@id": "pt:startTimestamp",
|
||||||
|
"@type": "sc:Number"
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"@id": "pt:state",
|
||||||
|
"@type": "sc:Number"
|
||||||
|
},
|
||||||
|
"stopTimestamp": {
|
||||||
|
"@id": "pt:stopTimestamp",
|
||||||
|
"@type": "sc:Number"
|
||||||
|
},
|
||||||
|
"subtitleLanguage": "sc:subtitleLanguage",
|
||||||
|
"support": {
|
||||||
|
"@id": "pt:support",
|
||||||
|
"@type": "sc:Text"
|
||||||
|
},
|
||||||
|
"uuid": "sc:identifier",
|
||||||
|
"views": {
|
||||||
|
"@id": "pt:views",
|
||||||
|
"@type": "sc:Number"
|
||||||
|
},
|
||||||
|
"waitTranscoding": {
|
||||||
|
"@id": "pt:waitTranscoding",
|
||||||
|
"@type": "sc:Boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": {
|
||||||
|
"@id": "as:comments",
|
||||||
|
"@type": "@id"
|
||||||
|
},
|
||||||
|
"dislikes": {
|
||||||
|
"@id": "as:dislikes",
|
||||||
|
"@type": "@id"
|
||||||
|
},
|
||||||
|
"likes": {
|
||||||
|
"@id": "as:likes",
|
||||||
|
"@type": "@id"
|
||||||
|
},
|
||||||
|
"playlists": {
|
||||||
|
"@id": "pt:playlists",
|
||||||
|
"@type": "@id"
|
||||||
|
},
|
||||||
|
"shares": {
|
||||||
|
"@id": "as:shares",
|
||||||
|
"@type": "@id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"endpoints": {
|
||||||
|
"sharedInbox": "https://peertube.social/inbox"
|
||||||
|
},
|
||||||
|
"followers": "https://peertube.social/accounts/craigmaloney/followers",
|
||||||
|
"following": "https://peertube.social/accounts/craigmaloney/following",
|
||||||
|
"icon": {
|
||||||
|
"mediaType": "image/png",
|
||||||
|
"type": "Image",
|
||||||
|
"url": "https://peertube.social/lazy-static/avatars/87bd694b-95bc-4066-83f4-bddfcd2b9caa.png"
|
||||||
|
},
|
||||||
|
"id": "https://peertube.social/accounts/craigmaloney",
|
||||||
|
"inbox": "https://peertube.social/accounts/craigmaloney/inbox",
|
||||||
|
"name": "Craig Maloney",
|
||||||
|
"outbox": "https://peertube.social/accounts/craigmaloney/outbox",
|
||||||
|
"playlists": "https://peertube.social/accounts/craigmaloney/playlists",
|
||||||
|
"preferredUsername": "craigmaloney",
|
||||||
|
"publicKey": {
|
||||||
|
"id": "https://peertube.social/accounts/craigmaloney#main-key",
|
||||||
|
"owner": "https://peertube.social/accounts/craigmaloney",
|
||||||
|
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9qvGIYUW01yc8CCsrwxK\n5OXlV5s7EbNWY8tJr/p1oGuELZwAnG2XKxtdbvgcCT+YxL5uRXIdCFIIIKrzRFr/\nHfS0mOgNT9u3gu+SstCNgtatciT0RVP77yiC3b2NHq1NRRvvVhzQb4cpIWObIxqh\nb2ypDClTc7XaKtgmQCbwZlGyZMT+EKz/vustD6BlpGsglRkm7iES6s1PPGb1BU+n\nS94KhbS2DOFiLcXCVWt0QarokIIuKznp4+xP1axKyP+SkT5AHx08Nd5TYFb2C1Jl\nz0WD/1q0mAN62m7QrA3SQPUgB+wWD+S3Nzf7FwNPiP4srbBgxVEUnji/r9mQ6BXC\nrQIDAQAB\n-----END PUBLIC KEY-----"
|
||||||
|
},
|
||||||
|
"summary": null,
|
||||||
|
"type": "Person",
|
||||||
|
"url": "https://peertube.social/accounts/craigmaloney"
|
||||||
|
}
|
234
test/fixtures/tesla_mock/peertube-social.json
vendored
Normal file
234
test/fixtures/tesla_mock/peertube-social.json
vendored
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1",
|
||||||
|
{
|
||||||
|
"CacheFile": "pt:CacheFile",
|
||||||
|
"Hashtag": "as:Hashtag",
|
||||||
|
"Infohash": "pt:Infohash",
|
||||||
|
"RsaSignature2017": "https://w3id.org/security#RsaSignature2017",
|
||||||
|
"category": "sc:category",
|
||||||
|
"commentsEnabled": {
|
||||||
|
"@id": "pt:commentsEnabled",
|
||||||
|
"@type": "sc:Boolean"
|
||||||
|
},
|
||||||
|
"downloadEnabled": {
|
||||||
|
"@id": "pt:downloadEnabled",
|
||||||
|
"@type": "sc:Boolean"
|
||||||
|
},
|
||||||
|
"expires": "sc:expires",
|
||||||
|
"fps": {
|
||||||
|
"@id": "pt:fps",
|
||||||
|
"@type": "sc:Number"
|
||||||
|
},
|
||||||
|
"language": "sc:inLanguage",
|
||||||
|
"licence": "sc:license",
|
||||||
|
"originallyPublishedAt": "sc:datePublished",
|
||||||
|
"position": {
|
||||||
|
"@id": "pt:position",
|
||||||
|
"@type": "sc:Number"
|
||||||
|
},
|
||||||
|
"pt": "https://joinpeertube.org/ns#",
|
||||||
|
"sc": "http://schema.org#",
|
||||||
|
"sensitive": "as:sensitive",
|
||||||
|
"size": {
|
||||||
|
"@id": "pt:size",
|
||||||
|
"@type": "sc:Number"
|
||||||
|
},
|
||||||
|
"startTimestamp": {
|
||||||
|
"@id": "pt:startTimestamp",
|
||||||
|
"@type": "sc:Number"
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"@id": "pt:state",
|
||||||
|
"@type": "sc:Number"
|
||||||
|
},
|
||||||
|
"stopTimestamp": {
|
||||||
|
"@id": "pt:stopTimestamp",
|
||||||
|
"@type": "sc:Number"
|
||||||
|
},
|
||||||
|
"subtitleLanguage": "sc:subtitleLanguage",
|
||||||
|
"support": {
|
||||||
|
"@id": "pt:support",
|
||||||
|
"@type": "sc:Text"
|
||||||
|
},
|
||||||
|
"uuid": "sc:identifier",
|
||||||
|
"views": {
|
||||||
|
"@id": "pt:views",
|
||||||
|
"@type": "sc:Number"
|
||||||
|
},
|
||||||
|
"waitTranscoding": {
|
||||||
|
"@id": "pt:waitTranscoding",
|
||||||
|
"@type": "sc:Boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": {
|
||||||
|
"@id": "as:comments",
|
||||||
|
"@type": "@id"
|
||||||
|
},
|
||||||
|
"dislikes": {
|
||||||
|
"@id": "as:dislikes",
|
||||||
|
"@type": "@id"
|
||||||
|
},
|
||||||
|
"likes": {
|
||||||
|
"@id": "as:likes",
|
||||||
|
"@type": "@id"
|
||||||
|
},
|
||||||
|
"playlists": {
|
||||||
|
"@id": "pt:playlists",
|
||||||
|
"@type": "@id"
|
||||||
|
},
|
||||||
|
"shares": {
|
||||||
|
"@id": "as:shares",
|
||||||
|
"@type": "@id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributedTo": [
|
||||||
|
{
|
||||||
|
"id": "https://peertube.social/accounts/craigmaloney",
|
||||||
|
"type": "Person"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "https://peertube.social/video-channels/9909c7d9-6b5b-4aae-9164-c1af7229c91c",
|
||||||
|
"type": "Group"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"category": {
|
||||||
|
"identifier": "15",
|
||||||
|
"name": "Science & Technology"
|
||||||
|
},
|
||||||
|
"cc": [
|
||||||
|
"https://peertube.social/accounts/craigmaloney/followers"
|
||||||
|
],
|
||||||
|
"comments": "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe/comments",
|
||||||
|
"commentsEnabled": true,
|
||||||
|
"content": "Support this and our other Michigan!/usr/group videos and meetings. Learn more at http://mug.org/membership\n\nTwenty Years in Jail: FreeBSD's Jails, Then and Now\n\nJails started as a limited virtualization system, but over the last two years they've...",
|
||||||
|
"dislikes": "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe/dislikes",
|
||||||
|
"downloadEnabled": true,
|
||||||
|
"duration": "PT5151S",
|
||||||
|
"icon": {
|
||||||
|
"height": 122,
|
||||||
|
"mediaType": "image/jpeg",
|
||||||
|
"type": "Image",
|
||||||
|
"url": "https://peertube.social/static/thumbnails/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe.jpg",
|
||||||
|
"width": 223
|
||||||
|
},
|
||||||
|
"id": "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe",
|
||||||
|
"language": {
|
||||||
|
"identifier": "en",
|
||||||
|
"name": "English"
|
||||||
|
},
|
||||||
|
"licence": {
|
||||||
|
"identifier": "1",
|
||||||
|
"name": "Attribution"
|
||||||
|
},
|
||||||
|
"likes": "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe/likes",
|
||||||
|
"mediaType": "text/markdown",
|
||||||
|
"name": "Twenty Years in Jail: FreeBSD's Jails, Then and Now",
|
||||||
|
"originallyPublishedAt": "2019-08-13T00:00:00.000Z",
|
||||||
|
"published": "2020-02-12T01:06:08.054Z",
|
||||||
|
"sensitive": false,
|
||||||
|
"shares": "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe/announces",
|
||||||
|
"state": 1,
|
||||||
|
"subtitleLanguage": [],
|
||||||
|
"support": "Learn more at http://mug.org",
|
||||||
|
"tag": [
|
||||||
|
{
|
||||||
|
"name": "linux",
|
||||||
|
"type": "Hashtag"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mug.org",
|
||||||
|
"type": "Hashtag"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "open",
|
||||||
|
"type": "Hashtag"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "oss",
|
||||||
|
"type": "Hashtag"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "source",
|
||||||
|
"type": "Hashtag"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"to": [
|
||||||
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
],
|
||||||
|
"type": "Video",
|
||||||
|
"updated": "2020-02-15T15:01:09.474Z",
|
||||||
|
"url": [
|
||||||
|
{
|
||||||
|
"href": "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe",
|
||||||
|
"mediaType": "text/html",
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fps": 30,
|
||||||
|
"height": 240,
|
||||||
|
"href": "https://peertube.social/static/webseed/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-240.mp4",
|
||||||
|
"mediaType": "video/mp4",
|
||||||
|
"size": 119465800,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": 240,
|
||||||
|
"href": "https://peertube.social/static/torrents/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-240.torrent",
|
||||||
|
"mediaType": "application/x-bittorrent",
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": 240,
|
||||||
|
"href": "magnet:?xs=https%3A%2F%2Fpeertube.social%2Fstatic%2Ftorrents%2F278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-240.torrent&xt=urn:btih:b3365331a8543bf48d09add56d7fe4b1cbbb5659&dn=Twenty+Years+in+Jail%3A+FreeBSD's+Jails%2C+Then+and+Now&tr=wss%3A%2F%2Fpeertube.social%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fpeertube.social%2Ftracker%2Fannounce&ws=https%3A%2F%2Fpeertube.social%2Fstatic%2Fwebseed%2F278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-240.mp4",
|
||||||
|
"mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fps": 30,
|
||||||
|
"height": 360,
|
||||||
|
"href": "https://peertube.social/static/webseed/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-360.mp4",
|
||||||
|
"mediaType": "video/mp4",
|
||||||
|
"size": 143930318,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": 360,
|
||||||
|
"href": "https://peertube.social/static/torrents/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-360.torrent",
|
||||||
|
"mediaType": "application/x-bittorrent",
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": 360,
|
||||||
|
"href": "magnet:?xs=https%3A%2F%2Fpeertube.social%2Fstatic%2Ftorrents%2F278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-360.torrent&xt=urn:btih:0d37b23c98cb0d89e28b5dc8f49b3c97a041e569&dn=Twenty+Years+in+Jail%3A+FreeBSD's+Jails%2C+Then+and+Now&tr=wss%3A%2F%2Fpeertube.social%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fpeertube.social%2Ftracker%2Fannounce&ws=https%3A%2F%2Fpeertube.social%2Fstatic%2Fwebseed%2F278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-360.mp4",
|
||||||
|
"mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fps": 30,
|
||||||
|
"height": 480,
|
||||||
|
"href": "https://peertube.social/static/webseed/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-480.mp4",
|
||||||
|
"mediaType": "video/mp4",
|
||||||
|
"size": 130530754,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": 480,
|
||||||
|
"href": "https://peertube.social/static/torrents/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-480.torrent",
|
||||||
|
"mediaType": "application/x-bittorrent",
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": 480,
|
||||||
|
"href": "magnet:?xs=https%3A%2F%2Fpeertube.social%2Fstatic%2Ftorrents%2F278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-480.torrent&xt=urn:btih:3a13ff822ad9494165eff6167183ddaaabc1372a&dn=Twenty+Years+in+Jail%3A+FreeBSD's+Jails%2C+Then+and+Now&tr=wss%3A%2F%2Fpeertube.social%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fpeertube.social%2Ftracker%2Fannounce&ws=https%3A%2F%2Fpeertube.social%2Fstatic%2Fwebseed%2F278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-480.mp4",
|
||||||
|
"mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
|
||||||
|
"type": "Link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"uuid": "278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe",
|
||||||
|
"views": 2,
|
||||||
|
"waitTranscoding": false
|
||||||
|
}
|
@ -44,7 +44,8 @@ defmodule Pleroma.SignatureTest do
|
|||||||
|
|
||||||
test "it returns error when not found user" do
|
test "it returns error when not found user" do
|
||||||
assert capture_log(fn ->
|
assert capture_log(fn ->
|
||||||
assert Signature.fetch_public_key(make_fake_conn("test-ap_id")) == {:error, :error}
|
assert Signature.fetch_public_key(make_fake_conn("https://test-ap-id")) ==
|
||||||
|
{:error, :error}
|
||||||
end) =~ "[error] Could not decode user"
|
end) =~ "[error] Could not decode user"
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -64,7 +65,7 @@ defmodule Pleroma.SignatureTest do
|
|||||||
|
|
||||||
test "it returns error when not found user" do
|
test "it returns error when not found user" do
|
||||||
assert capture_log(fn ->
|
assert capture_log(fn ->
|
||||||
{:error, _} = Signature.refetch_public_key(make_fake_conn("test-ap_id"))
|
{:error, _} = Signature.refetch_public_key(make_fake_conn("https://test-ap_id"))
|
||||||
end) =~ "[error] Could not decode user"
|
end) =~ "[error] Could not decode user"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -100,12 +101,21 @@ defmodule Pleroma.SignatureTest do
|
|||||||
describe "key_id_to_actor_id/1" do
|
describe "key_id_to_actor_id/1" do
|
||||||
test "it properly deduces the actor id for misskey" do
|
test "it properly deduces the actor id for misskey" do
|
||||||
assert Signature.key_id_to_actor_id("https://example.com/users/1234/publickey") ==
|
assert Signature.key_id_to_actor_id("https://example.com/users/1234/publickey") ==
|
||||||
"https://example.com/users/1234"
|
{:ok, "https://example.com/users/1234"}
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it properly deduces the actor id for mastodon and pleroma" do
|
test "it properly deduces the actor id for mastodon and pleroma" do
|
||||||
assert Signature.key_id_to_actor_id("https://example.com/users/1234#main-key") ==
|
assert Signature.key_id_to_actor_id("https://example.com/users/1234#main-key") ==
|
||||||
"https://example.com/users/1234"
|
{:ok, "https://example.com/users/1234"}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it calls webfinger for 'acct:' accounts" do
|
||||||
|
with_mock(Pleroma.Web.WebFinger,
|
||||||
|
finger: fn _ -> %{"ap_id" => "https://gensokyo.2hu/users/raymoo"} end
|
||||||
|
) do
|
||||||
|
assert Signature.key_id_to_actor_id("acct:raymoo@gensokyo.2hu") ==
|
||||||
|
{:ok, "https://gensokyo.2hu/users/raymoo"}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -6,12 +6,16 @@ defmodule Pleroma.Captcha.Mock do
|
|||||||
alias Pleroma.Captcha.Service
|
alias Pleroma.Captcha.Service
|
||||||
@behaviour Service
|
@behaviour Service
|
||||||
|
|
||||||
|
@solution "63615261b77f5354fb8c4e4986477555"
|
||||||
|
|
||||||
|
def solution, do: @solution
|
||||||
|
|
||||||
@impl Service
|
@impl Service
|
||||||
def new,
|
def new,
|
||||||
do: %{
|
do: %{
|
||||||
type: :mock,
|
type: :mock,
|
||||||
token: "afa1815e14e29355e6c8f6b143a39fa2",
|
token: "afa1815e14e29355e6c8f6b143a39fa2",
|
||||||
answer_data: "63615261b77f5354fb8c4e4986477555",
|
answer_data: @solution,
|
||||||
url: "https://example.org/captcha.png"
|
url: "https://example.org/captcha.png"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,6 +308,22 @@ defmodule HttpRequestMock do
|
|||||||
}}
|
}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get("https://peertube.social/accounts/craigmaloney", _, _, _) do
|
||||||
|
{:ok,
|
||||||
|
%Tesla.Env{
|
||||||
|
status: 200,
|
||||||
|
body: File.read!("test/fixtures/tesla_mock/craigmaloney.json")
|
||||||
|
}}
|
||||||
|
end
|
||||||
|
|
||||||
|
def get("https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe", _, _, _) do
|
||||||
|
{:ok,
|
||||||
|
%Tesla.Env{
|
||||||
|
status: 200,
|
||||||
|
body: File.read!("test/fixtures/tesla_mock/peertube-social.json")
|
||||||
|
}}
|
||||||
|
end
|
||||||
|
|
||||||
def get("https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39", _, _, [
|
def get("https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39", _, _, [
|
||||||
{"accept", "application/activity+json"}
|
{"accept", "application/activity+json"}
|
||||||
]) do
|
]) do
|
||||||
|
@ -1221,6 +1221,35 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||||||
:error = Transmogrifier.handle_incoming(data)
|
:error = Transmogrifier.handle_incoming(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "skip converting the content when it is nil" do
|
||||||
|
object_id = "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe"
|
||||||
|
|
||||||
|
{:ok, object} = Fetcher.fetch_and_contain_remote_object_from_id(object_id)
|
||||||
|
|
||||||
|
result =
|
||||||
|
Pleroma.Web.ActivityPub.Transmogrifier.fix_object(Map.merge(object, %{"content" => nil}))
|
||||||
|
|
||||||
|
assert result["content"] == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it converts content of object to html" do
|
||||||
|
object_id = "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe"
|
||||||
|
|
||||||
|
{:ok, %{"content" => content_markdown}} =
|
||||||
|
Fetcher.fetch_and_contain_remote_object_from_id(object_id)
|
||||||
|
|
||||||
|
{:ok, %Pleroma.Object{data: %{"content" => content}} = object} =
|
||||||
|
Fetcher.fetch_object_from_id(object_id)
|
||||||
|
|
||||||
|
assert content_markdown ==
|
||||||
|
"Support this and our other Michigan!/usr/group videos and meetings. Learn more at http://mug.org/membership\n\nTwenty Years in Jail: FreeBSD's Jails, Then and Now\n\nJails started as a limited virtualization system, but over the last two years they've..."
|
||||||
|
|
||||||
|
assert content ==
|
||||||
|
"<p>Support this and our other Michigan!/usr/group videos and meetings. Learn more at <a href=\"http://mug.org/membership\">http://mug.org/membership</a></p><p>Twenty Years in Jail: FreeBSD’s Jails, Then and Now</p><p>Jails started as a limited virtualization system, but over the last two years they’ve…</p>"
|
||||||
|
|
||||||
|
assert object.data["mediaType"] == "text/html"
|
||||||
|
end
|
||||||
|
|
||||||
test "it remaps video URLs as attachments if necessary" do
|
test "it remaps video URLs as attachments if necessary" do
|
||||||
{:ok, object} =
|
{:ok, object} =
|
||||||
Fetcher.fetch_object_from_id(
|
Fetcher.fetch_object_from_id(
|
||||||
|
@ -1347,9 +1347,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||||||
|
|
||||||
{:ok, %{id: report_id}} =
|
{:ok, %{id: report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel offended",
|
comment: "I feel offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
response =
|
response =
|
||||||
@ -1374,16 +1374,16 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||||||
|
|
||||||
{:ok, %{id: report_id}} =
|
{:ok, %{id: report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel offended",
|
comment: "I feel offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
{:ok, %{id: second_report_id}} =
|
{:ok, %{id: second_report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel very offended",
|
comment: "I feel very offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
%{
|
%{
|
||||||
@ -1523,9 +1523,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||||||
|
|
||||||
{:ok, %{id: report_id}} =
|
{:ok, %{id: report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel offended",
|
comment: "I feel offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
response =
|
response =
|
||||||
@ -1547,15 +1547,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||||||
|
|
||||||
{:ok, %{id: first_report_id}} =
|
{:ok, %{id: first_report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel offended",
|
comment: "I feel offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
{:ok, %{id: second_report_id}} =
|
{:ok, %{id: second_report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I don't like this user"
|
comment: "I don't like this user"
|
||||||
})
|
})
|
||||||
|
|
||||||
CommonAPI.update_report_state(second_report_id, "closed")
|
CommonAPI.update_report_state(second_report_id, "closed")
|
||||||
@ -3431,9 +3431,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||||||
|
|
||||||
{:ok, %{id: report_id}} =
|
{:ok, %{id: report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel offended",
|
comment: "I feel offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
post(conn, "/api/pleroma/admin/reports/#{report_id}/notes", %{
|
post(conn, "/api/pleroma/admin/reports/#{report_id}/notes", %{
|
||||||
|
@ -15,7 +15,7 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
|
|||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.report(user, %{"account_id" => other_user.id})
|
{:ok, activity} = CommonAPI.report(user, %{account_id: other_user.id})
|
||||||
|
|
||||||
expected = %{
|
expected = %{
|
||||||
content: nil,
|
content: nil,
|
||||||
@ -48,7 +48,7 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
|
|||||||
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "toot"})
|
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "toot"})
|
||||||
|
|
||||||
{:ok, report_activity} =
|
{:ok, report_activity} =
|
||||||
CommonAPI.report(user, %{"account_id" => other_user.id, "status_ids" => [activity.id]})
|
CommonAPI.report(user, %{account_id: other_user.id, status_ids: [activity.id]})
|
||||||
|
|
||||||
other_user = Pleroma.User.get_by_id(other_user.id)
|
other_user = Pleroma.User.get_by_id(other_user.id)
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
|
|||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.report(user, %{"account_id" => other_user.id})
|
{:ok, activity} = CommonAPI.report(user, %{account_id: other_user.id})
|
||||||
{:ok, activity} = CommonAPI.update_report_state(activity.id, "closed")
|
{:ok, activity} = CommonAPI.update_report_state(activity.id, "closed")
|
||||||
|
|
||||||
assert %{state: "closed"} =
|
assert %{state: "closed"} =
|
||||||
@ -94,8 +94,8 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
|
|||||||
|
|
||||||
{:ok, activity} =
|
{:ok, activity} =
|
||||||
CommonAPI.report(user, %{
|
CommonAPI.report(user, %{
|
||||||
"account_id" => other_user.id,
|
account_id: other_user.id,
|
||||||
"comment" => "posts are too good for this instance"
|
comment: "posts are too good for this instance"
|
||||||
})
|
})
|
||||||
|
|
||||||
assert %{content: "posts are too good for this instance"} =
|
assert %{content: "posts are too good for this instance"} =
|
||||||
@ -108,8 +108,8 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
|
|||||||
|
|
||||||
{:ok, activity} =
|
{:ok, activity} =
|
||||||
CommonAPI.report(user, %{
|
CommonAPI.report(user, %{
|
||||||
"account_id" => other_user.id,
|
account_id: other_user.id,
|
||||||
"comment" => ""
|
comment: ""
|
||||||
})
|
})
|
||||||
|
|
||||||
data = Map.put(activity.data, "content", "<script> alert('hecked :D:D:D:D:D:D:D') </script>")
|
data = Map.put(activity.data, "content", "<script> alert('hecked :D:D:D:D:D:D:D') </script>")
|
||||||
@ -125,8 +125,8 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
|
|||||||
|
|
||||||
{:ok, activity} =
|
{:ok, activity} =
|
||||||
CommonAPI.report(user, %{
|
CommonAPI.report(user, %{
|
||||||
"account_id" => other_user.id,
|
account_id: other_user.id,
|
||||||
"comment" => ""
|
comment: ""
|
||||||
})
|
})
|
||||||
|
|
||||||
Pleroma.User.delete(other_user)
|
Pleroma.User.delete(other_user)
|
||||||
|
@ -485,9 +485,9 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||||||
comment = "foobar"
|
comment = "foobar"
|
||||||
|
|
||||||
report_data = %{
|
report_data = %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => comment,
|
comment: comment,
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
}
|
}
|
||||||
|
|
||||||
note_obj = %{
|
note_obj = %{
|
||||||
@ -517,9 +517,9 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||||||
|
|
||||||
{:ok, %Activity{id: report_id}} =
|
{:ok, %Activity{id: report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel offended",
|
comment: "I feel offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
{:ok, report} = CommonAPI.update_report_state(report_id, "resolved")
|
{:ok, report} = CommonAPI.update_report_state(report_id, "resolved")
|
||||||
@ -538,9 +538,9 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||||||
|
|
||||||
{:ok, %Activity{id: report_id}} =
|
{:ok, %Activity{id: report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel offended",
|
comment: "I feel offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
assert CommonAPI.update_report_state(report_id, "test") == {:error, "Unsupported state"}
|
assert CommonAPI.update_report_state(report_id, "test") == {:error, "Unsupported state"}
|
||||||
@ -552,16 +552,16 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||||||
|
|
||||||
{:ok, %Activity{id: first_report_id}} =
|
{:ok, %Activity{id: first_report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel offended",
|
comment: "I feel offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
{:ok, %Activity{id: second_report_id}} =
|
{:ok, %Activity{id: second_report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel very offended!",
|
comment: "I feel very offended!",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
{:ok, report_ids} =
|
{:ok, report_ids} =
|
||||||
|
@ -925,7 +925,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||||||
|> Map.put(:remote_ip, {127, 0, 0, 5})
|
|> Map.put(:remote_ip, {127, 0, 0, 5})
|
||||||
|> post("/api/v1/accounts", Map.delete(valid_params, :email))
|
|> post("/api/v1/accounts", Map.delete(valid_params, :email))
|
||||||
|
|
||||||
assert json_response_and_validate_schema(res, 400) == %{"error" => "Missing parameters"}
|
assert json_response_and_validate_schema(res, 400) ==
|
||||||
|
%{"error" => "Missing parameter: email"}
|
||||||
|
|
||||||
res =
|
res =
|
||||||
conn
|
conn
|
||||||
@ -1093,6 +1094,91 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "create account with enabled captcha" do
|
||||||
|
setup %{conn: conn} do
|
||||||
|
app_token = insert(:oauth_token, user: nil)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_req_header("authorization", "Bearer " <> app_token.token)
|
||||||
|
|> put_req_header("content-type", "multipart/form-data")
|
||||||
|
|
||||||
|
[conn: conn]
|
||||||
|
end
|
||||||
|
|
||||||
|
setup do: clear_config([Pleroma.Captcha, :enabled], true)
|
||||||
|
|
||||||
|
test "creates an account and returns 200 if captcha is valid", %{conn: conn} do
|
||||||
|
%{token: token, answer_data: answer_data} = Pleroma.Captcha.new()
|
||||||
|
|
||||||
|
params = %{
|
||||||
|
username: "lain",
|
||||||
|
email: "lain@example.org",
|
||||||
|
password: "PlzDontHackLain",
|
||||||
|
agreement: true,
|
||||||
|
captcha_solution: Pleroma.Captcha.Mock.solution(),
|
||||||
|
captcha_token: token,
|
||||||
|
captcha_answer_data: answer_data
|
||||||
|
}
|
||||||
|
|
||||||
|
assert %{
|
||||||
|
"access_token" => access_token,
|
||||||
|
"created_at" => _,
|
||||||
|
"scope" => ["read"],
|
||||||
|
"token_type" => "Bearer"
|
||||||
|
} =
|
||||||
|
conn
|
||||||
|
|> post("/api/v1/accounts", params)
|
||||||
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
|
assert Token |> Repo.get_by(token: access_token) |> Repo.preload(:user) |> Map.get(:user)
|
||||||
|
|
||||||
|
Cachex.del(:used_captcha_cache, token)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns 400 if any captcha field is not provided", %{conn: conn} do
|
||||||
|
captcha_fields = [:captcha_solution, :captcha_token, :captcha_answer_data]
|
||||||
|
|
||||||
|
valid_params = %{
|
||||||
|
username: "lain",
|
||||||
|
email: "lain@example.org",
|
||||||
|
password: "PlzDontHackLain",
|
||||||
|
agreement: true,
|
||||||
|
captcha_solution: "xx",
|
||||||
|
captcha_token: "xx",
|
||||||
|
captcha_answer_data: "xx"
|
||||||
|
}
|
||||||
|
|
||||||
|
for field <- captcha_fields do
|
||||||
|
expected = %{
|
||||||
|
"error" => "{\"captcha\":[\"Invalid CAPTCHA (Missing parameter: #{field})\"]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert expected ==
|
||||||
|
conn
|
||||||
|
|> post("/api/v1/accounts", Map.delete(valid_params, field))
|
||||||
|
|> json_response_and_validate_schema(:bad_request)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns an error if captcha is invalid", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
username: "lain",
|
||||||
|
email: "lain@example.org",
|
||||||
|
password: "PlzDontHackLain",
|
||||||
|
agreement: true,
|
||||||
|
captcha_solution: "cofe",
|
||||||
|
captcha_token: "cofe",
|
||||||
|
captcha_answer_data: "cofe"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert %{"error" => "{\"captcha\":[\"Invalid answer data\"]}"} ==
|
||||||
|
conn
|
||||||
|
|> post("/api/v1/accounts", params)
|
||||||
|
|> json_response_and_validate_schema(:bad_request)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "GET /api/v1/accounts/:id/lists - account_lists" do
|
describe "GET /api/v1/accounts/:id/lists - account_lists" do
|
||||||
test "returns lists to which the account belongs" do
|
test "returns lists to which the account belongs" do
|
||||||
%{user: user, conn: conn} = oauth_access(["read:lists"])
|
%{user: user, conn: conn} = oauth_access(["read:lists"])
|
||||||
|
@ -25,7 +25,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
conn
|
conn
|
||||||
|> assign(:user, user)
|
|> assign(:user, user)
|
||||||
|> get("/api/v1/notifications")
|
|> get("/api/v1/notifications")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert Enum.all?(response, fn n ->
|
assert Enum.all?(response, fn n ->
|
||||||
get_in(n, ["account", "pleroma", "relationship"]) == %{}
|
get_in(n, ["account", "pleroma", "relationship"]) == %{}
|
||||||
@ -50,7 +50,9 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
user.ap_id
|
user.ap_id
|
||||||
}\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
|
}\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
|
||||||
|
|
||||||
assert [%{"status" => %{"content" => response}} | _rest] = json_response(conn, 200)
|
assert [%{"status" => %{"content" => response}} | _rest] =
|
||||||
|
json_response_and_validate_schema(conn, 200)
|
||||||
|
|
||||||
assert response == expected_response
|
assert response == expected_response
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -69,7 +71,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
user.ap_id
|
user.ap_id
|
||||||
}\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
|
}\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
|
||||||
|
|
||||||
assert %{"status" => %{"content" => response}} = json_response(conn, 200)
|
assert %{"status" => %{"content" => response}} = json_response_and_validate_schema(conn, 200)
|
||||||
assert response == expected_response
|
assert response == expected_response
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -84,9 +86,10 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|> assign(:user, user)
|
|> assign(:user, user)
|
||||||
|> post("/api/v1/notifications/dismiss", %{"id" => notification.id})
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> post("/api/v1/notifications/dismiss", %{"id" => to_string(notification.id)})
|
||||||
|
|
||||||
assert %{} = json_response(conn, 200)
|
assert %{} = json_response_and_validate_schema(conn, 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "dismissing a single notification" do
|
test "dismissing a single notification" do
|
||||||
@ -102,7 +105,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
|> assign(:user, user)
|
|> assign(:user, user)
|
||||||
|> post("/api/v1/notifications/#{notification.id}/dismiss")
|
|> post("/api/v1/notifications/#{notification.id}/dismiss")
|
||||||
|
|
||||||
assert %{} = json_response(conn, 200)
|
assert %{} = json_response_and_validate_schema(conn, 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "clearing all notifications" do
|
test "clearing all notifications" do
|
||||||
@ -115,11 +118,11 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
|
|
||||||
ret_conn = post(conn, "/api/v1/notifications/clear")
|
ret_conn = post(conn, "/api/v1/notifications/clear")
|
||||||
|
|
||||||
assert %{} = json_response(ret_conn, 200)
|
assert %{} = json_response_and_validate_schema(ret_conn, 200)
|
||||||
|
|
||||||
ret_conn = get(conn, "/api/v1/notifications")
|
ret_conn = get(conn, "/api/v1/notifications")
|
||||||
|
|
||||||
assert all = json_response(ret_conn, 200)
|
assert all = json_response_and_validate_schema(ret_conn, 200)
|
||||||
assert all == []
|
assert all == []
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -143,7 +146,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/notifications?limit=2&min_id=#{notification1_id}")
|
|> get("/api/v1/notifications?limit=2&min_id=#{notification1_id}")
|
||||||
|> json_response(:ok)
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
|
assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
|
||||||
|
|
||||||
@ -151,7 +154,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/notifications?limit=2&since_id=#{notification1_id}")
|
|> get("/api/v1/notifications?limit=2&since_id=#{notification1_id}")
|
||||||
|> json_response(:ok)
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
|
assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
|
||||||
|
|
||||||
@ -159,7 +162,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/notifications?limit=2&max_id=#{notification4_id}")
|
|> get("/api/v1/notifications?limit=2&max_id=#{notification4_id}")
|
||||||
|> json_response(:ok)
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
|
assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
|
||||||
end
|
end
|
||||||
@ -181,36 +184,28 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
{:ok, private_activity} =
|
{:ok, private_activity} =
|
||||||
CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "private"})
|
CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "private"})
|
||||||
|
|
||||||
conn_res =
|
query = params_to_query(%{exclude_visibilities: ["public", "unlisted", "private"]})
|
||||||
get(conn, "/api/v1/notifications", %{
|
conn_res = get(conn, "/api/v1/notifications?" <> query)
|
||||||
exclude_visibilities: ["public", "unlisted", "private"]
|
|
||||||
})
|
|
||||||
|
|
||||||
assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
|
assert [%{"status" => %{"id" => id}}] = json_response_and_validate_schema(conn_res, 200)
|
||||||
assert id == direct_activity.id
|
assert id == direct_activity.id
|
||||||
|
|
||||||
conn_res =
|
query = params_to_query(%{exclude_visibilities: ["public", "unlisted", "direct"]})
|
||||||
get(conn, "/api/v1/notifications", %{
|
conn_res = get(conn, "/api/v1/notifications?" <> query)
|
||||||
exclude_visibilities: ["public", "unlisted", "direct"]
|
|
||||||
})
|
|
||||||
|
|
||||||
assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
|
assert [%{"status" => %{"id" => id}}] = json_response_and_validate_schema(conn_res, 200)
|
||||||
assert id == private_activity.id
|
assert id == private_activity.id
|
||||||
|
|
||||||
conn_res =
|
query = params_to_query(%{exclude_visibilities: ["public", "private", "direct"]})
|
||||||
get(conn, "/api/v1/notifications", %{
|
conn_res = get(conn, "/api/v1/notifications?" <> query)
|
||||||
exclude_visibilities: ["public", "private", "direct"]
|
|
||||||
})
|
|
||||||
|
|
||||||
assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
|
assert [%{"status" => %{"id" => id}}] = json_response_and_validate_schema(conn_res, 200)
|
||||||
assert id == unlisted_activity.id
|
assert id == unlisted_activity.id
|
||||||
|
|
||||||
conn_res =
|
query = params_to_query(%{exclude_visibilities: ["unlisted", "private", "direct"]})
|
||||||
get(conn, "/api/v1/notifications", %{
|
conn_res = get(conn, "/api/v1/notifications?" <> query)
|
||||||
exclude_visibilities: ["unlisted", "private", "direct"]
|
|
||||||
})
|
|
||||||
|
|
||||||
assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
|
assert [%{"status" => %{"id" => id}}] = json_response_and_validate_schema(conn_res, 200)
|
||||||
assert id == public_activity.id
|
assert id == public_activity.id
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -237,8 +232,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
|
|
||||||
activity_ids =
|
activity_ids =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/notifications", %{exclude_visibilities: ["direct"]})
|
|> get("/api/v1/notifications?exclude_visibilities[]=direct")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|> Enum.map(& &1["status"]["id"])
|
|> Enum.map(& &1["status"]["id"])
|
||||||
|
|
||||||
assert public_activity.id in activity_ids
|
assert public_activity.id in activity_ids
|
||||||
@ -248,8 +243,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
|
|
||||||
activity_ids =
|
activity_ids =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/notifications", %{exclude_visibilities: ["unlisted"]})
|
|> get("/api/v1/notifications?exclude_visibilities[]=unlisted")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|> Enum.map(& &1["status"]["id"])
|
|> Enum.map(& &1["status"]["id"])
|
||||||
|
|
||||||
assert public_activity.id in activity_ids
|
assert public_activity.id in activity_ids
|
||||||
@ -259,8 +254,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
|
|
||||||
activity_ids =
|
activity_ids =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/notifications", %{exclude_visibilities: ["private"]})
|
|> get("/api/v1/notifications?exclude_visibilities[]=private")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|> Enum.map(& &1["status"]["id"])
|
|> Enum.map(& &1["status"]["id"])
|
||||||
|
|
||||||
assert public_activity.id in activity_ids
|
assert public_activity.id in activity_ids
|
||||||
@ -270,8 +265,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
|
|
||||||
activity_ids =
|
activity_ids =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/notifications", %{exclude_visibilities: ["public"]})
|
|> get("/api/v1/notifications?exclude_visibilities[]=public")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|> Enum.map(& &1["status"]["id"])
|
|> Enum.map(& &1["status"]["id"])
|
||||||
|
|
||||||
refute public_activity.id in activity_ids
|
refute public_activity.id in activity_ids
|
||||||
@ -295,8 +290,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
|
|
||||||
activity_ids =
|
activity_ids =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/notifications", %{exclude_visibilities: ["unlisted"]})
|
|> get("/api/v1/notifications?exclude_visibilities[]=unlisted")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|> Enum.map(& &1["status"]["id"])
|
|> Enum.map(& &1["status"]["id"])
|
||||||
|
|
||||||
assert public_activity.id in activity_ids
|
assert public_activity.id in activity_ids
|
||||||
@ -319,25 +314,27 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
reblog_notification_id = get_notification_id_by_activity(reblog_activity)
|
reblog_notification_id = get_notification_id_by_activity(reblog_activity)
|
||||||
follow_notification_id = get_notification_id_by_activity(follow_activity)
|
follow_notification_id = get_notification_id_by_activity(follow_activity)
|
||||||
|
|
||||||
conn_res =
|
query = params_to_query(%{exclude_types: ["mention", "favourite", "reblog"]})
|
||||||
get(conn, "/api/v1/notifications", %{exclude_types: ["mention", "favourite", "reblog"]})
|
conn_res = get(conn, "/api/v1/notifications?" <> query)
|
||||||
|
|
||||||
assert [%{"id" => ^follow_notification_id}] = json_response(conn_res, 200)
|
assert [%{"id" => ^follow_notification_id}] = json_response_and_validate_schema(conn_res, 200)
|
||||||
|
|
||||||
conn_res =
|
query = params_to_query(%{exclude_types: ["favourite", "reblog", "follow"]})
|
||||||
get(conn, "/api/v1/notifications", %{exclude_types: ["favourite", "reblog", "follow"]})
|
conn_res = get(conn, "/api/v1/notifications?" <> query)
|
||||||
|
|
||||||
assert [%{"id" => ^mention_notification_id}] = json_response(conn_res, 200)
|
assert [%{"id" => ^mention_notification_id}] =
|
||||||
|
json_response_and_validate_schema(conn_res, 200)
|
||||||
|
|
||||||
conn_res =
|
query = params_to_query(%{exclude_types: ["reblog", "follow", "mention"]})
|
||||||
get(conn, "/api/v1/notifications", %{exclude_types: ["reblog", "follow", "mention"]})
|
conn_res = get(conn, "/api/v1/notifications?" <> query)
|
||||||
|
|
||||||
assert [%{"id" => ^favorite_notification_id}] = json_response(conn_res, 200)
|
assert [%{"id" => ^favorite_notification_id}] =
|
||||||
|
json_response_and_validate_schema(conn_res, 200)
|
||||||
|
|
||||||
conn_res =
|
query = params_to_query(%{exclude_types: ["follow", "mention", "favourite"]})
|
||||||
get(conn, "/api/v1/notifications", %{exclude_types: ["follow", "mention", "favourite"]})
|
conn_res = get(conn, "/api/v1/notifications?" <> query)
|
||||||
|
|
||||||
assert [%{"id" => ^reblog_notification_id}] = json_response(conn_res, 200)
|
assert [%{"id" => ^reblog_notification_id}] = json_response_and_validate_schema(conn_res, 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "filters notifications using include_types" do
|
test "filters notifications using include_types" do
|
||||||
@ -355,32 +352,34 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
reblog_notification_id = get_notification_id_by_activity(reblog_activity)
|
reblog_notification_id = get_notification_id_by_activity(reblog_activity)
|
||||||
follow_notification_id = get_notification_id_by_activity(follow_activity)
|
follow_notification_id = get_notification_id_by_activity(follow_activity)
|
||||||
|
|
||||||
conn_res = get(conn, "/api/v1/notifications", %{include_types: ["follow"]})
|
conn_res = get(conn, "/api/v1/notifications?include_types[]=follow")
|
||||||
|
|
||||||
assert [%{"id" => ^follow_notification_id}] = json_response(conn_res, 200)
|
assert [%{"id" => ^follow_notification_id}] = json_response_and_validate_schema(conn_res, 200)
|
||||||
|
|
||||||
conn_res = get(conn, "/api/v1/notifications", %{include_types: ["mention"]})
|
conn_res = get(conn, "/api/v1/notifications?include_types[]=mention")
|
||||||
|
|
||||||
assert [%{"id" => ^mention_notification_id}] = json_response(conn_res, 200)
|
assert [%{"id" => ^mention_notification_id}] =
|
||||||
|
json_response_and_validate_schema(conn_res, 200)
|
||||||
|
|
||||||
conn_res = get(conn, "/api/v1/notifications", %{include_types: ["favourite"]})
|
conn_res = get(conn, "/api/v1/notifications?include_types[]=favourite")
|
||||||
|
|
||||||
assert [%{"id" => ^favorite_notification_id}] = json_response(conn_res, 200)
|
assert [%{"id" => ^favorite_notification_id}] =
|
||||||
|
json_response_and_validate_schema(conn_res, 200)
|
||||||
|
|
||||||
conn_res = get(conn, "/api/v1/notifications", %{include_types: ["reblog"]})
|
conn_res = get(conn, "/api/v1/notifications?include_types[]=reblog")
|
||||||
|
|
||||||
assert [%{"id" => ^reblog_notification_id}] = json_response(conn_res, 200)
|
assert [%{"id" => ^reblog_notification_id}] = json_response_and_validate_schema(conn_res, 200)
|
||||||
|
|
||||||
result = conn |> get("/api/v1/notifications") |> json_response(200)
|
result = conn |> get("/api/v1/notifications") |> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert length(result) == 4
|
assert length(result) == 4
|
||||||
|
|
||||||
|
query = params_to_query(%{include_types: ["follow", "mention", "favourite", "reblog"]})
|
||||||
|
|
||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/notifications", %{
|
|> get("/api/v1/notifications?" <> query)
|
||||||
include_types: ["follow", "mention", "favourite", "reblog"]
|
|> json_response_and_validate_schema(200)
|
||||||
})
|
|
||||||
|> json_response(200)
|
|
||||||
|
|
||||||
assert length(result) == 4
|
assert length(result) == 4
|
||||||
end
|
end
|
||||||
@ -402,7 +401,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/notifications")
|
|> get("/api/v1/notifications")
|
||||||
|> json_response(:ok)
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
assert [%{"id" => ^notification2_id}, %{"id" => ^notification1_id}] = result
|
assert [%{"id" => ^notification2_id}, %{"id" => ^notification1_id}] = result
|
||||||
|
|
||||||
@ -414,22 +413,19 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
result =
|
result =
|
||||||
conn2
|
conn2
|
||||||
|> get("/api/v1/notifications")
|
|> get("/api/v1/notifications")
|
||||||
|> json_response(:ok)
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
|
assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
|
||||||
|
|
||||||
conn_destroy =
|
query = params_to_query(%{ids: [notification1_id, notification2_id]})
|
||||||
conn
|
conn_destroy = delete(conn, "/api/v1/notifications/destroy_multiple?" <> query)
|
||||||
|> delete("/api/v1/notifications/destroy_multiple", %{
|
|
||||||
"ids" => [notification1_id, notification2_id]
|
|
||||||
})
|
|
||||||
|
|
||||||
assert json_response(conn_destroy, 200) == %{}
|
assert json_response_and_validate_schema(conn_destroy, 200) == %{}
|
||||||
|
|
||||||
result =
|
result =
|
||||||
conn2
|
conn2
|
||||||
|> get("/api/v1/notifications")
|
|> get("/api/v1/notifications")
|
||||||
|> json_response(:ok)
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
|
assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
|
||||||
end
|
end
|
||||||
@ -443,13 +439,13 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
|
|
||||||
ret_conn = get(conn, "/api/v1/notifications")
|
ret_conn = get(conn, "/api/v1/notifications")
|
||||||
|
|
||||||
assert length(json_response(ret_conn, 200)) == 1
|
assert length(json_response_and_validate_schema(ret_conn, 200)) == 1
|
||||||
|
|
||||||
{:ok, _user_relationships} = User.mute(user, user2)
|
{:ok, _user_relationships} = User.mute(user, user2)
|
||||||
|
|
||||||
conn = get(conn, "/api/v1/notifications")
|
conn = get(conn, "/api/v1/notifications")
|
||||||
|
|
||||||
assert json_response(conn, 200) == []
|
assert json_response_and_validate_schema(conn, 200) == []
|
||||||
end
|
end
|
||||||
|
|
||||||
test "see notifications after muting user without notifications" do
|
test "see notifications after muting user without notifications" do
|
||||||
@ -461,13 +457,13 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
|
|
||||||
ret_conn = get(conn, "/api/v1/notifications")
|
ret_conn = get(conn, "/api/v1/notifications")
|
||||||
|
|
||||||
assert length(json_response(ret_conn, 200)) == 1
|
assert length(json_response_and_validate_schema(ret_conn, 200)) == 1
|
||||||
|
|
||||||
{:ok, _user_relationships} = User.mute(user, user2, false)
|
{:ok, _user_relationships} = User.mute(user, user2, false)
|
||||||
|
|
||||||
conn = get(conn, "/api/v1/notifications")
|
conn = get(conn, "/api/v1/notifications")
|
||||||
|
|
||||||
assert length(json_response(conn, 200)) == 1
|
assert length(json_response_and_validate_schema(conn, 200)) == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
test "see notifications after muting user with notifications and with_muted parameter" do
|
test "see notifications after muting user with notifications and with_muted parameter" do
|
||||||
@ -479,13 +475,13 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
|
|
||||||
ret_conn = get(conn, "/api/v1/notifications")
|
ret_conn = get(conn, "/api/v1/notifications")
|
||||||
|
|
||||||
assert length(json_response(ret_conn, 200)) == 1
|
assert length(json_response_and_validate_schema(ret_conn, 200)) == 1
|
||||||
|
|
||||||
{:ok, _user_relationships} = User.mute(user, user2)
|
{:ok, _user_relationships} = User.mute(user, user2)
|
||||||
|
|
||||||
conn = get(conn, "/api/v1/notifications", %{"with_muted" => "true"})
|
conn = get(conn, "/api/v1/notifications?with_muted=true")
|
||||||
|
|
||||||
assert length(json_response(conn, 200)) == 1
|
assert length(json_response_and_validate_schema(conn, 200)) == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag capture_log: true
|
@tag capture_log: true
|
||||||
@ -512,7 +508,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
|
|
||||||
conn = get(conn, "/api/v1/notifications")
|
conn = get(conn, "/api/v1/notifications")
|
||||||
|
|
||||||
assert length(json_response(conn, 200)) == 1
|
assert length(json_response_and_validate_schema(conn, 200)) == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "link headers" do
|
describe "link headers" do
|
||||||
@ -538,10 +534,10 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|> assign(:user, user)
|
|> assign(:user, user)
|
||||||
|> get("/api/v1/notifications", %{media_only: true})
|
|> get("/api/v1/notifications?limit=5")
|
||||||
|
|
||||||
assert [link_header] = get_resp_header(conn, "link")
|
assert [link_header] = get_resp_header(conn, "link")
|
||||||
assert link_header =~ ~r/media_only=true/
|
assert link_header =~ ~r/limit=5/
|
||||||
assert link_header =~ ~r/min_id=#{notification2.id}/
|
assert link_header =~ ~r/min_id=#{notification2.id}/
|
||||||
assert link_header =~ ~r/max_id=#{notification1.id}/
|
assert link_header =~ ~r/max_id=#{notification1.id}/
|
||||||
end
|
end
|
||||||
@ -560,14 +556,14 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
assert [%{"account" => %{"id" => ^account_id}}] =
|
assert [%{"account" => %{"id" => ^account_id}}] =
|
||||||
conn
|
conn
|
||||||
|> assign(:user, user)
|
|> assign(:user, user)
|
||||||
|> get("/api/v1/notifications", %{account_id: account_id})
|
|> get("/api/v1/notifications?account_id=#{account_id}")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert %{"error" => "Account is not found"} =
|
assert %{"error" => "Account is not found"} =
|
||||||
conn
|
conn
|
||||||
|> assign(:user, user)
|
|> assign(:user, user)
|
||||||
|> get("/api/v1/notifications", %{account_id: "cofe"})
|
|> get("/api/v1/notifications?account_id=cofe")
|
||||||
|> json_response(404)
|
|> json_response_and_validate_schema(404)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -577,4 +573,11 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||||||
|> Map.get(:id)
|
|> Map.get(:id)
|
||||||
|> to_string()
|
|> to_string()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp params_to_query(%{} = params) do
|
||||||
|
Enum.map_join(params, "&", fn
|
||||||
|
{k, v} when is_list(v) -> Enum.map_join(v, "&", &"#{k}[]=#{&1}")
|
||||||
|
{k, v} -> k <> "=" <> v
|
||||||
|
end)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -22,8 +22,9 @@ defmodule Pleroma.Web.MastodonAPI.ReportControllerTest do
|
|||||||
test "submit a basic report", %{conn: conn, target_user: target_user} do
|
test "submit a basic report", %{conn: conn, target_user: target_user} do
|
||||||
assert %{"action_taken" => false, "id" => _} =
|
assert %{"action_taken" => false, "id" => _} =
|
||||||
conn
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/v1/reports", %{"account_id" => target_user.id})
|
|> post("/api/v1/reports", %{"account_id" => target_user.id})
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "submit a report with statuses and comment", %{
|
test "submit a report with statuses and comment", %{
|
||||||
@ -33,23 +34,25 @@ defmodule Pleroma.Web.MastodonAPI.ReportControllerTest do
|
|||||||
} do
|
} do
|
||||||
assert %{"action_taken" => false, "id" => _} =
|
assert %{"action_taken" => false, "id" => _} =
|
||||||
conn
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/v1/reports", %{
|
|> post("/api/v1/reports", %{
|
||||||
"account_id" => target_user.id,
|
"account_id" => target_user.id,
|
||||||
"status_ids" => [activity.id],
|
"status_ids" => [activity.id],
|
||||||
"comment" => "bad status!",
|
"comment" => "bad status!",
|
||||||
"forward" => "false"
|
"forward" => "false"
|
||||||
})
|
})
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "account_id is required", %{
|
test "account_id is required", %{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
activity: activity
|
activity: activity
|
||||||
} do
|
} do
|
||||||
assert %{"error" => "Valid `account_id` required"} =
|
assert %{"error" => "Missing field: account_id."} =
|
||||||
conn
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/v1/reports", %{"status_ids" => [activity.id]})
|
|> post("/api/v1/reports", %{"status_ids" => [activity.id]})
|
||||||
|> json_response(400)
|
|> json_response_and_validate_schema(400)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "comment must be up to the size specified in the config", %{
|
test "comment must be up to the size specified in the config", %{
|
||||||
@ -63,17 +66,21 @@ defmodule Pleroma.Web.MastodonAPI.ReportControllerTest do
|
|||||||
|
|
||||||
assert ^error =
|
assert ^error =
|
||||||
conn
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
|
|> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
|
||||||
|> json_response(400)
|
|> json_response_and_validate_schema(400)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns error when account is not exist", %{
|
test "returns error when account is not exist", %{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
activity: activity
|
activity: activity
|
||||||
} do
|
} do
|
||||||
conn = post(conn, "/api/v1/reports", %{"status_ids" => [activity.id], "account_id" => "foo"})
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> post("/api/v1/reports", %{"status_ids" => [activity.id], "account_id" => "foo"})
|
||||||
|
|
||||||
assert json_response(conn, 400) == %{"error" => "Account not found"}
|
assert json_response_and_validate_schema(conn, 400) == %{"error" => "Account not found"}
|
||||||
end
|
end
|
||||||
|
|
||||||
test "doesn't fail if an admin has no email", %{conn: conn, target_user: target_user} do
|
test "doesn't fail if an admin has no email", %{conn: conn, target_user: target_user} do
|
||||||
@ -81,7 +88,8 @@ defmodule Pleroma.Web.MastodonAPI.ReportControllerTest do
|
|||||||
|
|
||||||
assert %{"action_taken" => false, "id" => _} =
|
assert %{"action_taken" => false, "id" => _} =
|
||||||
conn
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/v1/reports", %{"account_id" => target_user.id})
|
|> post("/api/v1/reports", %{"account_id" => target_user.id})
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do
|
defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do
|
||||||
use Pleroma.Web.ConnCase
|
use Pleroma.Web.ConnCase
|
||||||
|
|
||||||
alias Pleroma.Config
|
|
||||||
|
|
||||||
setup do: oauth_access(["read"])
|
setup do: oauth_access(["read"])
|
||||||
|
|
||||||
test "returns empty result", %{conn: conn} do
|
test "returns empty result", %{conn: conn} do
|
||||||
|
@ -18,7 +18,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
|
|
||||||
test "it registers a new user and returns the user." do
|
test "it registers a new user and returns the user." do
|
||||||
data = %{
|
data = %{
|
||||||
:nickname => "lain",
|
:username => "lain",
|
||||||
:email => "lain@wired.jp",
|
:email => "lain@wired.jp",
|
||||||
:fullname => "lain iwakura",
|
:fullname => "lain iwakura",
|
||||||
:password => "bear",
|
:password => "bear",
|
||||||
@ -35,7 +35,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
|
|
||||||
test "it registers a new user with empty string in bio and returns the user." do
|
test "it registers a new user with empty string in bio and returns the user." do
|
||||||
data = %{
|
data = %{
|
||||||
:nickname => "lain",
|
:username => "lain",
|
||||||
:email => "lain@wired.jp",
|
:email => "lain@wired.jp",
|
||||||
:fullname => "lain iwakura",
|
:fullname => "lain iwakura",
|
||||||
:bio => "",
|
:bio => "",
|
||||||
@ -60,7 +60,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
end
|
end
|
||||||
|
|
||||||
data = %{
|
data = %{
|
||||||
:nickname => "lain",
|
:username => "lain",
|
||||||
:email => "lain@wired.jp",
|
:email => "lain@wired.jp",
|
||||||
:fullname => "lain iwakura",
|
:fullname => "lain iwakura",
|
||||||
:bio => "",
|
:bio => "",
|
||||||
@ -87,7 +87,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
|
|
||||||
test "it registers a new user and parses mentions in the bio" do
|
test "it registers a new user and parses mentions in the bio" do
|
||||||
data1 = %{
|
data1 = %{
|
||||||
:nickname => "john",
|
:username => "john",
|
||||||
:email => "john@gmail.com",
|
:email => "john@gmail.com",
|
||||||
:fullname => "John Doe",
|
:fullname => "John Doe",
|
||||||
:bio => "test",
|
:bio => "test",
|
||||||
@ -98,7 +98,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
{:ok, user1} = TwitterAPI.register_user(data1)
|
{:ok, user1} = TwitterAPI.register_user(data1)
|
||||||
|
|
||||||
data2 = %{
|
data2 = %{
|
||||||
:nickname => "lain",
|
:username => "lain",
|
||||||
:email => "lain@wired.jp",
|
:email => "lain@wired.jp",
|
||||||
:fullname => "lain iwakura",
|
:fullname => "lain iwakura",
|
||||||
:bio => "@john test",
|
:bio => "@john test",
|
||||||
@ -123,7 +123,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
{:ok, invite} = UserInviteToken.create_invite()
|
{:ok, invite} = UserInviteToken.create_invite()
|
||||||
|
|
||||||
data = %{
|
data = %{
|
||||||
:nickname => "vinny",
|
:username => "vinny",
|
||||||
:email => "pasta@pizza.vs",
|
:email => "pasta@pizza.vs",
|
||||||
:fullname => "Vinny Vinesauce",
|
:fullname => "Vinny Vinesauce",
|
||||||
:bio => "streamer",
|
:bio => "streamer",
|
||||||
@ -145,7 +145,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
|
|
||||||
test "returns error on invalid token" do
|
test "returns error on invalid token" do
|
||||||
data = %{
|
data = %{
|
||||||
:nickname => "GrimReaper",
|
:username => "GrimReaper",
|
||||||
:email => "death@reapers.afterlife",
|
:email => "death@reapers.afterlife",
|
||||||
:fullname => "Reaper Grim",
|
:fullname => "Reaper Grim",
|
||||||
:bio => "Your time has come",
|
:bio => "Your time has come",
|
||||||
@ -165,7 +165,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
UserInviteToken.update_invite!(invite, used: true)
|
UserInviteToken.update_invite!(invite, used: true)
|
||||||
|
|
||||||
data = %{
|
data = %{
|
||||||
:nickname => "GrimReaper",
|
:username => "GrimReaper",
|
||||||
:email => "death@reapers.afterlife",
|
:email => "death@reapers.afterlife",
|
||||||
:fullname => "Reaper Grim",
|
:fullname => "Reaper Grim",
|
||||||
:bio => "Your time has come",
|
:bio => "Your time has come",
|
||||||
@ -186,7 +186,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
|
|
||||||
setup do
|
setup do
|
||||||
data = %{
|
data = %{
|
||||||
:nickname => "vinny",
|
:username => "vinny",
|
||||||
:email => "pasta@pizza.vs",
|
:email => "pasta@pizza.vs",
|
||||||
:fullname => "Vinny Vinesauce",
|
:fullname => "Vinny Vinesauce",
|
||||||
:bio => "streamer",
|
:bio => "streamer",
|
||||||
@ -250,7 +250,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
UserInviteToken.update_invite!(invite, uses: 99)
|
UserInviteToken.update_invite!(invite, uses: 99)
|
||||||
|
|
||||||
data = %{
|
data = %{
|
||||||
:nickname => "vinny",
|
:username => "vinny",
|
||||||
:email => "pasta@pizza.vs",
|
:email => "pasta@pizza.vs",
|
||||||
:fullname => "Vinny Vinesauce",
|
:fullname => "Vinny Vinesauce",
|
||||||
:bio => "streamer",
|
:bio => "streamer",
|
||||||
@ -269,7 +269,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
AccountView.render("show.json", %{user: fetched_user})
|
AccountView.render("show.json", %{user: fetched_user})
|
||||||
|
|
||||||
data = %{
|
data = %{
|
||||||
:nickname => "GrimReaper",
|
:username => "GrimReaper",
|
||||||
:email => "death@reapers.afterlife",
|
:email => "death@reapers.afterlife",
|
||||||
:fullname => "Reaper Grim",
|
:fullname => "Reaper Grim",
|
||||||
:bio => "Your time has come",
|
:bio => "Your time has come",
|
||||||
@ -292,7 +292,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
{:ok, invite} = UserInviteToken.create_invite(%{expires_at: Date.utc_today(), max_use: 100})
|
{:ok, invite} = UserInviteToken.create_invite(%{expires_at: Date.utc_today(), max_use: 100})
|
||||||
|
|
||||||
data = %{
|
data = %{
|
||||||
:nickname => "vinny",
|
:username => "vinny",
|
||||||
:email => "pasta@pizza.vs",
|
:email => "pasta@pizza.vs",
|
||||||
:fullname => "Vinny Vinesauce",
|
:fullname => "Vinny Vinesauce",
|
||||||
:bio => "streamer",
|
:bio => "streamer",
|
||||||
@ -317,7 +317,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
UserInviteToken.update_invite!(invite, uses: 99)
|
UserInviteToken.update_invite!(invite, uses: 99)
|
||||||
|
|
||||||
data = %{
|
data = %{
|
||||||
:nickname => "vinny",
|
:username => "vinny",
|
||||||
:email => "pasta@pizza.vs",
|
:email => "pasta@pizza.vs",
|
||||||
:fullname => "Vinny Vinesauce",
|
:fullname => "Vinny Vinesauce",
|
||||||
:bio => "streamer",
|
:bio => "streamer",
|
||||||
@ -335,7 +335,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
AccountView.render("show.json", %{user: fetched_user})
|
AccountView.render("show.json", %{user: fetched_user})
|
||||||
|
|
||||||
data = %{
|
data = %{
|
||||||
:nickname => "GrimReaper",
|
:username => "GrimReaper",
|
||||||
:email => "death@reapers.afterlife",
|
:email => "death@reapers.afterlife",
|
||||||
:fullname => "Reaper Grim",
|
:fullname => "Reaper Grim",
|
||||||
:bio => "Your time has come",
|
:bio => "Your time has come",
|
||||||
@ -355,7 +355,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
UserInviteToken.create_invite(%{expires_at: Date.add(Date.utc_today(), -1), max_use: 100})
|
UserInviteToken.create_invite(%{expires_at: Date.add(Date.utc_today(), -1), max_use: 100})
|
||||||
|
|
||||||
data = %{
|
data = %{
|
||||||
:nickname => "GrimReaper",
|
:username => "GrimReaper",
|
||||||
:email => "death@reapers.afterlife",
|
:email => "death@reapers.afterlife",
|
||||||
:fullname => "Reaper Grim",
|
:fullname => "Reaper Grim",
|
||||||
:bio => "Your time has come",
|
:bio => "Your time has come",
|
||||||
@ -377,7 +377,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
UserInviteToken.update_invite!(invite, uses: 100)
|
UserInviteToken.update_invite!(invite, uses: 100)
|
||||||
|
|
||||||
data = %{
|
data = %{
|
||||||
:nickname => "GrimReaper",
|
:username => "GrimReaper",
|
||||||
:email => "death@reapers.afterlife",
|
:email => "death@reapers.afterlife",
|
||||||
:fullname => "Reaper Grim",
|
:fullname => "Reaper Grim",
|
||||||
:bio => "Your time has come",
|
:bio => "Your time has come",
|
||||||
@ -395,16 +395,15 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||||||
|
|
||||||
test "it returns the error on registration problems" do
|
test "it returns the error on registration problems" do
|
||||||
data = %{
|
data = %{
|
||||||
:nickname => "lain",
|
:username => "lain",
|
||||||
:email => "lain@wired.jp",
|
:email => "lain@wired.jp",
|
||||||
:fullname => "lain iwakura",
|
:fullname => "lain iwakura",
|
||||||
:bio => "close the world.",
|
:bio => "close the world."
|
||||||
:password => "bear"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{:error, error_object} = TwitterAPI.register_user(data)
|
{:error, error} = TwitterAPI.register_user(data)
|
||||||
|
|
||||||
assert is_binary(error_object[:error])
|
assert is_binary(error)
|
||||||
refute User.get_cached_by_nickname("lain")
|
refute User.get_cached_by_nickname("lain")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user