@@ -25,6 +25,7 @@ erl_crash.dump | |||
# secrets files as long as you replace their contents by environment | |||
# variables. | |||
/config/*.secret.exs | |||
/config/generated_config.exs | |||
# Database setup file, some may forget to delete it | |||
/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: | |||
* Mastalab (Android) | |||
* Tusky (Android) | |||
* Twidere (Android) | |||
* Mastalab (Android, Streaming Ready) | |||
* Tusky (Android, No Streaming) | |||
* Twidere (Android, No Streaming) | |||
* Mast (iOS) | |||
* Amaroq (iOS) | |||
Client applications that are known to work well: | |||
* Pawoo (Android + iOS) | |||
* Tootdon (Android + iOS) | |||
* Tootle (iOS) | |||
* Whalebird (Windows + Mac + Linux) | |||
@@ -115,7 +115,7 @@ config :logger, :console, | |||
config :logger, :ex_syslogger, | |||
level: :debug, | |||
ident: "Pleroma", | |||
format: "$date $time $metadata[$level] $message", | |||
format: "$metadata[$level] $message", | |||
metadata: [:request_id] | |||
config :mime, :types, %{ | |||
@@ -100,6 +100,26 @@ config :pleroma, Pleroma.Mailer, | |||
## :logger | |||
* `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/) | |||
@@ -52,6 +52,14 @@ defmodule Mix.Tasks.Pleroma.User do | |||
- `--locked`/`--no-locked` - whether the user's account is locked | |||
- `--moderator`/`--no-moderator` - whether the user is a moderator | |||
- `--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 | |||
{options, [], []} = | |||
@@ -249,6 +257,32 @@ defmodule Mix.Tasks.Pleroma.User do | |||
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 | |||
Common.start_pleroma() | |||
@@ -12,8 +12,10 @@ defmodule Pleroma.Config.DeprecationWarnings do | |||
You are using the old configuration mechanism for the frontend. Please check config.md. | |||
""") | |||
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(""" | |||
!!!DEPRECATION WARNING!!! | |||
You are using the old configuration mechanism for the hellthread filter. Please check config.md. | |||
@@ -23,5 +25,6 @@ defmodule Pleroma.Config.DeprecationWarnings do | |||
def warn do | |||
check_frontend_config_mechanism() | |||
check_hellthread_threshold() | |||
end | |||
end |
@@ -59,6 +59,8 @@ defmodule Pleroma.HTML do | |||
end) | |||
end | |||
def extract_first_external_url(_, nil), do: {:error, "No content"} | |||
def extract_first_external_url(object, content) do | |||
key = "URL|#{object.id}" | |||
@@ -23,6 +23,7 @@ defmodule Pleroma.User.Info do | |||
field(:ap_enabled, :boolean, default: false) | |||
field(:is_moderator, :boolean, default: false) | |||
field(:is_admin, :boolean, default: false) | |||
field(:show_role, :boolean, default: true) | |||
field(:keys, :string, default: nil) | |||
field(:settings, :map, default: nil) | |||
field(:magic_key, :string, default: nil) | |||
@@ -30,7 +31,8 @@ defmodule Pleroma.User.Info do | |||
field(:topic, :string, default: nil) | |||
field(:hub, :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: []) | |||
# Found in the wild | |||
@@ -143,8 +145,10 @@ defmodule Pleroma.User.Info do | |||
:no_rich_text, | |||
:default_scope, | |||
:banner, | |||
:hide_network, | |||
:background | |||
:hide_follows, | |||
:hide_followers, | |||
:background, | |||
:show_role | |||
]) | |||
end | |||
@@ -194,7 +198,8 @@ defmodule Pleroma.User.Info do | |||
info | |||
|> cast(params, [ | |||
:is_moderator, | |||
:is_admin | |||
:is_admin, | |||
:show_role | |||
]) | |||
end | |||
@@ -521,7 +521,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do | |||
defp restrict_actor(query, _), do: query | |||
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 | |||
defp restrict_type(query, %{"type" => type}) do | |||
@@ -198,6 +198,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do | |||
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 | |||
if nickname == user.nickname do | |||
conn | |||
@@ -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 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do | |||
|> Map.put("tag", combined) | |||
end | |||
def fix_tag(%{"tag" => %{} = tag} = object), do: Map.put(object, "tag", [tag]) | |||
def fix_tag(object), do: object | |||
# content map usually only has one language so this will do for now. | |||
@@ -86,7 +86,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do | |||
query = from(user in query, select: [:ap_id]) | |||
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()) | |||
end | |||
@@ -99,7 +99,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do | |||
"id" => "#{user.ap_id}/following", | |||
"type" => "OrderedCollection", | |||
"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()) | |||
end | |||
@@ -109,7 +109,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do | |||
query = from(user in query, select: [:ap_id]) | |||
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()) | |||
end | |||
@@ -122,7 +122,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do | |||
"id" => "#{user.ap_id}/followers", | |||
"type" => "OrderedCollection", | |||
"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()) | |||
end | |||
@@ -239,6 +239,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do | |||
if offset < total do | |||
Map.put(map, "next", "#{iri}?page=#{page + 1}") | |||
else | |||
map | |||
end | |||
end | |||
end |
@@ -605,7 +605,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do | |||
followers = | |||
cond do | |||
for_user && user.id == for_user.id -> followers | |||
user.info.hide_network -> [] | |||
user.info.hide_followers -> [] | |||
true -> followers | |||
end | |||
@@ -621,7 +621,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do | |||
followers = | |||
cond do | |||
for_user && user.id == for_user.id -> followers | |||
user.info.hide_network -> [] | |||
user.info.hide_follows -> [] | |||
true -> followers | |||
end | |||
@@ -182,18 +182,24 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do | |||
end | |||
def render("card.json", %{rich_media: rich_media, page_url: page_url}) do | |||
page_url_data = URI.parse(page_url) | |||
page_url_data = | |||
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 | |||
page_url | |||
page_url_data | |||
end | |||
page_url = page_url_data |> to_string | |||
image_url = | |||
URI.merge(page_url_data, URI.parse(rich_media[:image])) | |||
|> to_string | |||
if rich_media[:image] != nil do | |||
URI.merge(page_url_data, URI.parse(rich_media[:image])) | |||
|> to_string | |||
else | |||
nil | |||
end | |||
site_name = rich_media[:site_name] || page_url_data.host | |||
@@ -54,22 +54,12 @@ defmodule Pleroma.Web.RichMedia.Parser do | |||
{:error, "Found metadata was invalid or incomplete: #{inspect(data)}"} | |||
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 | |||
data | |||
|> Enum.reject(fn {_, val} -> | |||
case string_is_valid_unicode(val) do | |||
{:ok, _} -> false | |||
|> Enum.reject(fn {key, val} -> | |||
with {:ok, _} <- Jason.encode(%{key => val}) do | |||
false | |||
else | |||
_ -> true | |||
end | |||
end) | |||
@@ -454,6 +454,7 @@ defmodule Pleroma.Web.Router do | |||
scope "/", Pleroma.Web.ActivityPub do | |||
pipe_through([:activitypub_client]) | |||
get("/api/ap/whoami", ActivityPubController, :whoami) | |||
get("/users/:nickname/inbox", ActivityPubController, :read_inbox) | |||
post("/users/:nickname/outbox", ActivityPubController, :update_outbox) | |||
end | |||
@@ -24,7 +24,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do | |||
conn | |||
|> put_view(UserView) | |||
|> render("show.json", %{user: user, token: token}) | |||
|> render("show.json", %{user: user, token: token, for: user}) | |||
end | |||
def status_update(%{assigns: %{user: user}} = conn, %{"status" => _} = status_data) do | |||
@@ -503,7 +503,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do | |||
followers = | |||
cond do | |||
for_user && user.id == for_user.id -> followers | |||
user.info.hide_network -> [] | |||
user.info.hide_followers -> [] | |||
true -> followers | |||
end | |||
@@ -523,7 +523,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do | |||
friends = | |||
cond do | |||
for_user && user.id == for_user.id -> friends | |||
user.info.hide_network -> [] | |||
user.info.hide_follows -> [] | |||
true -> friends | |||
end | |||
@@ -618,7 +618,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do | |||
defp build_info_cng(user, params) do | |||
info_params = | |||
["no_rich_text", "locked", "hide_network"] | |||
["no_rich_text", "locked", "hide_followers", "hide_follows", "show_role"] | |||
|> Enum.reduce(%{}, fn key, res -> | |||
if value = params[key] do | |||
Map.put(res, key, value == "true") | |||
@@ -108,7 +108,8 @@ defmodule Pleroma.Web.TwitterAPI.UserView do | |||
"locked" => user.info.locked, | |||
"default_scope" => user.info.default_scope, | |||
"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, | |||
# Pleroma extension | |||
@@ -118,6 +119,12 @@ defmodule Pleroma.Web.TwitterAPI.UserView 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 | |||
Map.put(data, "token", token_string(assigns[:token])) | |||
else | |||
@@ -125,6 +132,20 @@ defmodule Pleroma.Web.TwitterAPI.UserView do | |||
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(_), do: nil | |||
@@ -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 |
@@ -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", | |||
"webPushNotifications": false, | |||
"noAttachmentLinks": false, | |||
"nsfwCensorImage": "", | |||
"useOneClickNsfw": true, | |||
"playVideosInline": false, | |||
"useContainFit": false | |||
"nsfwCensorImage": "" | |||
} |
@@ -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 |
@@ -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 |
@@ -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){/*! | |||
localForage -- Offline Storage, Improved | |||
@@ -386,9 +386,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do | |||
assert result["first"]["orderedItems"] == [user.ap_id] | |||
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_two = insert(:user, %{info: %{hide_network: true}}) | |||
user_two = insert(:user, %{info: %{hide_followers: true}}) | |||
User.follow(user, user_two) | |||
result = | |||
@@ -441,8 +441,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do | |||
assert result["first"]["orderedItems"] == [user_two.ap_id] | |||
end | |||
test "it returns returns empty if the user has 'hide_network' set", %{conn: conn} do | |||
user = insert(:user, %{info: %{hide_network: true}}) | |||
test "it returns returns empty if the user has 'hide_follows' set", %{conn: conn} do | |||
user = insert(:user, %{info: %{hide_follows: true}}) | |||
user_two = insert(:user) | |||
User.follow(user, user_two) | |||
@@ -1101,9 +1101,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do | |||
assert id == to_string(user.id) | |||
end | |||
test "getting followers, hide_network", %{conn: conn} do | |||
test "getting followers, hide_followers", %{conn: conn} do | |||
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) | |||
conn = | |||
@@ -1113,9 +1113,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do | |||
assert [] == json_response(conn, 200) | |||
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) | |||
other_user = insert(:user, %{info: %{hide_network: true}}) | |||
other_user = insert(:user, %{info: %{hide_followers: true}}) | |||
{:ok, _user} = User.follow(user, other_user) | |||
conn = | |||
@@ -1139,8 +1139,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do | |||
assert id == to_string(other_user.id) | |||
end | |||
test "getting following, hide_network", %{conn: conn} do | |||
user = insert(:user, %{info: %{hide_network: true}}) | |||
test "getting following, hide_follows", %{conn: conn} do | |||
user = insert(:user, %{info: %{hide_follows: true}}) | |||
other_user = insert(:user) | |||
{:ok, user} = User.follow(user, other_user) | |||
@@ -1151,8 +1151,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do | |||
assert [] == json_response(conn, 200) | |||
end | |||
test "getting following, hide_network, same user requesting", %{conn: conn} do | |||
user = insert(:user, %{info: %{hide_network: true}}) | |||
test "getting following, hide_follows, same user requesting", %{conn: conn} do | |||
user = insert(:user, %{info: %{hide_follows: true}}) | |||
other_user = insert(:user) | |||
{:ok, user} = User.follow(user, other_user) | |||
@@ -235,4 +235,59 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do | |||
] | |||
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 |
@@ -62,7 +62,8 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do | |||
|> post("/api/account/verify_credentials.json") | |||
|> 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 | |||
@@ -107,7 +108,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do | |||
|> post(request_path, %{status: "Nice meme.", visibility: "private"}) | |||
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 | |||
@@ -418,6 +419,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do | |||
assert Enum.at(response, 0) == | |||
ActivityRepresenter.to_map(activity, %{ | |||
user: current_user, | |||
for: current_user, | |||
mentioned: [current_user] | |||
}) | |||
end | |||
@@ -547,7 +549,9 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do | |||
response = json_response(conn, 200) | |||
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 | |||
test "with credentials with user_id", %{conn: conn, user: current_user} do | |||
@@ -1132,8 +1136,8 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do | |||
) | |||
end | |||
test "it returns empty for a hidden network", %{conn: conn} do | |||
user = insert(:user, %{info: %{hide_network: true}}) | |||
test "it returns empty when hide_followers is set to true", %{conn: conn} do | |||
user = insert(:user, %{info: %{hide_followers: true}}) | |||
follower_one = insert(:user) | |||
follower_two = insert(:user) | |||
not_follower = insert(:user) | |||
@@ -1150,10 +1154,11 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do | |||
assert [] == response | |||
end | |||
test "it returns the followers for a hidden network if requested by the user themselves", %{ | |||
conn: conn | |||
} do | |||
user = insert(:user, %{info: %{hide_network: true}}) | |||
test "it returns the followers when hide_followers is set to true if requested by the user themselves", | |||
%{ | |||
conn: conn | |||
} do | |||
user = insert(:user, %{info: %{hide_followers: true}}) | |||
follower_one = insert(:user) | |||
follower_two = insert(:user) | |||
_not_follower = insert(:user) | |||
@@ -1256,8 +1261,8 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do | |||
) | |||
end | |||
test "it returns empty for a hidden network", %{conn: conn} do | |||
user = insert(:user, %{info: %{hide_network: true}}) | |||
test "it returns empty when hide_follows is set to true", %{conn: conn} do | |||
user = insert(:user, %{info: %{hide_follows: true}}) | |||
followed_one = insert(:user) | |||
followed_two = insert(:user) | |||
not_followed = insert(:user) | |||
@@ -1273,10 +1278,11 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do | |||
assert [] == json_response(conn, 200) | |||
end | |||
test "it returns friends for a hidden network if the user themselves request it", %{ | |||
conn: conn | |||
} do | |||
user = insert(:user, %{info: %{hide_network: true}}) | |||
test "it returns friends when hide_follows is set to true if the user themselves request it", | |||
%{ | |||
conn: conn | |||
} do | |||
user = insert(:user, %{info: %{hide_follows: true}}) | |||
followed_one = insert(:user) | |||
followed_two = insert(:user) | |||
_not_followed = insert(:user) | |||
@@ -1364,27 +1370,75 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do | |||
assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user}) | |||
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) | |||
conn | |||
|> assign(:user, user) | |||
|> post("/api/account/update_profile.json", %{ | |||
"hide_network" => "true" | |||
"hide_follows" => "true" | |||
}) | |||
user = Repo.get!(User, user.id) | |||
assert user.info.hide_network == true | |||
assert user.info.hide_follows == true | |||
conn = | |||
conn | |||
|> assign(:user, user) | |||
|> post("/api/account/update_profile.json", %{ | |||
"hide_network" => "false" | |||
"hide_follows" => "false" | |||
}) | |||
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}) | |||
end | |||
@@ -1788,7 +1842,8 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do | |||
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 | |||
@@ -1817,7 +1872,8 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do | |||
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 |
@@ -36,6 +36,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do | |||
describe "GET /api/statusnet/config.json" do | |||
test "it returns the managed config", %{conn: conn} do | |||
Pleroma.Config.put([:instance, :managed_config], false) | |||
Pleroma.Config.put([:fe], theme: "rei-ayanami-towel") | |||
response = | |||
conn | |||
@@ -100,7 +100,8 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do | |||
"locked" => false, | |||
"default_scope" => "public", | |||
"no_rich_text" => false, | |||
"hide_network" => false, | |||
"hide_follows" => false, | |||
"hide_followers" => false, | |||
"fields" => [], | |||
"pleroma" => %{ | |||
"confirmation_pending" => false, | |||
@@ -147,7 +148,8 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do | |||
"locked" => false, | |||
"default_scope" => "public", | |||
"no_rich_text" => false, | |||
"hide_network" => false, | |||
"hide_follows" => false, | |||
"hide_followers" => false, | |||
"fields" => [], | |||
"pleroma" => %{ | |||
"confirmation_pending" => false, | |||
@@ -195,7 +197,8 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do | |||
"locked" => false, | |||
"default_scope" => "public", | |||
"no_rich_text" => false, | |||
"hide_network" => false, | |||
"hide_follows" => false, | |||
"hide_followers" => false, | |||
"fields" => [], | |||
"pleroma" => %{ | |||
"confirmation_pending" => false, | |||
@@ -211,6 +214,7 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do | |||
represented = UserView.render("show.json", %{user: user, for: user}) | |||
assert represented["rights"]["delete_others_notice"] | |||
assert represented["role"] == "moderator" | |||
end | |||
test "a user that is a admin" do | |||
@@ -218,6 +222,21 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do | |||
represented = UserView.render("show.json", %{user: user, for: user}) | |||
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 | |||
test "A blocked user for the blocker" do | |||
@@ -257,7 +276,8 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do | |||
"locked" => false, | |||
"default_scope" => "public", | |||
"no_rich_text" => false, | |||
"hide_network" => false, | |||
"hide_follows" => false, | |||
"hide_followers" => false, | |||
"fields" => [], | |||
"pleroma" => %{ | |||
"confirmation_pending" => false, | |||