Browse Source

Merge branch 'release/2.0.7' into 'stable'

Release/2.0.7

See merge request pleroma/secteam/pleroma!8
tags/v2.0.7
rinpatch 4 years ago
parent
commit
f891e2b2f1
20 changed files with 339 additions and 121 deletions
  1. +14
    -0
      CHANGELOG.md
  2. +2
    -4
      config/description.exs
  3. +3
    -2
      docs/configuration/cheatsheet.md
  4. +24
    -1
      lib/pleroma/config/deprecation_warnings.ex
  5. +5
    -0
      lib/pleroma/constants.ex
  6. +6
    -1
      lib/pleroma/plugs/http_security_plug.ex
  7. +3
    -4
      lib/pleroma/plugs/instance_static.ex
  8. +1
    -1
      lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex
  9. +3
    -2
      lib/pleroma/web/endpoint.ex
  10. +6
    -8
      lib/pleroma/web/mastodon_api/views/status_view.ex
  11. +3
    -3
      lib/pleroma/web/rich_media/helpers.ex
  12. +4
    -8
      lib/pleroma/web/rich_media/parser.ex
  13. +4
    -4
      lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex
  14. +6
    -12
      lib/pleroma/web/rich_media/parsers/oembed_parser.ex
  15. +1
    -1
      lib/pleroma/web/templates/layout/static_fe.html.eex
  16. +1
    -1
      mix.exs
  17. +183
    -0
      priv/static/static-fe/static-fe.css
  18. +2
    -2
      test/web/activity_pub/mrf/user_allowlist_policy_test.exs
  19. +38
    -37
      test/web/rich_media/parser_test.exs
  20. +30
    -30
      test/web/rich_media/parsers/twitter_card_test.exs

+ 14
- 0
CHANGELOG.md View File

@@ -3,6 +3,20 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [2.0.7] - 2020-06-13

### Security
- Fix potential DoSes exploiting atom leaks in rich media parser and the `UserAllowListPolicy` MRF policy

### Fixed
- CSP: not allowing images/media from every host when mediaproxy is disabled
- CSP: not adding mediaproxy base url to image/media hosts
- StaticFE missing the CSS file

### Upgrade notes

1. Restart Pleroma

## [2.0.6] - 2020-06-09

### Security


+ 2
- 4
config/description.exs View File

@@ -1483,14 +1483,12 @@ config :pleroma, :config_description, [
# %{
# group: :pleroma,
# key: :mrf_user_allowlist,
# type: :group,
# type: :map,
# description:
# "The keys in this section are the domain names that the policy should apply to." <>
# " Each key should be assigned a list of users that should be allowed through by their ActivityPub ID",
# children: [
# ["example.org": ["https://example.org/users/admin"]],
# suggestions: [
# ["example.org": ["https://example.org/users/admin"]]
# %{"example.org" => ["https://example.org/users/admin"]}
# ]
# ]
# },


+ 3
- 2
docs/configuration/cheatsheet.md View File

@@ -133,8 +133,9 @@ their ActivityPub ID.
An example:

```elixir
config :pleroma, :mrf_user_allowlist,
"example.org": ["https://example.org/users/admin"]
config :pleroma, :mrf_user_allowlist, %{
"example.org" => ["https://example.org/users/admin"]
}
```

#### :mrf_object_age


+ 24
- 1
lib/pleroma/config/deprecation_warnings.ex View File

@@ -4,9 +4,10 @@

defmodule Pleroma.Config.DeprecationWarnings do
require Logger
alias Pleroma.Config

def check_hellthread_threshold do
if Pleroma.Config.get([:mrf_hellthread, :threshold]) do
if Config.get([:mrf_hellthread, :threshold]) do
Logger.warn("""
!!!DEPRECATION WARNING!!!
You are using the old configuration mechanism for the hellthread filter. Please check config.md.
@@ -14,7 +15,29 @@ defmodule Pleroma.Config.DeprecationWarnings do
end
end

def mrf_user_allowlist do
config = Config.get(:mrf_user_allowlist)

if config && Enum.any?(config, fn {k, _} -> is_atom(k) end) do
rewritten =
Enum.reduce(Config.get(:mrf_user_allowlist), Map.new(), fn {k, v}, acc ->
Map.put(acc, to_string(k), v)
end)

Config.put(:mrf_user_allowlist, rewritten)

Logger.error("""
!!!DEPRECATION WARNING!!!
As of Pleroma 2.0.7, the `mrf_user_allowlist` setting changed of format.
Pleroma 2.1 will remove support for the old format. Please change your configuration to match this:

config :pleroma, :mrf_user_allowlist, #{inspect(rewritten, pretty: true)}
""")
end
end

def warn do
check_hellthread_threshold()
mrf_user_allowlist()
end
end

+ 5
- 0
lib/pleroma/constants.ex View File

@@ -20,4 +20,9 @@ defmodule Pleroma.Constants do
"deleted_activity_id"
]
)

const(static_only_files,
do:
~w(index.html robots.txt static static-fe finmoji emoji packs sounds images instance sw.js sw-pleroma.js favicon.png schemas doc)
)
end

+ 6
- 1
lib/pleroma/plugs/http_security_plug.ex View File

@@ -75,7 +75,7 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do
sources = get_proxy_and_attachment_sources()
{[img_src, sources], [media_src, sources]}
else
{img_src, media_src}
{[img_src, " https:"], [media_src, " https:"]}
end

connect_src = ["connect-src 'self' ", static_url, ?\s, websocket_url]
@@ -113,6 +113,10 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do
add_source(acc, host)
end)

media_proxy_base_url =
if Config.get([:media_proxy, :base_url]),
do: URI.parse(Config.get([:media_proxy, :base_url])).host

upload_base_url =
if Config.get([Pleroma.Upload, :base_url]),
do: URI.parse(Config.get([Pleroma.Upload, :base_url])).host
@@ -122,6 +126,7 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do
do: URI.parse(Config.get([Pleroma.Uploaders.S3, :public_endpoint])).host

[]
|> add_source(media_proxy_base_url)
|> add_source(upload_base_url)
|> add_source(s3_endpoint)
|> add_source(media_proxy_whitelist)


+ 3
- 4
lib/pleroma/plugs/instance_static.ex View File

@@ -3,6 +3,8 @@
# SPDX-License-Identifier: AGPL-3.0-only

defmodule Pleroma.Plugs.InstanceStatic do
require Pleroma.Constants

@moduledoc """
This is a shim to call `Plug.Static` but with runtime `from` configuration.

@@ -21,9 +23,6 @@ defmodule Pleroma.Plugs.InstanceStatic do
end
end

@only ~w(index.html robots.txt static emoji packs sounds images instance favicon.png sw.js
sw-pleroma.js)

def init(opts) do
opts
|> Keyword.put(:from, "__unconfigured_instance_static_plug")
@@ -31,7 +30,7 @@ defmodule Pleroma.Plugs.InstanceStatic do
|> Plug.Static.init()
end

for only <- @only do
for only <- Pleroma.Constants.static_only_files() do
at = Plug.Router.Utils.split("/")

def call(%{request_path: "/" <> unquote(only) <> _} = conn, opts) do


+ 1
- 1
lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex View File

@@ -24,7 +24,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy do

allow_list =
Config.get(
[:mrf_user_allowlist, String.to_atom(actor_info.host)],
[:mrf_user_allowlist, actor_info.host],
[]
)



+ 3
- 2
lib/pleroma/web/endpoint.ex View File

@@ -5,6 +5,8 @@
defmodule Pleroma.Web.Endpoint do
use Phoenix.Endpoint, otp_app: :pleroma

require Pleroma.Constants

socket("/socket", Pleroma.Web.UserSocket)

plug(Pleroma.Plugs.SetLocalePlug)
@@ -34,8 +36,7 @@ defmodule Pleroma.Web.Endpoint do
Plug.Static,
at: "/",
from: :pleroma,
only:
~w(index.html robots.txt static finmoji emoji packs sounds images instance sw.js sw-pleroma.js favicon.png schemas doc),
only: Pleroma.Constants.static_only_files(),
# credo:disable-for-previous-line Credo.Check.Readability.MaxLineLength
gzip: true,
cache_control_for_etags: @static_cache_control,


+ 6
- 8
lib/pleroma/web/mastodon_api/views/status_view.ex View File

@@ -307,8 +307,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
page_url_data = URI.parse(page_url)

page_url_data =
if rich_media[:url] != nil do
URI.merge(page_url_data, URI.parse(rich_media[:url]))
if is_binary(rich_media["url"]) do
URI.merge(page_url_data, URI.parse(rich_media["url"]))
else
page_url_data
end
@@ -316,11 +316,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
page_url = page_url_data |> to_string

image_url =
if rich_media[:image] != nil do
URI.merge(page_url_data, URI.parse(rich_media[:image]))
if is_binary(rich_media["image"]) do
URI.merge(page_url_data, URI.parse(rich_media["image"]))
|> to_string
else
nil
end

%{
@@ -329,8 +327,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
provider_url: page_url_data.scheme <> "://" <> page_url_data.host,
url: page_url,
image: image_url |> MediaProxy.url(),
title: rich_media[:title] || "",
description: rich_media[:description] || "",
title: rich_media["title"] || "",
description: rich_media["description"] || "",
pleroma: %{
opengraph: rich_media
}


+ 3
- 3
lib/pleroma/web/rich_media/helpers.ex View File

@@ -9,7 +9,7 @@ defmodule Pleroma.Web.RichMedia.Helpers do
alias Pleroma.Object
alias Pleroma.Web.RichMedia.Parser

@spec validate_page_url(any()) :: :ok | :error
@spec validate_page_url(URI.t() | binary()) :: :ok | :error
defp validate_page_url(page_url) when is_binary(page_url) do
validate_tld = Application.get_env(:auto_linker, :opts)[:validate_tld]

@@ -18,8 +18,8 @@ defmodule Pleroma.Web.RichMedia.Helpers do
|> parse_uri(page_url)
end

defp validate_page_url(%URI{host: host, scheme: scheme, authority: authority})
when scheme == "https" and not is_nil(authority) do
defp validate_page_url(%URI{host: host, scheme: "https", authority: authority})
when is_binary(authority) do
cond do
host in Config.get([:rich_media, :ignore_hosts], []) ->
:error


+ 4
- 8
lib/pleroma/web/rich_media/parser.ex View File

@@ -83,7 +83,7 @@ defmodule Pleroma.Web.RichMedia.Parser do
html
|> parse_html()
|> maybe_parse()
|> Map.put(:url, url)
|> Map.put("url", url)
|> clean_parsed_data()
|> check_parsed_data()
rescue
@@ -103,8 +103,8 @@ defmodule Pleroma.Web.RichMedia.Parser do
end)
end

defp check_parsed_data(%{title: title} = data)
when is_binary(title) and byte_size(title) > 0 do
defp check_parsed_data(%{"title" => title} = data)
when is_binary(title) and title != "" do
{:ok, data}
end

@@ -115,11 +115,7 @@ defmodule Pleroma.Web.RichMedia.Parser do
defp clean_parsed_data(data) do
data
|> Enum.reject(fn {key, val} ->
with {:ok, _} <- Jason.encode(%{key => val}) do
false
else
_ -> true
end
not match?({:ok, _}, Jason.encode(%{key => val}))
end)
|> Map.new()
end


+ 4
- 4
lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex View File

@@ -29,19 +29,19 @@ defmodule Pleroma.Web.RichMedia.Parsers.MetaTagsParser do
{_tag, attributes, _children} = html_node

data =
Enum.into(attributes, %{}, fn {name, value} ->
Map.new(attributes, fn {name, value} ->
{name, String.trim_leading(value, "#{prefix}:")}
end)

%{String.to_atom(data[key_name]) => data[value_name]}
%{data[key_name] => data[value_name]}
end

defp maybe_put_title(%{title: _} = meta, _), do: meta
defp maybe_put_title(%{"title" => _} = meta, _), do: meta

defp maybe_put_title(meta, html) when meta != %{} do
case get_page_title(html) do
"" -> meta
title -> Map.put_new(meta, :title, title)
title -> Map.put_new(meta, "title", title)
end
end



+ 6
- 12
lib/pleroma/web/rich_media/parsers/oembed_parser.ex View File

@@ -5,7 +5,7 @@
defmodule Pleroma.Web.RichMedia.Parsers.OEmbed do
def parse(html, _data) do
with elements = [_ | _] <- get_discovery_data(html),
{:ok, oembed_url} <- get_oembed_url(elements),
oembed_url when is_binary(oembed_url) <- get_oembed_url(elements),
{:ok, oembed_data} <- get_oembed_data(oembed_url) do
{:ok, oembed_data}
else
@@ -17,19 +17,13 @@ defmodule Pleroma.Web.RichMedia.Parsers.OEmbed do
html |> Floki.find("link[type='application/json+oembed']")
end

defp get_oembed_url(nodes) do
{"link", attributes, _children} = nodes |> hd()

{:ok, Enum.into(attributes, %{})["href"]}
defp get_oembed_url([{"link", attributes, _children} | _]) do
Enum.find_value(attributes, fn {k, v} -> if k == "href", do: v end)
end

defp get_oembed_data(url) do
{:ok, %Tesla.Env{body: json}} = Pleroma.HTTP.get(url, [], adapter: [pool: :media])

{:ok, data} = Jason.decode(json)

data = data |> Map.new(fn {k, v} -> {String.to_atom(k), v} end)

{:ok, data}
with {:ok, %Tesla.Env{body: json}} <- Pleroma.HTTP.get(url, [], adapter: [pool: :media]) do
Jason.decode(json)
end
end
end

+ 1
- 1
lib/pleroma/web/templates/layout/static_fe.html.eex View File

@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width,initial-scale=1,minimal-ui" />
<title><%= Pleroma.Config.get([:instance, :name]) %></title>
<%= Phoenix.HTML.raw(assigns[:meta] || "") %>
<link rel="stylesheet" href="/static/static-fe.css">
<link rel="stylesheet" href="/static-fe/static-fe.css">
</head>
<body>
<div class="container">


+ 1
- 1
mix.exs View File

@@ -4,7 +4,7 @@ defmodule Pleroma.Mixfile do
def project do
[
app: :pleroma,
version: version("2.0.6"),
version: version("2.0.7"),
elixir: "~> 1.8",
elixirc_paths: elixirc_paths(Mix.env()),
compilers: [:phoenix, :gettext] ++ Mix.compilers(),


+ 183
- 0
priv/static/static-fe/static-fe.css View File

@@ -0,0 +1,183 @@
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;
}

+ 2
- 2
test/web/activity_pub/mrf/user_allowlist_policy_test.exs View File

@@ -17,14 +17,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicyTest do

test "pass filter if allow list isn't empty and user in allow list" do
actor = insert(:user)
Pleroma.Config.put([:mrf_user_allowlist, :localhost], [actor.ap_id, "test-ap-id"])
Pleroma.Config.put([:mrf_user_allowlist], %{"localhost" => [actor.ap_id, "test-ap-id"]})
message = %{"actor" => actor.ap_id}
assert UserAllowListPolicy.filter(message) == {:ok, message}
end

test "rejected if allow list isn't empty and user not in allow list" do
actor = insert(:user)
Pleroma.Config.put([:mrf_user_allowlist, :localhost], ["test-ap-id"])
Pleroma.Config.put([:mrf_user_allowlist], %{"localhost" => ["test-ap-id"]})
message = %{"actor" => actor.ap_id}
assert UserAllowListPolicy.filter(message) == {:reject, nil}
end


+ 38
- 37
test/web/rich_media/parser_test.exs View File

@@ -60,19 +60,19 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
test "doesn't just add a title" do
assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/non-ogp") ==
{:error,
"Found metadata was invalid or incomplete: %{url: \"http://example.com/non-ogp\"}"}
"Found metadata was invalid or incomplete: %{\"url\" => \"http://example.com/non-ogp\"}"}
end

test "parses ogp" do
assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/ogp") ==
{:ok,
%{
image: "http://ia.media-imdb.com/images/rock.jpg",
title: "The Rock",
description:
"image" => "http://ia.media-imdb.com/images/rock.jpg",
"title" => "The Rock",
"description" =>
"Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer.",
type: "video.movie",
url: "http://example.com/ogp"
"type" => "video.movie",
"url" => "http://example.com/ogp"
}}
end

@@ -80,12 +80,12 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/ogp-missing-title") ==
{:ok,
%{
image: "http://ia.media-imdb.com/images/rock.jpg",
title: "The Rock (1996)",
description:
"image" => "http://ia.media-imdb.com/images/rock.jpg",
"title" => "The Rock (1996)",
"description" =>
"Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer.",
type: "video.movie",
url: "http://example.com/ogp-missing-title"
"type" => "video.movie",
"url" => "http://example.com/ogp-missing-title"
}}
end

@@ -93,12 +93,12 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/twitter-card") ==
{:ok,
%{
card: "summary",
site: "@flickr",
image: "https://farm6.staticflickr.com/5510/14338202952_93595258ff_z.jpg",
title: "Small Island Developing States Photo Submission",
description: "View the album on Flickr.",
url: "http://example.com/twitter-card"
"card" => "summary",
"site" => "@flickr",
"image" => "https://farm6.staticflickr.com/5510/14338202952_93595258ff_z.jpg",
"title" => "Small Island Developing States Photo Submission",
"description" => "View the album on Flickr.",
"url" => "http://example.com/twitter-card"
}}
end

@@ -106,27 +106,28 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/oembed") ==
{:ok,
%{
author_name: "‮‭‬bees‬",
author_url: "https://www.flickr.com/photos/bees/",
cache_age: 3600,
flickr_type: "photo",
height: "768",
html:
"author_name" => "‮‭‬bees‬",
"author_url" => "https://www.flickr.com/photos/bees/",
"cache_age" => 3600,
"flickr_type" => "photo",
"height" => "768",
"html" =>
"<a data-flickr-embed=\"true\" href=\"https://www.flickr.com/photos/bees/2362225867/\" title=\"Bacon Lollys by ‮‭‬bees‬, on Flickr\"><img src=\"https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_b.jpg\" width=\"1024\" height=\"768\" alt=\"Bacon Lollys\"></a><script async src=\"https://embedr.flickr.com/assets/client-code.js\" charset=\"utf-8\"></script>",
license: "All Rights Reserved",
license_id: 0,
provider_name: "Flickr",
provider_url: "https://www.flickr.com/",
thumbnail_height: 150,
thumbnail_url: "https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_q.jpg",
thumbnail_width: 150,
title: "Bacon Lollys",
type: "photo",
url: "http://example.com/oembed",
version: "1.0",
web_page: "https://www.flickr.com/photos/bees/2362225867/",
web_page_short_url: "https://flic.kr/p/4AK2sc",
width: "1024"
"license" => "All Rights Reserved",
"license_id" => 0,
"provider_name" => "Flickr",
"provider_url" => "https://www.flickr.com/",
"thumbnail_height" => 150,
"thumbnail_url" =>
"https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_q.jpg",
"thumbnail_width" => 150,
"title" => "Bacon Lollys",
"type" => "photo",
"url" => "http://example.com/oembed",
"version" => "1.0",
"web_page" => "https://www.flickr.com/photos/bees/2362225867/",
"web_page_short_url" => "https://flic.kr/p/4AK2sc",
"width" => "1024"
}}
end



+ 30
- 30
test/web/rich_media/parsers/twitter_card_test.exs View File

@@ -19,11 +19,11 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do
assert TwitterCard.parse(html, %{}) ==
{:ok,
%{
"app:id:googleplay": "com.nytimes.android",
"app:name:googleplay": "NYTimes",
"app:url:googleplay": "nytimes://reader/id/100000006583622",
site: nil,
title:
"app:id:googleplay" => "com.nytimes.android",
"app:name:googleplay" => "NYTimes",
"app:url:googleplay" => "nytimes://reader/id/100000006583622",
"site" => nil,
"title" =>
"She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database. - The New York Times"
}}
end
@@ -36,15 +36,15 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do
assert TwitterCard.parse(html, %{}) ==
{:ok,
%{
card: "summary_large_image",
description:
"card" => "summary_large_image",
"description" =>
"With little oversight, the N.Y.P.D. has been using powerful surveillance technology on photos of children and teenagers.",
image:
"image" =>
"https://static01.nyt.com/images/2019/08/01/nyregion/01nypd-juveniles-promo/01nypd-juveniles-promo-videoSixteenByNineJumbo1600.jpg",
"image:alt": "",
title:
"image:alt" => "",
"title" =>
"She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database.",
url:
"url" =>
"https://www.nytimes.com/2019/08/01/nyregion/nypd-facial-recognition-children-teenagers.html"
}}
end
@@ -57,19 +57,19 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do
assert TwitterCard.parse(html, %{}) ==
{:ok,
%{
"app:id:googleplay": "com.nytimes.android",
"app:name:googleplay": "NYTimes",
"app:url:googleplay": "nytimes://reader/id/100000006583622",
card: "summary_large_image",
description:
"app:id:googleplay" => "com.nytimes.android",
"app:name:googleplay" => "NYTimes",
"app:url:googleplay" => "nytimes://reader/id/100000006583622",
"card" => "summary_large_image",
"description" =>
"With little oversight, the N.Y.P.D. has been using powerful surveillance technology on photos of children and teenagers.",
image:
"image" =>
"https://static01.nyt.com/images/2019/08/01/nyregion/01nypd-juveniles-promo/01nypd-juveniles-promo-videoSixteenByNineJumbo1600.jpg",
"image:alt": "",
site: nil,
title:
"image:alt" => "",
"site" => nil,
"title" =>
"She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database.",
url:
"url" =>
"https://www.nytimes.com/2019/08/01/nyregion/nypd-facial-recognition-children-teenagers.html"
}}
end
@@ -86,11 +86,11 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do
assert TwitterCard.parse(html, %{}) ==
{:ok,
%{
site: "@atlasobscura",
title:
"site" => "@atlasobscura",
"title" =>
"The Missing Grave of Margaret Corbin, Revolutionary War Veteran - Atlas Obscura",
card: "summary_large_image",
image: image_path
"card" => "summary_large_image",
"image" => image_path
}}
end

@@ -102,12 +102,12 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do
assert TwitterCard.parse(html, %{}) ==
{:ok,
%{
site: nil,
title:
"site" => nil,
"title" =>
"She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database. - The New York Times",
"app:id:googleplay": "com.nytimes.android",
"app:name:googleplay": "NYTimes",
"app:url:googleplay": "nytimes://reader/id/100000006583622"
"app:id:googleplay" => "com.nytimes.android",
"app:name:googleplay" => "NYTimes",
"app:url:googleplay" => "nytimes://reader/id/100000006583622"
}}
end
end

Loading…
Cancel
Save