Add admin interface to manage instances subscriptions

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2019-12-03 11:29:51 +01:00
parent 0a96d70348
commit 334d66bf5d
141 changed files with 4198 additions and 1923 deletions

View File

@@ -1,12 +1,13 @@
defmodule Mobilizon.ActorsTest do
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
use Mobilizon.DataCase
use Oban.Testing, repo: Mobilizon.Storage.Repo
import Mobilizon.Factory
alias Mobilizon.{Actors, Config, Users}
alias Mobilizon.{Actors, Config, Users, Events, Tombstone}
alias Mobilizon.Actors.{Actor, Bot, Follower, Member}
alias Mobilizon.Events.{Event, Comment}
alias Mobilizon.Media.File, as: FileModel
alias Mobilizon.Service.ActivityPub
alias Mobilizon.Storage.Page
@@ -287,6 +288,12 @@ defmodule Mobilizon.ActorsTest do
test "delete_actor/1 deletes the actor", %{
actor: %Actor{avatar: %{url: avatar_url}, banner: %{url: banner_url}, id: actor_id} = actor
} do
%Event{url: event1_url} = event1 = insert(:event, organizer_actor: actor)
insert(:event, organizer_actor: actor)
%Comment{url: comment1_url} = comment1 = insert(:comment, actor: actor)
insert(:comment, actor: actor)
%URI{path: "/media/" <> avatar_path} = URI.parse(avatar_url)
%URI{path: "/media/" <> banner_path} = URI.parse(banner_url)
@@ -300,8 +307,34 @@ defmodule Mobilizon.ActorsTest do
"/" <> banner_path
)
assert {:ok, %Actor{}} = Actors.delete_actor(actor)
assert_raise Ecto.NoResultsError, fn -> Actors.get_actor!(actor_id) end
assert {:ok, %Oban.Job{}} = Actors.delete_actor(actor)
assert_enqueued(
worker: Mobilizon.Service.Workers.BackgroundWorker,
args: %{"actor_id" => actor.id, "op" => "delete_actor"}
)
assert %{success: 1, failure: 0} == Oban.drain_queue(:background)
assert %Actor{
name: nil,
summary: nil,
suspended: true,
avatar: nil,
banner: nil,
user_id: nil
} = Actors.get_actor(actor_id)
assert {:error, :event_not_found} = Events.get_event(event1.id)
assert %Tombstone{} = Tombstone.find_tombstone(event1_url)
assert %Comment{deleted_at: deleted_at} = Events.get_comment(comment1.id)
refute is_nil(deleted_at)
assert %Tombstone{} = Tombstone.find_tombstone(comment1_url)
refute File.exists?(
Config.get!([MobilizonWeb.Uploaders.Local, :uploads]) <>
"/" <> avatar_path
)
refute File.exists?(
Config.get!([MobilizonWeb.Uploaders.Local, :uploads]) <>

View File

@@ -314,7 +314,10 @@ defmodule Mobilizon.EventsTest do
setup do
actor = insert(:actor)
event = insert(:event, organizer_actor: actor)
event =
insert(:event, organizer_actor: actor, participant_stats: %{creator: 1, participant: 1})
participant = insert(:participant, actor: actor, event: event)
{:ok, participant: participant, event: event, actor: actor}
end
@@ -364,7 +367,8 @@ defmodule Mobilizon.EventsTest do
test "update_participant/2 with invalid data returns error changeset", %{
participant: participant
} do
assert {:error, %Ecto.Changeset{}} = Events.update_participant(participant, @invalid_attrs)
assert {:error, :participant, %Ecto.Changeset{}, %{}} =
Events.update_participant(participant, @invalid_attrs)
end
test "delete_participant/1 deletes the participant", %{participant: participant} do

View File

@@ -171,7 +171,7 @@ defmodule Mobilizon.Service.ActivityPub.ActivityPubTest do
assert update.data["actor"] == actor.url
assert update.data["to"] == [@activity_pub_public_audience]
assert update.data["object"]["id"] == actor.url
assert update.data["object"]["type"] == "Person"
assert update.data["object"]["type"] == :Person
assert update.data["object"]["summary"] == @updated_actor_summary
end

View File

@@ -8,8 +8,8 @@ defmodule Mobilizon.Service.ActivityPub.Converter.ActorTest do
test "valid actor to as" do
data = ActorConverter.model_to_as(%Actor{type: :Person, preferred_username: "test_account"})
assert is_map(data)
assert data["type"] == "Person"
assert data["preferred_username"] == "test_account"
assert data["type"] == :Person
assert data["preferredUsername"] == "test_account"
end
end
@@ -17,12 +17,13 @@ defmodule Mobilizon.Service.ActivityPub.Converter.ActorTest do
test "valid as data to model" do
{:ok, actor} =
ActorConverter.as_to_model_data(%{
"id" => "https://somedomain.tld/users/someone",
"type" => "Person",
"preferredUsername" => "test_account"
})
assert actor["type"] == :Person
assert actor["preferred_username"] == "test_account"
assert actor.type == "Person"
assert actor.preferred_username == "test_account"
end
end
end

View File

@@ -9,10 +9,10 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
use Mobilizon.DataCase
import Mobilizon.Factory
import ExUnit.CaptureLog
alias Mobilizon.Actors
alias Mobilizon.{Actors, Events, Tombstone}
alias Mobilizon.Actors.Actor
alias Mobilizon.Events
alias Mobilizon.Events.{Comment, Event, Participant}
alias Mobilizon.Service.ActivityPub
alias Mobilizon.Service.ActivityPub.{Activity, Utils}
@@ -131,7 +131,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
data
|> Map.put("object", object)
assert ExUnit.CaptureLog.capture_log([level: :warn], fn ->
assert capture_log([level: :warn], fn ->
{:ok, _returned_activity, _entity} = Transmogrifier.handle_incoming(data)
end) =~ "[warn] Parent object is something we don't handle"
end
@@ -145,7 +145,10 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
assert data["id"] ==
"https://framapiaf.org/users/admin/statuses/99512778738411822/activity"
assert data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
assert data["to"] == [
"https://www.w3.org/ns/activitystreams#Public",
"https://framapiaf.org/users/tcit"
]
# assert data["cc"] == [
# "https://framapiaf.org/users/admin/followers",
@@ -466,26 +469,70 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
refute is_nil(Events.get_comment_from_url(comment_url).deleted_at)
end
# TODO : make me ASAP
# test "it fails for incoming deletes with spoofed origin" do
# activity = insert(:note_activity)
test "it fails for incoming deletes with spoofed origin" do
comment = insert(:comment)
# data =
# File.read!("test/fixtures/mastodon-delete.json")
# |> Jason.decode!()
announce_data =
File.read!("test/fixtures/mastodon-announce.json")
|> Jason.decode!()
|> Map.put("object", comment.url)
# object =
# data["object"]
# |> Map.put("id", activity.data["object"]["id"])
{:ok, %Activity{local: false}, _} = Transmogrifier.handle_incoming(announce_data)
# data =
# data
# |> Map.put("object", object)
data =
File.read!("test/fixtures/mastodon-delete.json")
|> Jason.decode!()
# :error = Transmogrifier.handle_incoming(data)
object =
data["object"]
|> Map.put("id", comment.url)
# assert Repo.get(Activity, activity.id)
# end
data =
data
|> Map.put("object", object)
:error = Transmogrifier.handle_incoming(data)
assert Events.get_comment_from_url(comment.url)
end
test "it works for incoming actor deletes" do
%Actor{url: url} = actor = insert(:actor, url: "https://framapiaf.org/users/admin")
%Event{url: event1_url} = event1 = insert(:event, organizer_actor: actor)
insert(:event, organizer_actor: actor)
%Comment{url: comment1_url} = comment1 = insert(:comment, actor: actor)
insert(:comment, actor: actor)
data =
File.read!("test/fixtures/mastodon-delete-user.json")
|> Poison.decode!()
{:ok, _activity, _actor} = Transmogrifier.handle_incoming(data)
assert %{success: 1, failure: 0} == Oban.drain_queue(:background)
assert {:ok, %Actor{suspended: true}} = Actors.get_actor_by_url(url)
assert {:error, :event_not_found} = Events.get_event(event1.id)
assert %Tombstone{} = Tombstone.find_tombstone(event1_url)
assert %Comment{deleted_at: deleted_at} = Events.get_comment(comment1.id)
refute is_nil(deleted_at)
assert %Tombstone{} = Tombstone.find_tombstone(comment1_url)
end
test "it fails for incoming actor deletes with spoofed origin" do
%{url: url} = insert(:actor)
data =
File.read!("test/fixtures/mastodon-delete-user.json")
|> Poison.decode!()
|> Map.put("actor", url)
assert capture_log(fn ->
assert :error == Transmogrifier.handle_incoming(data)
end) =~ "Object origin check failed"
assert Actors.get_actor_by_url(url)
end
test "it works for incoming unannounces with an existing notice" do
use_cassette "activity_pub/mastodon_unannounce_activity" do
@@ -743,13 +790,14 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
end
test "it accepts Flag activities" do
%Actor{url: reporter_url} = _reporter = insert(:actor)
%Actor{url: reporter_url} = Mobilizon.Service.ActivityPub.Relay.get_actor()
%Actor{url: reported_url} = reported = insert(:actor)
%Comment{url: comment_url} = _comment = insert(:comment, actor: reported)
message = %{
"@context" => "https://www.w3.org/ns/activitystreams",
"to" => [],
"cc" => [reported_url],
"object" => [reported_url, comment_url],
"type" => "Flag",
@@ -762,11 +810,11 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
assert activity.data["object"] == [reported_url, comment_url]
assert activity.data["content"] == "blocked AND reported!!!"
assert activity.data["actor"] == reporter_url
assert activity.data["cc"] == [reported_url]
assert activity.data["cc"] == []
end
test "it accepts Join activities" do
%Actor{url: _organizer_url} = organizer = insert(:actor)
%Actor{url: organizer_url} = organizer = insert(:actor)
%Actor{url: participant_url} = _participant = insert(:actor)
%Event{url: event_url} = _event = insert(:event, organizer_actor: organizer)
@@ -779,8 +827,12 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
assert {:ok, activity, _} = Transmogrifier.handle_incoming(join_data)
assert activity.data["object"] == event_url
assert activity.data["actor"] == participant_url
assert activity.data["type"] == "Accept"
assert activity.data["object"]["object"] == event_url
assert activity.data["object"]["id"] =~ "/join/event/"
assert activity.data["object"]["type"] =~ "Join"
assert activity.data["actor"] == organizer_url
assert activity.data["id"] =~ "/accept/join/"
end
test "it accepts Accept activities for Join activities" do
@@ -821,12 +873,17 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|> Map.put("object", participation.url)
{:ok, reject_activity, _} = Transmogrifier.handle_incoming(reject_data)
assert reject_activity.data["object"] == join_activity.data["id"]
assert reject_activity.data["object"] =~ "/join/"
assert reject_activity.data["object"]["id"] == join_activity.data["id"]
assert reject_activity.data["object"]["id"] =~ "/join/"
assert reject_activity.data["id"] =~ "/reject/join/"
# We don't accept already rejected Reject activities
assert :error == Transmogrifier.handle_incoming(reject_data)
assert capture_log([level: :warn], fn ->
assert :error == Transmogrifier.handle_incoming(reject_data)
end) =~
"Unable to process Reject activity \"http://mastodon.example.org/users/admin#rejects/follows/4\". Object \"#{
join_activity.data["id"]
}\" wasn't found."
# Organiser is not present since we use factories directly
assert event.id
@@ -913,15 +970,6 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
assert Enum.member?(object["tag"], expected_mention)
end
# test "it adds the sensitive property" do
# user = insert(:user)
# {:ok, activity} = CommonAPI.post(user, %{"status" => "#nsfw hey"})
# {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
# assert modified["object"]["sensitive"]
# end
test "it adds the json-ld context and the conversation property" do
actor = insert(:actor)
@@ -975,125 +1023,28 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
assert is_nil(modified["object"]["announcement_count"])
assert is_nil(modified["object"]["context_id"])
end
end
# describe "actor rewriting" do
# test "it fixes the actor URL property to be a proper URI" do
# data = %{
# "url" => %{"href" => "http://example.com"}
# }
describe "actor origin check" do
test "it rejects objects with a bogus origin" do
use_cassette "activity_pub/object_bogus_origin" do
{:error, _} = ActivityPub.fetch_object_from_url("https://info.pleroma.site/activity.json")
end
end
# rewritten = Transmogrifier.maybe_fix_user_object(data)
# assert rewritten["url"] == "http://example.com"
# end
# end
test "it rejects activities which reference objects with bogus origins" do
use_cassette "activity_pub/activity_object_bogus" do
data = %{
"@context" => "https://www.w3.org/ns/activitystreams",
"id" => "https://framapiaf.org/users/admin/activities/1234",
"actor" => "https://framapiaf.org/users/admin",
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
"object" => "https://info.pleroma.site/activity.json",
"type" => "Announce"
}
# describe "actor origin containment" do
# test "it rejects objects with a bogus origin" do
# {:error, _} = ActivityPub.fetch_object_from_id("https://info.pleroma.site/activity.json")
# end
# test "it rejects activities which reference objects with bogus origins" do
# data = %{
# "@context" => "https://www.w3.org/ns/activitystreams",
# "id" => "http://mastodon.example.org/users/admin/activities/1234",
# "actor" => "http://mastodon.example.org/users/admin",
# "to" => ["https://www.w3.org/ns/activitystreams#Public"],
# "object" => "https://info.pleroma.site/activity.json",
# "type" => "Announce"
# }
# :error = Transmogrifier.handle_incoming(data)
# end
# test "it rejects objects when attributedTo is wrong (variant 1)" do
# {:error, _} = ActivityPub.fetch_object_from_id("https://info.pleroma.site/activity2.json")
# end
# test "it rejects activities which reference objects that have an incorrect attribution (variant 1)" do
# data = %{
# "@context" => "https://www.w3.org/ns/activitystreams",
# "id" => "http://mastodon.example.org/users/admin/activities/1234",
# "actor" => "http://mastodon.example.org/users/admin",
# "to" => ["https://www.w3.org/ns/activitystreams#Public"],
# "object" => "https://info.pleroma.site/activity2.json",
# "type" => "Announce"
# }
# :error = Transmogrifier.handle_incoming(data)
# end
# test "it rejects objects when attributedTo is wrong (variant 2)" do
# {:error, _} = ActivityPub.fetch_object_from_id("https://info.pleroma.site/activity3.json")
# end
# test "it rejects activities which reference objects that have an incorrect attribution (variant 2)" do
# data = %{
# "@context" => "https://www.w3.org/ns/activitystreams",
# "id" => "http://mastodon.example.org/users/admin/activities/1234",
# "actor" => "http://mastodon.example.org/users/admin",
# "to" => ["https://www.w3.org/ns/activitystreams#Public"],
# "object" => "https://info.pleroma.site/activity3.json",
# "type" => "Announce"
# }
# :error = Transmogrifier.handle_incoming(data)
# end
# end
# describe "general origin containment" do
# test "contain_origin_from_id() catches obvious spoofing attempts" do
# data = %{
# "id" => "http://example.com/~alyssa/activities/1234.json"
# }
# :error =
# Transmogrifier.contain_origin_from_id(
# "http://example.org/~alyssa/activities/1234.json",
# data
# )
# end
# test "contain_origin_from_id() allows alternate IDs within the same origin domain" do
# data = %{
# "id" => "http://example.com/~alyssa/activities/1234.json"
# }
# :ok =
# Transmogrifier.contain_origin_from_id(
# "http://example.com/~alyssa/activities/1234",
# data
# )
# end
# test "contain_origin_from_id() allows matching IDs" do
# data = %{
# "id" => "http://example.com/~alyssa/activities/1234.json"
# }
# :ok =
# Transmogrifier.contain_origin_from_id(
# "http://example.com/~alyssa/activities/1234.json",
# data
# )
# end
# test "users cannot be collided through fake direction spoofing attempts" do
# user =
# insert(:user, %{
# nickname: "rye@niu.moe",
# local: false,
# ap_id: "https://niu.moe/users/rye",
# follower_address: User.ap_followers(%User{nickname: "rye@niu.moe"})
# })
# {:error, _} = User.get_or_fetch_by_ap_id("https://n1u.moe/users/rye")
# end
# test "all objects with fake directions are rejected by the object fetcher" do
# {:error, _} =
# ActivityPub.fetch_and_contain_remote_object_from_id(
# "https://info.pleroma.site/activity4.json"
# )
# end
:error = Transmogrifier.handle_incoming(data)
end
end
end
end

View File

@@ -5,7 +5,7 @@ defmodule Mobilizon.Service.ActivityPub.UtilsTest do
import Mobilizon.Factory
alias Mobilizon.Service.ActivityPub.{Converter, Utils}
alias Mobilizon.Service.ActivityPub.Converter
alias MobilizonWeb.Endpoint
alias MobilizonWeb.Router.Helpers, as: Routes
@@ -36,7 +36,8 @@ defmodule Mobilizon.Service.ActivityPub.UtilsTest do
"uuid" => reply.uuid,
"id" => Routes.page_url(Endpoint, :comment, reply.uuid),
"inReplyTo" => comment.url,
"attributedTo" => reply.actor.url
"attributedTo" => reply.actor.url,
"mediaType" => "text/html"
} == Converter.Comment.model_to_as(reply)
end
@@ -44,7 +45,7 @@ defmodule Mobilizon.Service.ActivityPub.UtilsTest do
comment = insert(:comment)
reply = insert(:comment, in_reply_to_comment: comment)
to = ["https://www.w3.org/ns/activitystreams#Public"]
comment_data = Utils.make_comment_data(reply.actor.url, to, reply.text, comment.url)
comment_data = Converter.Comment.model_to_as(reply)
assert comment_data["type"] == "Note"
assert comment_data["to"] == to
assert comment_data["content"] == reply.text

View File

@@ -33,21 +33,21 @@ defmodule Mobilizon.Service.FormatterTest do
text = "Hey, check out https://www.youtube.com/watch?v=8Zg1-TufF%20zY?x=1&y=2#blabla ."
expected =
"Hey, check out <a href=\"https://www.youtube.com/watch?v=8Zg1-TufF%20zY?x=1&y=2#blabla\" target=\"_blank\" rel=\"noopener noreferrer\">https://www.youtube.com/watch?v=8Zg1-TufF%20zY?x=1&y=2#blabla</a> ."
"Hey, check out <a href=\"https://www.youtube.com/watch?v=8Zg1-TufF%20zY?x=1&y=2#blabla\" target=\"_blank\" rel=\"noopener noreferrer ugc\">https://www.youtube.com/watch?v=8Zg1-TufF%20zY?x=1&y=2#blabla</a> ."
assert {^expected, [], []} = Formatter.linkify(text)
text = "https://mastodon.social/@lambadalambda"
expected =
"<a href=\"https://mastodon.social/@lambadalambda\" target=\"_blank\" rel=\"noopener noreferrer\">https://mastodon.social/@lambadalambda</a>"
"<a href=\"https://mastodon.social/@lambadalambda\" target=\"_blank\" rel=\"noopener noreferrer ugc\">https://mastodon.social/@lambadalambda</a>"
assert {^expected, [], []} = Formatter.linkify(text)
text = "https://mastodon.social:4000/@lambadalambda"
expected =
"<a href=\"https://mastodon.social:4000/@lambadalambda\" target=\"_blank\" rel=\"noopener noreferrer\">https://mastodon.social:4000/@lambadalambda</a>"
"<a href=\"https://mastodon.social:4000/@lambadalambda\" target=\"_blank\" rel=\"noopener noreferrer ugc\">https://mastodon.social:4000/@lambadalambda</a>"
assert {^expected, [], []} = Formatter.linkify(text)
@@ -59,56 +59,57 @@ defmodule Mobilizon.Service.FormatterTest do
text = "http://www.cs.vu.nl/~ast/intel/"
expected =
"<a href=\"http://www.cs.vu.nl/~ast/intel/\" target=\"_blank\" rel=\"noopener noreferrer\">http://www.cs.vu.nl/~ast/intel/</a>"
"<a href=\"http://www.cs.vu.nl/~ast/intel/\" target=\"_blank\" rel=\"noopener noreferrer ugc\">http://www.cs.vu.nl/~ast/intel/</a>"
assert {^expected, [], []} = Formatter.linkify(text)
text = "https://forum.zdoom.org/viewtopic.php?f=44&t=57087"
expected =
"<a href=\"https://forum.zdoom.org/viewtopic.php?f=44&t=57087\" target=\"_blank\" rel=\"noopener noreferrer\">https://forum.zdoom.org/viewtopic.php?f=44&t=57087</a>"
"<a href=\"https://forum.zdoom.org/viewtopic.php?f=44&t=57087\" target=\"_blank\" rel=\"noopener noreferrer ugc\">https://forum.zdoom.org/viewtopic.php?f=44&t=57087</a>"
assert {^expected, [], []} = Formatter.linkify(text)
text = "https://en.wikipedia.org/wiki/Sophia_(Gnosticism)#Mythos_of_the_soul"
expected =
"<a href=\"https://en.wikipedia.org/wiki/Sophia_(Gnosticism)#Mythos_of_the_soul\" target=\"_blank\" rel=\"noopener noreferrer\">https://en.wikipedia.org/wiki/Sophia_(Gnosticism)#Mythos_of_the_soul</a>"
"<a href=\"https://en.wikipedia.org/wiki/Sophia_(Gnosticism)#Mythos_of_the_soul\" target=\"_blank\" rel=\"noopener noreferrer ugc\">https://en.wikipedia.org/wiki/Sophia_(Gnosticism)#Mythos_of_the_soul</a>"
assert {^expected, [], []} = Formatter.linkify(text)
text = "https://www.google.co.jp/search?q=Nasim+Aghdam"
expected =
"<a href=\"https://www.google.co.jp/search?q=Nasim+Aghdam\" target=\"_blank\" rel=\"noopener noreferrer\">https://www.google.co.jp/search?q=Nasim+Aghdam</a>"
"<a href=\"https://www.google.co.jp/search?q=Nasim+Aghdam\" target=\"_blank\" rel=\"noopener noreferrer ugc\">https://www.google.co.jp/search?q=Nasim+Aghdam</a>"
assert {^expected, [], []} = Formatter.linkify(text)
text = "https://en.wikipedia.org/wiki/Duff's_device"
expected =
"<a href=\"https://en.wikipedia.org/wiki/Duff's_device\" target=\"_blank\" rel=\"noopener noreferrer\">https://en.wikipedia.org/wiki/Duff's_device</a>"
"<a href=\"https://en.wikipedia.org/wiki/Duff's_device\" target=\"_blank\" rel=\"noopener noreferrer ugc\">https://en.wikipedia.org/wiki/Duff's_device</a>"
assert {^expected, [], []} = Formatter.linkify(text)
text = "https://pleroma.com https://pleroma.com/sucks"
expected =
"<a href=\"https://pleroma.com\" target=\"_blank\" rel=\"noopener noreferrer\">https://pleroma.com</a> <a href=\"https://pleroma.com/sucks\" target=\"_blank\" rel=\"noopener noreferrer\">https://pleroma.com/sucks</a>"
"<a href=\"https://pleroma.com\" target=\"_blank\" rel=\"noopener noreferrer ugc\">https://pleroma.com</a> <a href=\"https://pleroma.com/sucks\" target=\"_blank\" rel=\"noopener noreferrer ugc\">https://pleroma.com/sucks</a>"
assert {^expected, [], []} = Formatter.linkify(text)
text = "xmpp:contact@hacktivis.me"
expected =
"<a href=\"xmpp:contact@hacktivis.me\" target=\"_blank\" rel=\"noopener noreferrer\">xmpp:contact@hacktivis.me</a>"
"<a href=\"xmpp:contact@hacktivis.me\" target=\"_blank\" rel=\"noopener noreferrer ugc\">xmpp:contact@hacktivis.me</a>"
assert {^expected, [], []} = Formatter.linkify(text)
text =
"magnet:?xt=urn:btih:7ec9d298e91d6e4394d1379caf073c77ff3e3136&tr=udp%3A%2F%2Fopentor.org%3A2710&tr=udp%3A%2F%2Ftracker.blackunicorn.xyz%3A6969&tr=udp%3A%2F%2Ftracker.ccc.de%3A80&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A80&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.fastcast.nz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com"
expected = "<a href=\"#{text}\" target=\"_blank\" rel=\"noopener noreferrer\">#{text}</a>"
expected =
"<a href=\"#{text}\" target=\"_blank\" rel=\"noopener noreferrer ugc\">#{text}</a>"
assert {^expected, [], []} = Formatter.linkify(text)
end
@@ -117,32 +118,36 @@ defmodule Mobilizon.Service.FormatterTest do
describe "add_user_links" do
test "gives a replacement for user links, using local nicknames in user links text" do
text = "@gsimg According to @archa_eme_, that is @daggsy. Also hello @archaeme@archae.me"
_gsimg = insert(:actor, preferred_username: "gsimg")
gsimg = insert(:actor, preferred_username: "gsimg")
_archaeme =
archaeme =
insert(:actor, preferred_username: "archa_eme_", url: "https://archeme/@archa_eme_")
_archaeme_remote = insert(:actor, preferred_username: "archaeme", domain: "archae.me")
archaeme_remote = insert(:actor, preferred_username: "archaeme", domain: "archae.me")
{text, mentions, []} = Formatter.linkify(text)
assert length(mentions) == 3
expected_text =
"<span class='h-card mention'>@<span>gsimg</span></span> According to <span class='h-card mention'>@<span>archa_eme_</span></span>, that is @daggsy. Also hello <span class='h-card mention'>@<span>archaeme</span></span>"
"<span class='h-card mention' data-user='#{gsimg.id}'>@<span>gsimg</span></span> According to <span class='h-card mention' data-user='#{
archaeme.id
}'>@<span>archa_eme_</span></span>, that is @daggsy. Also hello <span class='h-card mention' data-user='#{
archaeme_remote.id
}'>@<span>archaeme</span></span>"
assert expected_text == text
end
test "gives a replacement for single-character local nicknames" do
text = "@o hi"
_o = insert(:actor, preferred_username: "o")
o = insert(:actor, preferred_username: "o")
{text, mentions, []} = Formatter.linkify(text)
assert length(mentions) == 1
expected_text = "<span class='h-card mention'>@<span>o</span></span> hi"
expected_text = "<span class='h-card mention' data-user='#{o.id}'>@<span>o</span></span> hi"
assert expected_text == text
end