Merge branch 'develop' into feature/keyword-policy
This commit is contained in:
commit
6c21f5aa16
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -25,6 +25,7 @@ erl_crash.dump
|
||||||
# secrets files as long as you replace their contents by environment
|
# secrets files as long as you replace their contents by environment
|
||||||
# variables.
|
# variables.
|
||||||
/config/*.secret.exs
|
/config/*.secret.exs
|
||||||
|
/config/generated_config.exs
|
||||||
|
|
||||||
# Database setup file, some may forget to delete it
|
# Database setup file, some may forget to delete it
|
||||||
/config/setup_db.psql
|
/config/setup_db.psql
|
||||||
|
|
|
@ -10,15 +10,14 @@ For clients it supports both the [GNU Social API with Qvitter extensions](https:
|
||||||
|
|
||||||
Client applications that are committed to supporting Pleroma:
|
Client applications that are committed to supporting Pleroma:
|
||||||
|
|
||||||
* Mastalab (Android)
|
* Mastalab (Android, Streaming Ready)
|
||||||
* Tusky (Android)
|
* Tusky (Android, No Streaming)
|
||||||
* Twidere (Android)
|
* Twidere (Android, No Streaming)
|
||||||
* Mast (iOS)
|
* Mast (iOS)
|
||||||
* Amaroq (iOS)
|
* Amaroq (iOS)
|
||||||
|
|
||||||
Client applications that are known to work well:
|
Client applications that are known to work well:
|
||||||
|
|
||||||
* Pawoo (Android + iOS)
|
|
||||||
* Tootdon (Android + iOS)
|
* Tootdon (Android + iOS)
|
||||||
* Tootle (iOS)
|
* Tootle (iOS)
|
||||||
* Whalebird (Windows + Mac + Linux)
|
* Whalebird (Windows + Mac + Linux)
|
||||||
|
|
|
@ -115,7 +115,7 @@
|
||||||
config :logger, :ex_syslogger,
|
config :logger, :ex_syslogger,
|
||||||
level: :debug,
|
level: :debug,
|
||||||
ident: "Pleroma",
|
ident: "Pleroma",
|
||||||
format: "$date $time $metadata[$level] $message",
|
format: "$metadata[$level] $message",
|
||||||
metadata: [:request_id]
|
metadata: [:request_id]
|
||||||
|
|
||||||
config :mime, :types, %{
|
config :mime, :types, %{
|
||||||
|
|
|
@ -100,6 +100,26 @@ config :pleroma, Pleroma.Mailer,
|
||||||
|
|
||||||
## :logger
|
## :logger
|
||||||
* `backends`: `:console` is used to send logs to stdout, `{ExSyslogger, :ex_syslogger}` to log to syslog
|
* `backends`: `:console` is used to send logs to stdout, `{ExSyslogger, :ex_syslogger}` to log to syslog
|
||||||
|
|
||||||
|
An example to enable ONLY ExSyslogger (f/ex in ``prod.secret.exs``) with info and debug suppressed:
|
||||||
|
```
|
||||||
|
config :logger,
|
||||||
|
backends: [{ExSyslogger, :ex_syslogger}]
|
||||||
|
|
||||||
|
config :logger, :ex_syslogger,
|
||||||
|
level: :warn
|
||||||
|
```
|
||||||
|
|
||||||
|
Another example, keeping console output and adding the pid to syslog output:
|
||||||
|
```
|
||||||
|
config :logger,
|
||||||
|
backends: [:console, {ExSyslogger, :ex_syslogger}]
|
||||||
|
|
||||||
|
config :logger, :ex_syslogger,
|
||||||
|
level: :warn,
|
||||||
|
option: [:pid, :ndelay]
|
||||||
|
```
|
||||||
|
|
||||||
See: [logger’s documentation](https://hexdocs.pm/logger/Logger.html) and [ex_syslogger’s documentation](https://hexdocs.pm/ex_syslogger/)
|
See: [logger’s documentation](https://hexdocs.pm/logger/Logger.html) and [ex_syslogger’s documentation](https://hexdocs.pm/ex_syslogger/)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,14 @@ defmodule Mix.Tasks.Pleroma.User do
|
||||||
- `--locked`/`--no-locked` - whether the user's account is locked
|
- `--locked`/`--no-locked` - whether the user's account is locked
|
||||||
- `--moderator`/`--no-moderator` - whether the user is a moderator
|
- `--moderator`/`--no-moderator` - whether the user is a moderator
|
||||||
- `--admin`/`--no-admin` - whether the user is an admin
|
- `--admin`/`--no-admin` - whether the user is an admin
|
||||||
|
|
||||||
|
## Add tags to a user.
|
||||||
|
|
||||||
|
mix pleroma.user tag NICKNAME TAGS
|
||||||
|
|
||||||
|
## Delete tags from a user.
|
||||||
|
|
||||||
|
mix pleroma.user untag NICKNAME TAGS
|
||||||
"""
|
"""
|
||||||
def run(["new", nickname, email | rest]) do
|
def run(["new", nickname, email | rest]) do
|
||||||
{options, [], []} =
|
{options, [], []} =
|
||||||
|
@ -249,6 +257,32 @@ def run(["set", nickname | rest]) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def run(["tag", nickname | tags]) do
|
||||||
|
Common.start_pleroma()
|
||||||
|
|
||||||
|
with %User{} = user <- User.get_by_nickname(nickname) do
|
||||||
|
user = user |> User.tag(tags)
|
||||||
|
|
||||||
|
Mix.shell().info("Tags of #{user.nickname}: #{inspect(tags)}")
|
||||||
|
else
|
||||||
|
_ ->
|
||||||
|
Mix.shell().error("Could not change user tags for #{nickname}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def run(["untag", nickname | tags]) do
|
||||||
|
Common.start_pleroma()
|
||||||
|
|
||||||
|
with %User{} = user <- User.get_by_nickname(nickname) do
|
||||||
|
user = user |> User.untag(tags)
|
||||||
|
|
||||||
|
Mix.shell().info("Tags of #{user.nickname}: #{inspect(tags)}")
|
||||||
|
else
|
||||||
|
_ ->
|
||||||
|
Mix.shell().error("Could not change user tags for #{nickname}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def run(["invite"]) do
|
def run(["invite"]) do
|
||||||
Common.start_pleroma()
|
Common.start_pleroma()
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,10 @@ def check_frontend_config_mechanism() do
|
||||||
You are using the old configuration mechanism for the frontend. Please check config.md.
|
You are using the old configuration mechanism for the frontend. Please check config.md.
|
||||||
""")
|
""")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if Pleroma.Config.get(:mrf_hellthread, :threshold) do
|
def check_hellthread_threshold do
|
||||||
|
if Pleroma.Config.get([:mrf_hellthread, :threshold]) do
|
||||||
Logger.warn("""
|
Logger.warn("""
|
||||||
!!!DEPRECATION WARNING!!!
|
!!!DEPRECATION WARNING!!!
|
||||||
You are using the old configuration mechanism for the hellthread filter. Please check config.md.
|
You are using the old configuration mechanism for the hellthread filter. Please check config.md.
|
||||||
|
@ -23,5 +25,6 @@ def check_frontend_config_mechanism() do
|
||||||
|
|
||||||
def warn do
|
def warn do
|
||||||
check_frontend_config_mechanism()
|
check_frontend_config_mechanism()
|
||||||
|
check_hellthread_threshold()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -59,6 +59,8 @@ defp generate_scrubber_signature(scrubbers) do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def extract_first_external_url(_, nil), do: {:error, "No content"}
|
||||||
|
|
||||||
def extract_first_external_url(object, content) do
|
def extract_first_external_url(object, content) do
|
||||||
key = "URL|#{object.id}"
|
key = "URL|#{object.id}"
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ defmodule Pleroma.User.Info do
|
||||||
field(:ap_enabled, :boolean, default: false)
|
field(:ap_enabled, :boolean, default: false)
|
||||||
field(:is_moderator, :boolean, default: false)
|
field(:is_moderator, :boolean, default: false)
|
||||||
field(:is_admin, :boolean, default: false)
|
field(:is_admin, :boolean, default: false)
|
||||||
|
field(:show_role, :boolean, default: true)
|
||||||
field(:keys, :string, default: nil)
|
field(:keys, :string, default: nil)
|
||||||
field(:settings, :map, default: nil)
|
field(:settings, :map, default: nil)
|
||||||
field(:magic_key, :string, default: nil)
|
field(:magic_key, :string, default: nil)
|
||||||
|
@ -30,7 +31,8 @@ defmodule Pleroma.User.Info do
|
||||||
field(:topic, :string, default: nil)
|
field(:topic, :string, default: nil)
|
||||||
field(:hub, :string, default: nil)
|
field(:hub, :string, default: nil)
|
||||||
field(:salmon, :string, default: nil)
|
field(:salmon, :string, default: nil)
|
||||||
field(:hide_network, :boolean, default: false)
|
field(:hide_followers, :boolean, default: false)
|
||||||
|
field(:hide_follows, :boolean, default: false)
|
||||||
field(:pinned_activities, {:array, :string}, default: [])
|
field(:pinned_activities, {:array, :string}, default: [])
|
||||||
|
|
||||||
# Found in the wild
|
# Found in the wild
|
||||||
|
@ -143,8 +145,10 @@ def profile_update(info, params) do
|
||||||
:no_rich_text,
|
:no_rich_text,
|
||||||
:default_scope,
|
:default_scope,
|
||||||
:banner,
|
:banner,
|
||||||
:hide_network,
|
:hide_follows,
|
||||||
:background
|
:hide_followers,
|
||||||
|
:background,
|
||||||
|
:show_role
|
||||||
])
|
])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -194,7 +198,8 @@ def admin_api_update(info, params) do
|
||||||
info
|
info
|
||||||
|> cast(params, [
|
|> cast(params, [
|
||||||
:is_moderator,
|
:is_moderator,
|
||||||
:is_admin
|
:is_admin,
|
||||||
|
:show_role
|
||||||
])
|
])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -521,7 +521,7 @@ defp restrict_actor(query, %{"actor_id" => actor_id}) do
|
||||||
defp restrict_actor(query, _), do: query
|
defp restrict_actor(query, _), do: query
|
||||||
|
|
||||||
defp restrict_type(query, %{"type" => type}) when is_binary(type) do
|
defp restrict_type(query, %{"type" => type}) when is_binary(type) do
|
||||||
restrict_type(query, %{"type" => [type]})
|
from(activity in query, where: fragment("?->>'type' = ?", activity.data, ^type))
|
||||||
end
|
end
|
||||||
|
|
||||||
defp restrict_type(query, %{"type" => type}) do
|
defp restrict_type(query, %{"type" => type}) do
|
||||||
|
|
|
@ -198,6 +198,14 @@ def relay(conn, _params) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def whoami(%{assigns: %{user: %User{} = user}} = conn, _params) do
|
||||||
|
conn
|
||||||
|
|> put_resp_header("content-type", "application/activity+json")
|
||||||
|
|> json(UserView.render("user.json", %{user: user}))
|
||||||
|
end
|
||||||
|
|
||||||
|
def whoami(_conn, _params), do: {:error, :not_found}
|
||||||
|
|
||||||
def read_inbox(%{assigns: %{user: user}} = conn, %{"nickname" => nickname} = params) do
|
def read_inbox(%{assigns: %{user: user}} = conn, %{"nickname" => nickname} = params) do
|
||||||
if nickname == user.nickname do
|
if nickname == user.nickname do
|
||||||
conn
|
conn
|
||||||
|
|
139
lib/pleroma/web/activity_pub/mrf/tag_policy.ex
Normal file
139
lib/pleroma/web/activity_pub/mrf/tag_policy.ex
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
|
||||||
|
alias Pleroma.User
|
||||||
|
@behaviour Pleroma.Web.ActivityPub.MRF
|
||||||
|
|
||||||
|
defp get_tags(%User{tags: tags}) when is_list(tags), do: tags
|
||||||
|
defp get_tags(_), do: []
|
||||||
|
|
||||||
|
defp process_tag(
|
||||||
|
"mrf_tag:media-force-nsfw",
|
||||||
|
%{"type" => "Create", "object" => %{"attachment" => child_attachment} = object} = message
|
||||||
|
)
|
||||||
|
when length(child_attachment) > 0 do
|
||||||
|
tags = (object["tag"] || []) ++ ["nsfw"]
|
||||||
|
|
||||||
|
object =
|
||||||
|
object
|
||||||
|
|> Map.put("tags", tags)
|
||||||
|
|> Map.put("sensitive", true)
|
||||||
|
|
||||||
|
message = Map.put(message, "object", object)
|
||||||
|
|
||||||
|
{:ok, message}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp process_tag(
|
||||||
|
"mrf_tag:media-strip",
|
||||||
|
%{"type" => "Create", "object" => %{"attachment" => child_attachment} = object} = message
|
||||||
|
)
|
||||||
|
when length(child_attachment) > 0 do
|
||||||
|
object = Map.delete(object, "attachment")
|
||||||
|
message = Map.put(message, "object", object)
|
||||||
|
|
||||||
|
{:ok, message}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp process_tag(
|
||||||
|
"mrf_tag:force-unlisted",
|
||||||
|
%{"type" => "Create", "to" => to, "cc" => cc, "actor" => actor} = message
|
||||||
|
) do
|
||||||
|
user = User.get_cached_by_ap_id(actor)
|
||||||
|
|
||||||
|
if Enum.member?(to, "https://www.w3.org/ns/activitystreams#Public") do
|
||||||
|
to =
|
||||||
|
List.delete(to, "https://www.w3.org/ns/activitystreams#Public") ++ [user.follower_address]
|
||||||
|
|
||||||
|
cc =
|
||||||
|
List.delete(cc, user.follower_address) ++ ["https://www.w3.org/ns/activitystreams#Public"]
|
||||||
|
|
||||||
|
object =
|
||||||
|
message["object"]
|
||||||
|
|> Map.put("to", to)
|
||||||
|
|> Map.put("cc", cc)
|
||||||
|
|
||||||
|
message =
|
||||||
|
message
|
||||||
|
|> Map.put("to", to)
|
||||||
|
|> Map.put("cc", cc)
|
||||||
|
|> Map.put("object", object)
|
||||||
|
|
||||||
|
{:ok, message}
|
||||||
|
else
|
||||||
|
{:ok, message}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp process_tag(
|
||||||
|
"mrf_tag:sandbox",
|
||||||
|
%{"type" => "Create", "to" => to, "cc" => cc, "actor" => actor} = message
|
||||||
|
) do
|
||||||
|
user = User.get_cached_by_ap_id(actor)
|
||||||
|
|
||||||
|
if Enum.member?(to, "https://www.w3.org/ns/activitystreams#Public") or
|
||||||
|
Enum.member?(cc, "https://www.w3.org/ns/activitystreams#Public") do
|
||||||
|
to =
|
||||||
|
List.delete(to, "https://www.w3.org/ns/activitystreams#Public") ++ [user.follower_address]
|
||||||
|
|
||||||
|
cc = List.delete(cc, "https://www.w3.org/ns/activitystreams#Public")
|
||||||
|
|
||||||
|
object =
|
||||||
|
message["object"]
|
||||||
|
|> Map.put("to", to)
|
||||||
|
|> Map.put("cc", cc)
|
||||||
|
|
||||||
|
message =
|
||||||
|
message
|
||||||
|
|> Map.put("to", to)
|
||||||
|
|> Map.put("cc", cc)
|
||||||
|
|> Map.put("object", object)
|
||||||
|
|
||||||
|
{:ok, message}
|
||||||
|
else
|
||||||
|
{:ok, message}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp process_tag(
|
||||||
|
"mrf_tag:disable-remote-subscription",
|
||||||
|
%{"type" => "Follow", "actor" => actor} = message
|
||||||
|
) do
|
||||||
|
user = User.get_cached_by_ap_id(actor)
|
||||||
|
|
||||||
|
if user.local == true do
|
||||||
|
{:ok, message}
|
||||||
|
else
|
||||||
|
{:reject, nil}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp process_tag("mrf_tag:disable-any-subscription", %{"type" => "Follow"}), do: {:reject, nil}
|
||||||
|
|
||||||
|
defp process_tag(_, message), do: {:ok, message}
|
||||||
|
|
||||||
|
def filter_message(actor, message) do
|
||||||
|
User.get_cached_by_ap_id(actor)
|
||||||
|
|> get_tags()
|
||||||
|
|> Enum.reduce({:ok, message}, fn
|
||||||
|
tag, {:ok, message} ->
|
||||||
|
process_tag(tag, message)
|
||||||
|
|
||||||
|
_, error ->
|
||||||
|
error
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def filter(%{"object" => target_actor, "type" => "Follow"} = message),
|
||||||
|
do: filter_message(target_actor, message)
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def filter(%{"actor" => actor, "type" => "Create"} = message),
|
||||||
|
do: filter_message(actor, message)
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def filter(message), do: {:ok, message}
|
||||||
|
end
|
|
@ -313,6 +313,8 @@ def fix_tag(%{"tag" => %{"type" => "Hashtag", "name" => hashtag} = tag} = object
|
||||||
|> Map.put("tag", combined)
|
|> Map.put("tag", combined)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def fix_tag(%{"tag" => %{} = tag} = object), do: Map.put(object, "tag", [tag])
|
||||||
|
|
||||||
def fix_tag(object), do: object
|
def fix_tag(object), do: object
|
||||||
|
|
||||||
# content map usually only has one language so this will do for now.
|
# content map usually only has one language so this will do for now.
|
||||||
|
|
|
@ -86,7 +86,7 @@ def render("following.json", %{user: user, page: page}) do
|
||||||
query = from(user in query, select: [:ap_id])
|
query = from(user in query, select: [:ap_id])
|
||||||
following = Repo.all(query)
|
following = Repo.all(query)
|
||||||
|
|
||||||
collection(following, "#{user.ap_id}/following", page, !user.info.hide_network)
|
collection(following, "#{user.ap_id}/following", page, !user.info.hide_follows)
|
||||||
|> Map.merge(Utils.make_json_ld_header())
|
|> Map.merge(Utils.make_json_ld_header())
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ def render("following.json", %{user: user}) do
|
||||||
"id" => "#{user.ap_id}/following",
|
"id" => "#{user.ap_id}/following",
|
||||||
"type" => "OrderedCollection",
|
"type" => "OrderedCollection",
|
||||||
"totalItems" => length(following),
|
"totalItems" => length(following),
|
||||||
"first" => collection(following, "#{user.ap_id}/following", 1, !user.info.hide_network)
|
"first" => collection(following, "#{user.ap_id}/following", 1, !user.info.hide_follows)
|
||||||
}
|
}
|
||||||
|> Map.merge(Utils.make_json_ld_header())
|
|> Map.merge(Utils.make_json_ld_header())
|
||||||
end
|
end
|
||||||
|
@ -109,7 +109,7 @@ def render("followers.json", %{user: user, page: page}) do
|
||||||
query = from(user in query, select: [:ap_id])
|
query = from(user in query, select: [:ap_id])
|
||||||
followers = Repo.all(query)
|
followers = Repo.all(query)
|
||||||
|
|
||||||
collection(followers, "#{user.ap_id}/followers", page, !user.info.hide_network)
|
collection(followers, "#{user.ap_id}/followers", page, !user.info.hide_followers)
|
||||||
|> Map.merge(Utils.make_json_ld_header())
|
|> Map.merge(Utils.make_json_ld_header())
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ def render("followers.json", %{user: user}) do
|
||||||
"id" => "#{user.ap_id}/followers",
|
"id" => "#{user.ap_id}/followers",
|
||||||
"type" => "OrderedCollection",
|
"type" => "OrderedCollection",
|
||||||
"totalItems" => length(followers),
|
"totalItems" => length(followers),
|
||||||
"first" => collection(followers, "#{user.ap_id}/followers", 1, !user.info.hide_network)
|
"first" => collection(followers, "#{user.ap_id}/followers", 1, !user.info.hide_followers)
|
||||||
}
|
}
|
||||||
|> Map.merge(Utils.make_json_ld_header())
|
|> Map.merge(Utils.make_json_ld_header())
|
||||||
end
|
end
|
||||||
|
@ -239,6 +239,8 @@ def collection(collection, iri, page, show_items \\ true, total \\ nil) do
|
||||||
|
|
||||||
if offset < total do
|
if offset < total do
|
||||||
Map.put(map, "next", "#{iri}?page=#{page + 1}")
|
Map.put(map, "next", "#{iri}?page=#{page + 1}")
|
||||||
|
else
|
||||||
|
map
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -605,7 +605,7 @@ def followers(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do
|
||||||
followers =
|
followers =
|
||||||
cond do
|
cond do
|
||||||
for_user && user.id == for_user.id -> followers
|
for_user && user.id == for_user.id -> followers
|
||||||
user.info.hide_network -> []
|
user.info.hide_followers -> []
|
||||||
true -> followers
|
true -> followers
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -621,7 +621,7 @@ def following(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do
|
||||||
followers =
|
followers =
|
||||||
cond do
|
cond do
|
||||||
for_user && user.id == for_user.id -> followers
|
for_user && user.id == for_user.id -> followers
|
||||||
user.info.hide_network -> []
|
user.info.hide_follows -> []
|
||||||
true -> followers
|
true -> followers
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -182,18 +182,24 @@ def render("status.json", _) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def render("card.json", %{rich_media: rich_media, page_url: page_url}) do
|
def render("card.json", %{rich_media: rich_media, page_url: page_url}) do
|
||||||
|
page_url_data = URI.parse(page_url)
|
||||||
|
|
||||||
page_url_data =
|
page_url_data =
|
||||||
if rich_media[:url] != nil do
|
if rich_media[:url] != nil do
|
||||||
URI.merge(URI.parse(page_url), URI.parse(rich_media[:url]))
|
URI.merge(page_url_data, URI.parse(rich_media[:url]))
|
||||||
else
|
else
|
||||||
page_url
|
page_url_data
|
||||||
end
|
end
|
||||||
|
|
||||||
page_url = page_url_data |> to_string
|
page_url = page_url_data |> to_string
|
||||||
|
|
||||||
image_url =
|
image_url =
|
||||||
|
if rich_media[:image] != nil do
|
||||||
URI.merge(page_url_data, URI.parse(rich_media[:image]))
|
URI.merge(page_url_data, URI.parse(rich_media[:image]))
|
||||||
|> to_string
|
|> to_string
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
site_name = rich_media[:site_name] || page_url_data.host
|
site_name = rich_media[:site_name] || page_url_data.host
|
||||||
|
|
||||||
|
|
|
@ -54,22 +54,12 @@ defp check_parsed_data(data) do
|
||||||
{:error, "Found metadata was invalid or incomplete: #{inspect(data)}"}
|
{:error, "Found metadata was invalid or incomplete: #{inspect(data)}"}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp string_is_valid_unicode(data) when is_binary(data) do
|
|
||||||
data
|
|
||||||
|> :unicode.characters_to_binary()
|
|
||||||
|> clean_string()
|
|
||||||
end
|
|
||||||
|
|
||||||
defp string_is_valid_unicode(data), do: {:ok, data}
|
|
||||||
|
|
||||||
defp clean_string({:error, _, _}), do: {:error, "Invalid data"}
|
|
||||||
defp clean_string(data), do: {:ok, data}
|
|
||||||
|
|
||||||
defp clean_parsed_data(data) do
|
defp clean_parsed_data(data) do
|
||||||
data
|
data
|
||||||
|> Enum.reject(fn {_, val} ->
|
|> Enum.reject(fn {key, val} ->
|
||||||
case string_is_valid_unicode(val) do
|
with {:ok, _} <- Jason.encode(%{key => val}) do
|
||||||
{:ok, _} -> false
|
false
|
||||||
|
else
|
||||||
_ -> true
|
_ -> true
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -454,6 +454,7 @@ defmodule Pleroma.Web.Router do
|
||||||
scope "/", Pleroma.Web.ActivityPub do
|
scope "/", Pleroma.Web.ActivityPub do
|
||||||
pipe_through([:activitypub_client])
|
pipe_through([:activitypub_client])
|
||||||
|
|
||||||
|
get("/api/ap/whoami", ActivityPubController, :whoami)
|
||||||
get("/users/:nickname/inbox", ActivityPubController, :read_inbox)
|
get("/users/:nickname/inbox", ActivityPubController, :read_inbox)
|
||||||
post("/users/:nickname/outbox", ActivityPubController, :update_outbox)
|
post("/users/:nickname/outbox", ActivityPubController, :update_outbox)
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,7 +24,7 @@ def verify_credentials(%{assigns: %{user: user}} = conn, _params) do
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_view(UserView)
|
|> put_view(UserView)
|
||||||
|> render("show.json", %{user: user, token: token})
|
|> render("show.json", %{user: user, token: token, for: user})
|
||||||
end
|
end
|
||||||
|
|
||||||
def status_update(%{assigns: %{user: user}} = conn, %{"status" => _} = status_data) do
|
def status_update(%{assigns: %{user: user}} = conn, %{"status" => _} = status_data) do
|
||||||
|
@ -503,7 +503,7 @@ def followers(%{assigns: %{user: for_user}} = conn, params) do
|
||||||
followers =
|
followers =
|
||||||
cond do
|
cond do
|
||||||
for_user && user.id == for_user.id -> followers
|
for_user && user.id == for_user.id -> followers
|
||||||
user.info.hide_network -> []
|
user.info.hide_followers -> []
|
||||||
true -> followers
|
true -> followers
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -523,7 +523,7 @@ def friends(%{assigns: %{user: for_user}} = conn, params) do
|
||||||
friends =
|
friends =
|
||||||
cond do
|
cond do
|
||||||
for_user && user.id == for_user.id -> friends
|
for_user && user.id == for_user.id -> friends
|
||||||
user.info.hide_network -> []
|
user.info.hide_follows -> []
|
||||||
true -> friends
|
true -> friends
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -618,7 +618,7 @@ def raw_empty_array(conn, _params) do
|
||||||
|
|
||||||
defp build_info_cng(user, params) do
|
defp build_info_cng(user, params) do
|
||||||
info_params =
|
info_params =
|
||||||
["no_rich_text", "locked", "hide_network"]
|
["no_rich_text", "locked", "hide_followers", "hide_follows", "show_role"]
|
||||||
|> Enum.reduce(%{}, fn key, res ->
|
|> Enum.reduce(%{}, fn key, res ->
|
||||||
if value = params[key] do
|
if value = params[key] do
|
||||||
Map.put(res, key, value == "true")
|
Map.put(res, key, value == "true")
|
||||||
|
|
|
@ -108,7 +108,8 @@ defp do_render("user.json", %{user: user = %User{}} = assigns) do
|
||||||
"locked" => user.info.locked,
|
"locked" => user.info.locked,
|
||||||
"default_scope" => user.info.default_scope,
|
"default_scope" => user.info.default_scope,
|
||||||
"no_rich_text" => user.info.no_rich_text,
|
"no_rich_text" => user.info.no_rich_text,
|
||||||
"hide_network" => user.info.hide_network,
|
"hide_followers" => user.info.hide_followers,
|
||||||
|
"hide_follows" => user.info.hide_follows,
|
||||||
"fields" => fields,
|
"fields" => fields,
|
||||||
|
|
||||||
# Pleroma extension
|
# Pleroma extension
|
||||||
|
@ -118,6 +119,12 @@ defp do_render("user.json", %{user: user = %User{}} = assigns) do
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data =
|
||||||
|
if(user.info.is_admin || user.info.is_moderator,
|
||||||
|
do: maybe_with_role(data, user, for_user),
|
||||||
|
else: data
|
||||||
|
)
|
||||||
|
|
||||||
if assigns[:token] do
|
if assigns[:token] do
|
||||||
Map.put(data, "token", token_string(assigns[:token]))
|
Map.put(data, "token", token_string(assigns[:token]))
|
||||||
else
|
else
|
||||||
|
@ -125,6 +132,20 @@ defp do_render("user.json", %{user: user = %User{}} = assigns) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp maybe_with_role(data, %User{id: id} = user, %User{id: id}) do
|
||||||
|
Map.merge(data, %{"role" => role(user), "show_role" => user.info.show_role})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_with_role(data, %User{info: %{show_role: true}} = user, _user) do
|
||||||
|
Map.merge(data, %{"role" => role(user)})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_with_role(data, _, _), do: data
|
||||||
|
|
||||||
|
defp role(%User{info: %{:is_admin => true}}), do: "admin"
|
||||||
|
defp role(%User{info: %{:is_moderator => true}}), do: "moderator"
|
||||||
|
defp role(_), do: "member"
|
||||||
|
|
||||||
defp image_url(%{"url" => [%{"href" => href} | _]}), do: href
|
defp image_url(%{"url" => [%{"href" => href} | _]}), do: href
|
||||||
defp image_url(_), do: nil
|
defp image_url(_), do: nil
|
||||||
|
|
||||||
|
|
12
priv/repo/migrations/20190203185340_split_hide_network.exs
Normal file
12
priv/repo/migrations/20190203185340_split_hide_network.exs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.SplitHideNetwork do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
execute("UPDATE users SET info = jsonb_set(info, '{hide_network}'::text[], 'false'::jsonb) WHERE NOT(info::jsonb ? 'hide_network')")
|
||||||
|
execute("UPDATE users SET info = jsonb_set(info, '{hide_followings}'::text[], info->'hide_network')")
|
||||||
|
execute("UPDATE users SET info = jsonb_set(info, '{hide_followers}'::text[], info->'hide_network')")
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
end
|
||||||
|
end
|
30
priv/repo/migrations/20190204200237_add_correct_dm_index.exs
Normal file
30
priv/repo/migrations/20190204200237_add_correct_dm_index.exs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.AddCorrectDMIndex do
|
||||||
|
use Ecto.Migration
|
||||||
|
@disable_ddl_transaction true
|
||||||
|
|
||||||
|
def up do
|
||||||
|
drop_if_exists(
|
||||||
|
index(:activities, ["activity_visibility(actor, recipients, data)"],
|
||||||
|
name: :activities_visibility_index
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
create(
|
||||||
|
index(:activities, ["activity_visibility(actor, recipients, data)", "id DESC NULLS LAST"],
|
||||||
|
name: :activities_visibility_index,
|
||||||
|
concurrently: true,
|
||||||
|
where: "data->>'type' = 'Create'"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
drop(
|
||||||
|
index(:activities, ["activity_visibility(actor, recipients, data)", "id DESC"],
|
||||||
|
name: :activities_visibility_index,
|
||||||
|
concurrently: true,
|
||||||
|
where: "data->>'type' = 'Create'"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1 +1 @@
|
||||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link rel=stylesheet href=/static/font/css/fontello.css><link rel=stylesheet href=/static/font/css/animation.css><link href=/static/css/app.42c43da15d7ab16ad8e42d21fcfc5a43.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.6aa5664a1a2c0832ce7b.js></script><script type=text/javascript src=/static/js/vendor.56a115a1d7339d6811a0.js></script><script type=text/javascript src=/static/js/app.59ebcfb47f86a7a5ba3f.js></script></body></html>
|
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link rel=stylesheet href=/static/font/css/fontello.css><link rel=stylesheet href=/static/font/css/animation.css><link href=/static/css/app.d75cda10f04aeefec7b657f8244070e9.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.f00ab54db04706aab2c9.js></script><script type=text/javascript src=/static/js/vendor.5173dfeead1ded3d1f46.js></script><script type=text/javascript src=/static/js/app.0e4952ec8d775da840f1.js></script></body></html>
|
|
@ -19,8 +19,5 @@
|
||||||
"loginMethod": "password",
|
"loginMethod": "password",
|
||||||
"webPushNotifications": false,
|
"webPushNotifications": false,
|
||||||
"noAttachmentLinks": false,
|
"noAttachmentLinks": false,
|
||||||
"nsfwCensorImage": "",
|
"nsfwCensorImage": ""
|
||||||
"useOneClickNsfw": true,
|
|
||||||
"playVideosInline": false,
|
|
||||||
"useContainFit": false
|
|
||||||
}
|
}
|
||||||
|
|
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
16
priv/static/static/js/app.0e4952ec8d775da840f1.js
Normal file
16
priv/static/static/js/app.0e4952ec8d775da840f1.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/static/js/app.0e4952ec8d775da840f1.js.map
Normal file
1
priv/static/static/js/app.0e4952ec8d775da840f1.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
|
@ -1,2 +0,0 @@
|
||||||
!function(e){function t(a){if(r[a])return r[a].exports;var n=r[a]={exports:{},id:a,loaded:!1};return e[a].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var a=window.webpackJsonp;window.webpackJsonp=function(o,p){for(var c,l,s=0,i=[];s<o.length;s++)l=o[s],n[l]&&i.push.apply(i,n[l]),n[l]=0;for(c in p)Object.prototype.hasOwnProperty.call(p,c)&&(e[c]=p[c]);for(a&&a(o,p);i.length;)i.shift().call(null,t);if(p[0])return r[0]=0,t(0)};var r={},n={0:0};t.e=function(e,a){if(0===n[e])return a.call(null,t);if(void 0!==n[e])n[e].push(a);else{n[e]=[a];var r=document.getElementsByTagName("head")[0],o=document.createElement("script");o.type="text/javascript",o.charset="utf-8",o.async=!0,o.src=t.p+"static/js/"+e+"."+{1:"56a115a1d7339d6811a0",2:"59ebcfb47f86a7a5ba3f"}[e]+".js",r.appendChild(o)}},t.m=e,t.c=r,t.p="/"}([]);
|
|
||||||
//# sourceMappingURL=manifest.6aa5664a1a2c0832ce7b.js.map
|
|
2
priv/static/static/js/manifest.f00ab54db04706aab2c9.js
Normal file
2
priv/static/static/js/manifest.f00ab54db04706aab2c9.js
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
!function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={exports:{},id:r,loaded:!1};return e[r].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var r=window.webpackJsonp;window.webpackJsonp=function(o,p){for(var c,l,s=0,d=[];s<o.length;s++)l=o[s],a[l]&&d.push.apply(d,a[l]),a[l]=0;for(c in p)Object.prototype.hasOwnProperty.call(p,c)&&(e[c]=p[c]);for(r&&r(o,p);d.length;)d.shift().call(null,t);if(p[0])return n[0]=0,t(0)};var n={},a={0:0};t.e=function(e,r){if(0===a[e])return r.call(null,t);if(void 0!==a[e])a[e].push(r);else{a[e]=[r];var n=document.getElementsByTagName("head")[0],o=document.createElement("script");o.type="text/javascript",o.charset="utf-8",o.async=!0,o.src=t.p+"static/js/"+e+"."+{1:"5173dfeead1ded3d1f46",2:"0e4952ec8d775da840f1"}[e]+".js",n.appendChild(o)}},t.m=e,t.c=n,t.p="/"}([]);
|
||||||
|
//# sourceMappingURL=manifest.f00ab54db04706aab2c9.js.map
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
priv/static/static/js/vendor.5173dfeead1ded3d1f46.js.map
Normal file
1
priv/static/static/js/vendor.5173dfeead1ded3d1f46.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
|
@ -1,4 +1,4 @@
|
||||||
var serviceWorkerOption = {"assets":["/static/img/nsfw.74818f9.png","/static/js/manifest.6aa5664a1a2c0832ce7b.js","/static/js/vendor.56a115a1d7339d6811a0.js","/static/js/app.59ebcfb47f86a7a5ba3f.js","/static/css/app.42c43da15d7ab16ad8e42d21fcfc5a43.css"]};
|
var serviceWorkerOption = {"assets":["/static/img/nsfw.74818f9.png","/static/js/manifest.f00ab54db04706aab2c9.js","/static/js/vendor.5173dfeead1ded3d1f46.js","/static/js/app.0e4952ec8d775da840f1.js","/static/css/app.d75cda10f04aeefec7b657f8244070e9.css"]};
|
||||||
|
|
||||||
!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,n),o.loaded=!0,o.exports}var t={};return n.m=e,n.c=t,n.p="/",n(0)}([function(e,n,t){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(){return u.default.getItem("vuex-lz").then(function(e){return e.config.webPushNotifications})}function i(){return clients.matchAll({includeUncontrolled:!0}).then(function(e){return e.filter(function(e){var n=e.type;return"window"===n})})}var a=t(1),u=r(a);self.addEventListener("push",function(e){e.data&&e.waitUntil(o().then(function(n){return n&&i().then(function(n){var t=e.data.json();if(0===n.length)return self.registration.showNotification(t.title,t)})}))}),self.addEventListener("notificationclick",function(e){e.notification.close(),e.waitUntil(i().then(function(e){for(var n=0;n<e.length;n++){var t=e[n];if("/"===t.url&&"focus"in t)return t.focus()}if(clients.openWindow)return clients.openWindow("/")}))})},function(e,n){/*!
|
!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,n),o.loaded=!0,o.exports}var t={};return n.m=e,n.c=t,n.p="/",n(0)}([function(e,n,t){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(){return u.default.getItem("vuex-lz").then(function(e){return e.config.webPushNotifications})}function i(){return clients.matchAll({includeUncontrolled:!0}).then(function(e){return e.filter(function(e){var n=e.type;return"window"===n})})}var a=t(1),u=r(a);self.addEventListener("push",function(e){e.data&&e.waitUntil(o().then(function(n){return n&&i().then(function(n){var t=e.data.json();if(0===n.length)return self.registration.showNotification(t.title,t)})}))}),self.addEventListener("notificationclick",function(e){e.notification.close(),e.waitUntil(i().then(function(e){for(var n=0;n<e.length;n++){var t=e[n];if("/"===t.url&&"focus"in t)return t.focus()}if(clients.openWindow)return clients.openWindow("/")}))})},function(e,n){/*!
|
||||||
localForage -- Offline Storage, Improved
|
localForage -- Offline Storage, Improved
|
||||||
|
|
File diff suppressed because one or more lines are too long
1
priv/static/sw.js.map
Normal file
1
priv/static/sw.js.map
Normal file
File diff suppressed because one or more lines are too long
|
@ -386,9 +386,9 @@ test "it returns the followers in a collection", %{conn: conn} do
|
||||||
assert result["first"]["orderedItems"] == [user.ap_id]
|
assert result["first"]["orderedItems"] == [user.ap_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns returns empty if the user has 'hide_network' set", %{conn: conn} do
|
test "it returns returns empty if the user has 'hide_followers' set", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
user_two = insert(:user, %{info: %{hide_network: true}})
|
user_two = insert(:user, %{info: %{hide_followers: true}})
|
||||||
User.follow(user, user_two)
|
User.follow(user, user_two)
|
||||||
|
|
||||||
result =
|
result =
|
||||||
|
@ -441,8 +441,8 @@ test "it returns the following in a collection", %{conn: conn} do
|
||||||
assert result["first"]["orderedItems"] == [user_two.ap_id]
|
assert result["first"]["orderedItems"] == [user_two.ap_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns returns empty if the user has 'hide_network' set", %{conn: conn} do
|
test "it returns returns empty if the user has 'hide_follows' set", %{conn: conn} do
|
||||||
user = insert(:user, %{info: %{hide_network: true}})
|
user = insert(:user, %{info: %{hide_follows: true}})
|
||||||
user_two = insert(:user)
|
user_two = insert(:user)
|
||||||
User.follow(user, user_two)
|
User.follow(user, user_two)
|
||||||
|
|
||||||
|
|
|
@ -1101,9 +1101,9 @@ test "getting followers", %{conn: conn} do
|
||||||
assert id == to_string(user.id)
|
assert id == to_string(user.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "getting followers, hide_network", %{conn: conn} do
|
test "getting followers, hide_followers", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
other_user = insert(:user, %{info: %{hide_network: true}})
|
other_user = insert(:user, %{info: %{hide_followers: true}})
|
||||||
{:ok, _user} = User.follow(user, other_user)
|
{:ok, _user} = User.follow(user, other_user)
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
|
@ -1113,9 +1113,9 @@ test "getting followers, hide_network", %{conn: conn} do
|
||||||
assert [] == json_response(conn, 200)
|
assert [] == json_response(conn, 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "getting followers, hide_network, same user requesting", %{conn: conn} do
|
test "getting followers, hide_followers, same user requesting", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
other_user = insert(:user, %{info: %{hide_network: true}})
|
other_user = insert(:user, %{info: %{hide_followers: true}})
|
||||||
{:ok, _user} = User.follow(user, other_user)
|
{:ok, _user} = User.follow(user, other_user)
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
|
@ -1139,8 +1139,8 @@ test "getting following", %{conn: conn} do
|
||||||
assert id == to_string(other_user.id)
|
assert id == to_string(other_user.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "getting following, hide_network", %{conn: conn} do
|
test "getting following, hide_follows", %{conn: conn} do
|
||||||
user = insert(:user, %{info: %{hide_network: true}})
|
user = insert(:user, %{info: %{hide_follows: true}})
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
{:ok, user} = User.follow(user, other_user)
|
{:ok, user} = User.follow(user, other_user)
|
||||||
|
|
||||||
|
@ -1151,8 +1151,8 @@ test "getting following, hide_network", %{conn: conn} do
|
||||||
assert [] == json_response(conn, 200)
|
assert [] == json_response(conn, 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "getting following, hide_network, same user requesting", %{conn: conn} do
|
test "getting following, hide_follows, same user requesting", %{conn: conn} do
|
||||||
user = insert(:user, %{info: %{hide_network: true}})
|
user = insert(:user, %{info: %{hide_follows: true}})
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
{:ok, user} = User.follow(user, other_user)
|
{:ok, user} = User.follow(user, other_user)
|
||||||
|
|
||||||
|
|
|
@ -235,4 +235,59 @@ test "it returns a a dictionary tags" do
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "rich media cards" do
|
||||||
|
test "a rich media card without a site name renders correctly" do
|
||||||
|
page_url = "http://example.com"
|
||||||
|
|
||||||
|
card = %{
|
||||||
|
url: page_url,
|
||||||
|
image: page_url <> "/example.jpg",
|
||||||
|
title: "Example website"
|
||||||
|
}
|
||||||
|
|
||||||
|
%{provider_name: "example.com"} =
|
||||||
|
StatusView.render("card.json", %{page_url: page_url, rich_media: card})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "a rich media card without a site name or image renders correctly" do
|
||||||
|
page_url = "http://example.com"
|
||||||
|
|
||||||
|
card = %{
|
||||||
|
url: page_url,
|
||||||
|
title: "Example website"
|
||||||
|
}
|
||||||
|
|
||||||
|
%{provider_name: "example.com"} =
|
||||||
|
StatusView.render("card.json", %{page_url: page_url, rich_media: card})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "a rich media card without an image renders correctly" do
|
||||||
|
page_url = "http://example.com"
|
||||||
|
|
||||||
|
card = %{
|
||||||
|
url: page_url,
|
||||||
|
site_name: "Example site name",
|
||||||
|
title: "Example website"
|
||||||
|
}
|
||||||
|
|
||||||
|
%{provider_name: "Example site name"} =
|
||||||
|
StatusView.render("card.json", %{page_url: page_url, rich_media: card})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "a rich media card with all relevant data renders correctly" do
|
||||||
|
page_url = "http://example.com"
|
||||||
|
|
||||||
|
card = %{
|
||||||
|
url: page_url,
|
||||||
|
site_name: "Example site name",
|
||||||
|
title: "Example website",
|
||||||
|
image: page_url <> "/example.jpg",
|
||||||
|
description: "Example description"
|
||||||
|
}
|
||||||
|
|
||||||
|
%{provider_name: "Example site name"} =
|
||||||
|
StatusView.render("card.json", %{page_url: page_url, rich_media: card})
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -62,7 +62,8 @@ test "with credentials", %{conn: conn, user: user} do
|
||||||
|> post("/api/account/verify_credentials.json")
|
|> post("/api/account/verify_credentials.json")
|
||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
assert response == UserView.render("show.json", %{user: user, token: response["token"]})
|
assert response ==
|
||||||
|
UserView.render("show.json", %{user: user, token: response["token"], for: user})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -107,7 +108,7 @@ test "with credentials", %{conn: conn, user: user} do
|
||||||
|> post(request_path, %{status: "Nice meme.", visibility: "private"})
|
|> post(request_path, %{status: "Nice meme.", visibility: "private"})
|
||||||
|
|
||||||
assert json_response(conn, 200) ==
|
assert json_response(conn, 200) ==
|
||||||
ActivityRepresenter.to_map(Repo.one(Activity), %{user: user})
|
ActivityRepresenter.to_map(Repo.one(Activity), %{user: user, for: user})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -418,6 +419,7 @@ test "with credentials", %{conn: conn, user: current_user} do
|
||||||
assert Enum.at(response, 0) ==
|
assert Enum.at(response, 0) ==
|
||||||
ActivityRepresenter.to_map(activity, %{
|
ActivityRepresenter.to_map(activity, %{
|
||||||
user: current_user,
|
user: current_user,
|
||||||
|
for: current_user,
|
||||||
mentioned: [current_user]
|
mentioned: [current_user]
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
@ -547,7 +549,9 @@ test "with credentials", %{conn: conn, user: current_user} do
|
||||||
response = json_response(conn, 200)
|
response = json_response(conn, 200)
|
||||||
|
|
||||||
assert length(response) == 1
|
assert length(response) == 1
|
||||||
assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: current_user})
|
|
||||||
|
assert Enum.at(response, 0) ==
|
||||||
|
ActivityRepresenter.to_map(activity, %{user: current_user, for: current_user})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "with credentials with user_id", %{conn: conn, user: current_user} do
|
test "with credentials with user_id", %{conn: conn, user: current_user} do
|
||||||
|
@ -1132,8 +1136,8 @@ test "it returns a given user's followers with user_id", %{conn: conn} do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns empty for a hidden network", %{conn: conn} do
|
test "it returns empty when hide_followers is set to true", %{conn: conn} do
|
||||||
user = insert(:user, %{info: %{hide_network: true}})
|
user = insert(:user, %{info: %{hide_followers: true}})
|
||||||
follower_one = insert(:user)
|
follower_one = insert(:user)
|
||||||
follower_two = insert(:user)
|
follower_two = insert(:user)
|
||||||
not_follower = insert(:user)
|
not_follower = insert(:user)
|
||||||
|
@ -1150,10 +1154,11 @@ test "it returns empty for a hidden network", %{conn: conn} do
|
||||||
assert [] == response
|
assert [] == response
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns the followers for a hidden network if requested by the user themselves", %{
|
test "it returns the followers when hide_followers is set to true if requested by the user themselves",
|
||||||
|
%{
|
||||||
conn: conn
|
conn: conn
|
||||||
} do
|
} do
|
||||||
user = insert(:user, %{info: %{hide_network: true}})
|
user = insert(:user, %{info: %{hide_followers: true}})
|
||||||
follower_one = insert(:user)
|
follower_one = insert(:user)
|
||||||
follower_two = insert(:user)
|
follower_two = insert(:user)
|
||||||
_not_follower = insert(:user)
|
_not_follower = insert(:user)
|
||||||
|
@ -1256,8 +1261,8 @@ test "it returns a given user's friends with user_id", %{conn: conn} do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns empty for a hidden network", %{conn: conn} do
|
test "it returns empty when hide_follows is set to true", %{conn: conn} do
|
||||||
user = insert(:user, %{info: %{hide_network: true}})
|
user = insert(:user, %{info: %{hide_follows: true}})
|
||||||
followed_one = insert(:user)
|
followed_one = insert(:user)
|
||||||
followed_two = insert(:user)
|
followed_two = insert(:user)
|
||||||
not_followed = insert(:user)
|
not_followed = insert(:user)
|
||||||
|
@ -1273,10 +1278,11 @@ test "it returns empty for a hidden network", %{conn: conn} do
|
||||||
assert [] == json_response(conn, 200)
|
assert [] == json_response(conn, 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns friends for a hidden network if the user themselves request it", %{
|
test "it returns friends when hide_follows is set to true if the user themselves request it",
|
||||||
|
%{
|
||||||
conn: conn
|
conn: conn
|
||||||
} do
|
} do
|
||||||
user = insert(:user, %{info: %{hide_network: true}})
|
user = insert(:user, %{info: %{hide_follows: true}})
|
||||||
followed_one = insert(:user)
|
followed_one = insert(:user)
|
||||||
followed_two = insert(:user)
|
followed_two = insert(:user)
|
||||||
_not_followed = insert(:user)
|
_not_followed = insert(:user)
|
||||||
|
@ -1364,27 +1370,75 @@ test "it updates a user's profile", %{conn: conn} do
|
||||||
assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
|
assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it sets and un-sets hide_network", %{conn: conn} do
|
test "it sets and un-sets hide_follows", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> assign(:user, user)
|
|> assign(:user, user)
|
||||||
|> post("/api/account/update_profile.json", %{
|
|> post("/api/account/update_profile.json", %{
|
||||||
"hide_network" => "true"
|
"hide_follows" => "true"
|
||||||
})
|
})
|
||||||
|
|
||||||
user = Repo.get!(User, user.id)
|
user = Repo.get!(User, user.id)
|
||||||
assert user.info.hide_network == true
|
assert user.info.hide_follows == true
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|> assign(:user, user)
|
|> assign(:user, user)
|
||||||
|> post("/api/account/update_profile.json", %{
|
|> post("/api/account/update_profile.json", %{
|
||||||
"hide_network" => "false"
|
"hide_follows" => "false"
|
||||||
})
|
})
|
||||||
|
|
||||||
user = Repo.get!(User, user.id)
|
user = Repo.get!(User, user.id)
|
||||||
assert user.info.hide_network == false
|
assert user.info.hide_follows == false
|
||||||
|
assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it sets and un-sets hide_followers", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/account/update_profile.json", %{
|
||||||
|
"hide_followers" => "true"
|
||||||
|
})
|
||||||
|
|
||||||
|
user = Repo.get!(User, user.id)
|
||||||
|
assert user.info.hide_followers == true
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/account/update_profile.json", %{
|
||||||
|
"hide_followers" => "false"
|
||||||
|
})
|
||||||
|
|
||||||
|
user = Repo.get!(User, user.id)
|
||||||
|
assert user.info.hide_followers == false
|
||||||
|
assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it sets and un-sets show_role", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/account/update_profile.json", %{
|
||||||
|
"show_role" => "true"
|
||||||
|
})
|
||||||
|
|
||||||
|
user = Repo.get!(User, user.id)
|
||||||
|
assert user.info.show_role == true
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/account/update_profile.json", %{
|
||||||
|
"show_role" => "false"
|
||||||
|
})
|
||||||
|
|
||||||
|
user = Repo.get!(User, user.id)
|
||||||
|
assert user.info.show_role == false
|
||||||
assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
|
assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1788,7 +1842,8 @@ test "with credentials", %{conn: conn, user: user} do
|
||||||
|
|
||||||
user = refresh_record(user)
|
user = refresh_record(user)
|
||||||
|
|
||||||
assert json_response(response, 200) == ActivityRepresenter.to_map(activity, %{user: user})
|
assert json_response(response, 200) ==
|
||||||
|
ActivityRepresenter.to_map(activity, %{user: user, for: user})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1817,7 +1872,8 @@ test "with credentials", %{conn: conn, user: user} do
|
||||||
|
|
||||||
user = refresh_record(user)
|
user = refresh_record(user)
|
||||||
|
|
||||||
assert json_response(response, 200) == ActivityRepresenter.to_map(activity, %{user: user})
|
assert json_response(response, 200) ==
|
||||||
|
ActivityRepresenter.to_map(activity, %{user: user, for: user})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -36,6 +36,7 @@ test "it returns HTTP 200", %{conn: conn} do
|
||||||
describe "GET /api/statusnet/config.json" do
|
describe "GET /api/statusnet/config.json" do
|
||||||
test "it returns the managed config", %{conn: conn} do
|
test "it returns the managed config", %{conn: conn} do
|
||||||
Pleroma.Config.put([:instance, :managed_config], false)
|
Pleroma.Config.put([:instance, :managed_config], false)
|
||||||
|
Pleroma.Config.put([:fe], theme: "rei-ayanami-towel")
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|
|
|
@ -100,7 +100,8 @@ test "A user" do
|
||||||
"locked" => false,
|
"locked" => false,
|
||||||
"default_scope" => "public",
|
"default_scope" => "public",
|
||||||
"no_rich_text" => false,
|
"no_rich_text" => false,
|
||||||
"hide_network" => false,
|
"hide_follows" => false,
|
||||||
|
"hide_followers" => false,
|
||||||
"fields" => [],
|
"fields" => [],
|
||||||
"pleroma" => %{
|
"pleroma" => %{
|
||||||
"confirmation_pending" => false,
|
"confirmation_pending" => false,
|
||||||
|
@ -147,7 +148,8 @@ test "A user for a given other follower", %{user: user} do
|
||||||
"locked" => false,
|
"locked" => false,
|
||||||
"default_scope" => "public",
|
"default_scope" => "public",
|
||||||
"no_rich_text" => false,
|
"no_rich_text" => false,
|
||||||
"hide_network" => false,
|
"hide_follows" => false,
|
||||||
|
"hide_followers" => false,
|
||||||
"fields" => [],
|
"fields" => [],
|
||||||
"pleroma" => %{
|
"pleroma" => %{
|
||||||
"confirmation_pending" => false,
|
"confirmation_pending" => false,
|
||||||
|
@ -195,7 +197,8 @@ test "A user that follows you", %{user: user} do
|
||||||
"locked" => false,
|
"locked" => false,
|
||||||
"default_scope" => "public",
|
"default_scope" => "public",
|
||||||
"no_rich_text" => false,
|
"no_rich_text" => false,
|
||||||
"hide_network" => false,
|
"hide_follows" => false,
|
||||||
|
"hide_followers" => false,
|
||||||
"fields" => [],
|
"fields" => [],
|
||||||
"pleroma" => %{
|
"pleroma" => %{
|
||||||
"confirmation_pending" => false,
|
"confirmation_pending" => false,
|
||||||
|
@ -211,6 +214,7 @@ test "a user that is a moderator" do
|
||||||
represented = UserView.render("show.json", %{user: user, for: user})
|
represented = UserView.render("show.json", %{user: user, for: user})
|
||||||
|
|
||||||
assert represented["rights"]["delete_others_notice"]
|
assert represented["rights"]["delete_others_notice"]
|
||||||
|
assert represented["role"] == "moderator"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "a user that is a admin" do
|
test "a user that is a admin" do
|
||||||
|
@ -218,6 +222,21 @@ test "a user that is a admin" do
|
||||||
represented = UserView.render("show.json", %{user: user, for: user})
|
represented = UserView.render("show.json", %{user: user, for: user})
|
||||||
|
|
||||||
assert represented["rights"]["admin"]
|
assert represented["rights"]["admin"]
|
||||||
|
assert represented["role"] == "admin"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "A moderator with hidden role for another user", %{user: user} do
|
||||||
|
admin = insert(:user, %{info: %{is_moderator: true, show_role: false}})
|
||||||
|
represented = UserView.render("show.json", %{user: admin, for: user})
|
||||||
|
|
||||||
|
assert represented["role"] == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
test "An admin with hidden role for another user", %{user: user} do
|
||||||
|
admin = insert(:user, %{info: %{is_admin: true, show_role: false}})
|
||||||
|
represented = UserView.render("show.json", %{user: admin, for: user})
|
||||||
|
|
||||||
|
assert represented["role"] == nil
|
||||||
end
|
end
|
||||||
|
|
||||||
test "A blocked user for the blocker" do
|
test "A blocked user for the blocker" do
|
||||||
|
@ -257,7 +276,8 @@ test "A blocked user for the blocker" do
|
||||||
"locked" => false,
|
"locked" => false,
|
||||||
"default_scope" => "public",
|
"default_scope" => "public",
|
||||||
"no_rich_text" => false,
|
"no_rich_text" => false,
|
||||||
"hide_network" => false,
|
"hide_follows" => false,
|
||||||
|
"hide_followers" => false,
|
||||||
"fields" => [],
|
"fields" => [],
|
||||||
"pleroma" => %{
|
"pleroma" => %{
|
||||||
"confirmation_pending" => false,
|
"confirmation_pending" => false,
|
||||||
|
|
Loading…
Reference in a new issue