forked from AkkomaGang/akkoma
Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into 1507-static-fe-prioritize-json
This commit is contained in:
commit
ed4f9f6a29
97 changed files with 1547 additions and 373 deletions
|
@ -14,7 +14,7 @@
|
||||||
* Pleroma version (could be found in the "Version" tab of settings in Pleroma-FE):
|
* Pleroma version (could be found in the "Version" tab of settings in Pleroma-FE):
|
||||||
* Elixir version (`elixir -v` for from source installations, N/A for OTP):
|
* Elixir version (`elixir -v` for from source installations, N/A for OTP):
|
||||||
* Operating system:
|
* Operating system:
|
||||||
* PostgreSQL version (`postgres -V`):
|
* PostgreSQL version (`psql -V`):
|
||||||
|
|
||||||
|
|
||||||
### Bug description
|
### Bug description
|
||||||
|
|
|
@ -17,6 +17,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
<summary>API Changes</summary>
|
<summary>API Changes</summary>
|
||||||
|
|
||||||
- **Breaking:** Emoji API: changed methods and renamed routes.
|
- **Breaking:** Emoji API: changed methods and renamed routes.
|
||||||
|
- Streaming: Repeats of a user's posts will no longer be pushed to the user's stream.
|
||||||
|
- Mastodon API: Added `pleroma.metadata.fields_limits` to /api/v1/instance
|
||||||
|
- Mastodon API: On deletion, returns the original post text.
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
@ -51,6 +54,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>API Changes</summary>
|
<summary>API Changes</summary>
|
||||||
|
- Mastodon API: Add pleroma.parents_visible field to statuses.
|
||||||
- Mastodon API: Extended `/api/v1/instance`.
|
- Mastodon API: Extended `/api/v1/instance`.
|
||||||
- Mastodon API: Support for `include_types` in `/api/v1/notifications`.
|
- Mastodon API: Support for `include_types` in `/api/v1/notifications`.
|
||||||
- Mastodon API: Added `/api/v1/notifications/:id/dismiss` endpoint.
|
- Mastodon API: Added `/api/v1/notifications/:id/dismiss` endpoint.
|
||||||
|
|
|
@ -437,8 +437,6 @@
|
||||||
config :pleroma, Pleroma.Web.Preload,
|
config :pleroma, Pleroma.Web.Preload,
|
||||||
providers: [
|
providers: [
|
||||||
Pleroma.Web.Preload.Providers.Instance,
|
Pleroma.Web.Preload.Providers.Instance,
|
||||||
Pleroma.Web.Preload.Providers.User,
|
|
||||||
Pleroma.Web.Preload.Providers.Timelines,
|
|
||||||
Pleroma.Web.Preload.Providers.StatusNet
|
Pleroma.Web.Preload.Providers.StatusNet
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -40,12 +40,13 @@
|
||||||
key: :link_name,
|
key: :link_name,
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description:
|
description:
|
||||||
"If enabled, a name parameter will be added to the url of the upload. For example `https://instance.tld/media/imagehash.png?name=realname.png`."
|
"If enabled, a name parameter will be added to the URL of the upload. For example `https://instance.tld/media/imagehash.png?name=realname.png`."
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :base_url,
|
key: :base_url,
|
||||||
|
label: "Base URL",
|
||||||
type: :string,
|
type: :string,
|
||||||
description: "Base url for the uploads, needed if you use CDN",
|
description: "Base URL for the uploads, needed if you use CDN",
|
||||||
suggestions: [
|
suggestions: [
|
||||||
"https://cdn-host.com"
|
"https://cdn-host.com"
|
||||||
]
|
]
|
||||||
|
@ -58,6 +59,7 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :proxy_opts,
|
key: :proxy_opts,
|
||||||
|
label: "Proxy Options",
|
||||||
type: :keyword,
|
type: :keyword,
|
||||||
description: "Options for Pleroma.ReverseProxy",
|
description: "Options for Pleroma.ReverseProxy",
|
||||||
suggestions: [
|
suggestions: [
|
||||||
|
@ -85,6 +87,7 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :http,
|
key: :http,
|
||||||
|
label: "HTTP",
|
||||||
type: :keyword,
|
type: :keyword,
|
||||||
description: "HTTP options",
|
description: "HTTP options",
|
||||||
children: [
|
children: [
|
||||||
|
@ -193,7 +196,9 @@
|
||||||
%{
|
%{
|
||||||
key: :args,
|
key: :args,
|
||||||
type: [:string, {:list, :string}, {:list, :tuple}],
|
type: [:string, {:list, :string}, {:list, :tuple}],
|
||||||
description: "List of actions for the mogrify command",
|
description:
|
||||||
|
"List of actions for the mogrify command. It's possible to add self-written settings as string. " <>
|
||||||
|
"For example `[\"auto-orient\", \"strip\", {\"resize\", \"3840x1080>\"}]` string will be parsed into list of the settings.",
|
||||||
suggestions: [
|
suggestions: [
|
||||||
"strip",
|
"strip",
|
||||||
"auto-orient",
|
"auto-orient",
|
||||||
|
@ -479,6 +484,7 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :uri_schemes,
|
key: :uri_schemes,
|
||||||
|
label: "URI Schemes",
|
||||||
type: :group,
|
type: :group,
|
||||||
description: "URI schemes related settings",
|
description: "URI schemes related settings",
|
||||||
children: [
|
children: [
|
||||||
|
@ -651,17 +657,17 @@
|
||||||
key: :invites_enabled,
|
key: :invites_enabled,
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description:
|
description:
|
||||||
"Enable user invitations for admins (depends on `registrations_open` being disabled)."
|
"Enable user invitations for admins (depends on `registrations_open` being disabled)"
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :account_activation_required,
|
key: :account_activation_required,
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Require users to confirm their emails before signing in."
|
description: "Require users to confirm their emails before signing in"
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :federating,
|
key: :federating,
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Enable federation with other instances."
|
description: "Enable federation with other instances"
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :federation_incoming_replies_max_depth,
|
key: :federation_incoming_replies_max_depth,
|
||||||
|
@ -679,7 +685,7 @@
|
||||||
label: "Fed. reachability timeout days",
|
label: "Fed. reachability timeout days",
|
||||||
type: :integer,
|
type: :integer,
|
||||||
description:
|
description:
|
||||||
"Timeout (in days) of each external federation target being unreachable prior to pausing federating to it.",
|
"Timeout (in days) of each external federation target being unreachable prior to pausing federating to it",
|
||||||
suggestions: [
|
suggestions: [
|
||||||
7
|
7
|
||||||
]
|
]
|
||||||
|
@ -801,6 +807,7 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :safe_dm_mentions,
|
key: :safe_dm_mentions,
|
||||||
|
label: "Safe DM mentions",
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description:
|
description:
|
||||||
"If enabled, only mentions at the beginning of a post will be used to address people in direct messages." <>
|
"If enabled, only mentions at the beginning of a post will be used to address people in direct messages." <>
|
||||||
|
@ -840,7 +847,7 @@
|
||||||
%{
|
%{
|
||||||
key: :skip_thread_containment,
|
key: :skip_thread_containment,
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Skip filtering out broken threads. Default: enabled"
|
description: "Skip filtering out broken threads. Default: enabled."
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :limit_to_local_content,
|
key: :limit_to_local_content,
|
||||||
|
@ -904,6 +911,7 @@
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
key: :totp,
|
key: :totp,
|
||||||
|
label: "TOTP settings",
|
||||||
type: :keyword,
|
type: :keyword,
|
||||||
description: "TOTP settings",
|
description: "TOTP settings",
|
||||||
suggestions: [digits: 6, period: 30],
|
suggestions: [digits: 6, period: 30],
|
||||||
|
@ -920,7 +928,7 @@
|
||||||
type: :integer,
|
type: :integer,
|
||||||
suggestions: [30],
|
suggestions: [30],
|
||||||
description:
|
description:
|
||||||
"a period for which the TOTP code will be valid, in seconds. Defaults to 30 seconds."
|
"A period for which the TOTP code will be valid, in seconds. Defaults to 30 seconds."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -934,7 +942,7 @@
|
||||||
key: :number,
|
key: :number,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
suggestions: [5],
|
suggestions: [5],
|
||||||
description: "number of backup codes to generate."
|
description: "Number of backup codes to generate."
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :length,
|
key: :length,
|
||||||
|
@ -974,6 +982,7 @@
|
||||||
group: :logger,
|
group: :logger,
|
||||||
type: :group,
|
type: :group,
|
||||||
key: :ex_syslogger,
|
key: :ex_syslogger,
|
||||||
|
label: "ExSyslogger",
|
||||||
description: "ExSyslogger-related settings",
|
description: "ExSyslogger-related settings",
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
|
@ -992,7 +1001,7 @@
|
||||||
%{
|
%{
|
||||||
key: :format,
|
key: :format,
|
||||||
type: :string,
|
type: :string,
|
||||||
description: "Default: \"$date $time [$level] $levelpad$node $metadata $message\".",
|
description: "Default: \"$date $time [$level] $levelpad$node $metadata $message\"",
|
||||||
suggestions: ["$metadata[$level] $message"]
|
suggestions: ["$metadata[$level] $message"]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
|
@ -1006,6 +1015,7 @@
|
||||||
group: :logger,
|
group: :logger,
|
||||||
type: :group,
|
type: :group,
|
||||||
key: :console,
|
key: :console,
|
||||||
|
label: "Console Logger",
|
||||||
description: "Console logger settings",
|
description: "Console logger settings",
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
|
@ -1017,7 +1027,7 @@
|
||||||
%{
|
%{
|
||||||
key: :format,
|
key: :format,
|
||||||
type: :string,
|
type: :string,
|
||||||
description: "Default: \"$date $time [$level] $levelpad$node $metadata $message\".",
|
description: "Default: \"$date $time [$level] $levelpad$node $metadata $message\"",
|
||||||
suggestions: ["$metadata[$level] $message"]
|
suggestions: ["$metadata[$level] $message"]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
|
@ -1030,6 +1040,7 @@
|
||||||
%{
|
%{
|
||||||
group: :quack,
|
group: :quack,
|
||||||
type: :group,
|
type: :group,
|
||||||
|
label: "Quack Logger",
|
||||||
description: "Quack-related settings",
|
description: "Quack-related settings",
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
|
@ -1140,19 +1151,19 @@
|
||||||
key: :greentext,
|
key: :greentext,
|
||||||
label: "Greentext",
|
label: "Greentext",
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Enables green text on lines prefixed with the > character."
|
description: "Enables green text on lines prefixed with the > character"
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :hideFilteredStatuses,
|
key: :hideFilteredStatuses,
|
||||||
label: "Hide Filtered Statuses",
|
label: "Hide Filtered Statuses",
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Hides filtered statuses from timelines."
|
description: "Hides filtered statuses from timelines"
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :hideMutedPosts,
|
key: :hideMutedPosts,
|
||||||
label: "Hide Muted Posts",
|
label: "Hide Muted Posts",
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Hides muted statuses from timelines."
|
description: "Hides muted statuses from timelines"
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :hidePostStats,
|
key: :hidePostStats,
|
||||||
|
@ -1164,7 +1175,7 @@
|
||||||
key: :hideSitename,
|
key: :hideSitename,
|
||||||
label: "Hide Sitename",
|
label: "Hide Sitename",
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Hides instance name from PleromaFE banner."
|
description: "Hides instance name from PleromaFE banner"
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :hideUserStats,
|
key: :hideUserStats,
|
||||||
|
@ -1209,14 +1220,14 @@
|
||||||
label: "NSFW Censor Image",
|
label: "NSFW Censor Image",
|
||||||
type: :string,
|
type: :string,
|
||||||
description:
|
description:
|
||||||
"URL of the image to use for hiding NSFW media attachments in the timeline.",
|
"URL of the image to use for hiding NSFW media attachments in the timeline",
|
||||||
suggestions: ["/static/img/nsfw.74818f9.png"]
|
suggestions: ["/static/img/nsfw.74818f9.png"]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :postContentType,
|
key: :postContentType,
|
||||||
label: "Post Content Type",
|
label: "Post Content Type",
|
||||||
type: {:dropdown, :atom},
|
type: {:dropdown, :atom},
|
||||||
description: "Default post formatting option.",
|
description: "Default post formatting option",
|
||||||
suggestions: ["text/plain", "text/html", "text/markdown", "text/bbcode"]
|
suggestions: ["text/plain", "text/html", "text/markdown", "text/bbcode"]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
|
@ -1245,14 +1256,14 @@
|
||||||
key: :sidebarRight,
|
key: :sidebarRight,
|
||||||
label: "Sidebar on Right",
|
label: "Sidebar on Right",
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Change alignment of sidebar and panels to the right."
|
description: "Change alignment of sidebar and panels to the right"
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :showFeaturesPanel,
|
key: :showFeaturesPanel,
|
||||||
label: "Show instance features panel",
|
label: "Show instance features panel",
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description:
|
description:
|
||||||
"Enables panel displaying functionality of the instance on the About page."
|
"Enables panel displaying functionality of the instance on the About page"
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :showInstanceSpecificPanel,
|
key: :showInstanceSpecificPanel,
|
||||||
|
@ -1310,7 +1321,7 @@
|
||||||
key: :mascots,
|
key: :mascots,
|
||||||
type: {:keyword, :map},
|
type: {:keyword, :map},
|
||||||
description:
|
description:
|
||||||
"Keyword of mascots, each element must contain both an url and a mime_type key",
|
"Keyword of mascots, each element must contain both an URL and a mime_type key",
|
||||||
suggestions: [
|
suggestions: [
|
||||||
pleroma_fox_tan: %{
|
pleroma_fox_tan: %{
|
||||||
url: "/images/pleroma-fox-tan-smol.png",
|
url: "/images/pleroma-fox-tan-smol.png",
|
||||||
|
@ -1334,7 +1345,7 @@
|
||||||
%{
|
%{
|
||||||
key: :default_user_avatar,
|
key: :default_user_avatar,
|
||||||
type: :string,
|
type: :string,
|
||||||
description: "URL of the default user avatar.",
|
description: "URL of the default user avatar",
|
||||||
suggestions: ["/images/avi.png"]
|
suggestions: ["/images/avi.png"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1344,7 +1355,7 @@
|
||||||
key: :manifest,
|
key: :manifest,
|
||||||
type: :group,
|
type: :group,
|
||||||
description:
|
description:
|
||||||
"This section describe PWA manifest instance-specific values. Currently this option relate only for MastoFE",
|
"This section describe PWA manifest instance-specific values. Currently this option relate only for MastoFE.",
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
key: :icons,
|
key: :icons,
|
||||||
|
@ -1380,10 +1391,49 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :mrf_simple,
|
key: :mrf,
|
||||||
label: "MRF simple",
|
tab: :mrf,
|
||||||
|
label: "MRF",
|
||||||
type: :group,
|
type: :group,
|
||||||
description: "Message Rewrite Facility",
|
description: "General MRF settings",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :policies,
|
||||||
|
type: [:module, {:list, :module}],
|
||||||
|
description:
|
||||||
|
"A list of MRF policies enabled. Module names are shortened (removed leading `Pleroma.Web.ActivityPub.MRF.` part), but on adding custom module you need to use full name.",
|
||||||
|
suggestions:
|
||||||
|
Generator.list_modules_in_dir(
|
||||||
|
"lib/pleroma/web/activity_pub/mrf",
|
||||||
|
"Elixir.Pleroma.Web.ActivityPub.MRF."
|
||||||
|
)
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :transparency,
|
||||||
|
label: "MRF transparency",
|
||||||
|
type: :boolean,
|
||||||
|
description:
|
||||||
|
"Make the content of your Message Rewrite Facility settings public (via nodeinfo)"
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :transparency_exclusions,
|
||||||
|
label: "MRF transparency exclusions",
|
||||||
|
type: {:list, :string},
|
||||||
|
description:
|
||||||
|
"Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.",
|
||||||
|
suggestions: [
|
||||||
|
"exclusion.com"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
group: :pleroma,
|
||||||
|
key: :mrf_simple,
|
||||||
|
tab: :mrf,
|
||||||
|
label: "MRF Simple",
|
||||||
|
type: :group,
|
||||||
|
description: "Simple ingress policies",
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
key: :media_removal,
|
key: :media_removal,
|
||||||
|
@ -1402,7 +1452,7 @@
|
||||||
key: :federated_timeline_removal,
|
key: :federated_timeline_removal,
|
||||||
type: {:list, :string},
|
type: {:list, :string},
|
||||||
description:
|
description:
|
||||||
"List of instances to remove from Federated (aka The Whole Known Network) Timeline",
|
"List of instances to remove from the Federated (aka The Whole Known Network) Timeline",
|
||||||
suggestions: ["example.com", "*.example.com"]
|
suggestions: ["example.com", "*.example.com"]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
|
@ -1446,14 +1496,15 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :mrf_activity_expiration,
|
key: :mrf_activity_expiration,
|
||||||
|
tab: :mrf,
|
||||||
label: "MRF Activity Expiration Policy",
|
label: "MRF Activity Expiration Policy",
|
||||||
type: :group,
|
type: :group,
|
||||||
description: "Adds expiration to all local Create Note activities",
|
description: "Adds automatic expiration to all local activities",
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
key: :days,
|
key: :days,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
description: "Default global expiration time for all local Create activities (in days)",
|
description: "Default global expiration time for all local activities (in days)",
|
||||||
suggestions: [90, 365]
|
suggestions: [90, 365]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1461,7 +1512,8 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :mrf_subchain,
|
key: :mrf_subchain,
|
||||||
label: "MRF subchain",
|
tab: :mrf,
|
||||||
|
label: "MRF Subchain",
|
||||||
type: :group,
|
type: :group,
|
||||||
description:
|
description:
|
||||||
"This policy processes messages through an alternate pipeline when a given message matches certain criteria." <>
|
"This policy processes messages through an alternate pipeline when a given message matches certain criteria." <>
|
||||||
|
@ -1482,9 +1534,9 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :mrf_rejectnonpublic,
|
key: :mrf_rejectnonpublic,
|
||||||
description:
|
tab: :mrf,
|
||||||
"MRF RejectNonPublic settings. RejectNonPublic drops posts with non-public visibility settings.",
|
description: "RejectNonPublic drops posts with non-public visibility settings.",
|
||||||
label: "MRF reject non public",
|
label: "MRF Reject Non Public",
|
||||||
type: :group,
|
type: :group,
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
|
@ -1503,16 +1555,17 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :mrf_hellthread,
|
key: :mrf_hellthread,
|
||||||
label: "MRF hellthread",
|
tab: :mrf,
|
||||||
|
label: "MRF Hellthread",
|
||||||
type: :group,
|
type: :group,
|
||||||
description: "Block messages with too much mentions",
|
description: "Block messages with excessive user mentions",
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
key: :delist_threshold,
|
key: :delist_threshold,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
description:
|
description:
|
||||||
"Number of mentioned users after which the message gets delisted (the message can still be seen, " <>
|
"Number of mentioned users after which the message gets removed from timelines and" <>
|
||||||
" but it will not show up in public timelines and mentioned users won't get notifications about it). Set to 0 to disable.",
|
"disables notifications. Set to 0 to disable.",
|
||||||
suggestions: [10]
|
suggestions: [10]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
|
@ -1527,7 +1580,8 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :mrf_keyword,
|
key: :mrf_keyword,
|
||||||
label: "MRF keyword",
|
tab: :mrf,
|
||||||
|
label: "MRF Keyword",
|
||||||
type: :group,
|
type: :group,
|
||||||
description: "Reject or Word-Replace messages with a keyword or regex",
|
description: "Reject or Word-Replace messages with a keyword or regex",
|
||||||
children: [
|
children: [
|
||||||
|
@ -1557,14 +1611,15 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :mrf_mention,
|
key: :mrf_mention,
|
||||||
label: "MRF mention",
|
tab: :mrf,
|
||||||
|
label: "MRF Mention",
|
||||||
type: :group,
|
type: :group,
|
||||||
description: "Block messages which mention a user",
|
description: "Block messages which mention a specific user",
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
key: :actors,
|
key: :actors,
|
||||||
type: {:list, :string},
|
type: {:list, :string},
|
||||||
description: "A list of actors for which any post mentioning them will be dropped.",
|
description: "A list of actors for which any post mentioning them will be dropped",
|
||||||
suggestions: ["actor1", "actor2"]
|
suggestions: ["actor1", "actor2"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1572,7 +1627,8 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :mrf_vocabulary,
|
key: :mrf_vocabulary,
|
||||||
label: "MRF vocabulary",
|
tab: :mrf,
|
||||||
|
label: "MRF Vocabulary",
|
||||||
type: :group,
|
type: :group,
|
||||||
description: "Filter messages which belong to certain activity vocabularies",
|
description: "Filter messages which belong to certain activity vocabularies",
|
||||||
children: [
|
children: [
|
||||||
|
@ -1580,14 +1636,14 @@
|
||||||
key: :accept,
|
key: :accept,
|
||||||
type: {:list, :string},
|
type: {:list, :string},
|
||||||
description:
|
description:
|
||||||
"A list of ActivityStreams terms to accept. If empty, all supported messages are accepted",
|
"A list of ActivityStreams terms to accept. If empty, all supported messages are accepted.",
|
||||||
suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
|
suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :reject,
|
key: :reject,
|
||||||
type: {:list, :string},
|
type: {:list, :string},
|
||||||
description:
|
description:
|
||||||
"A list of ActivityStreams terms to reject. If empty, no messages are rejected",
|
"A list of ActivityStreams terms to reject. If empty, no messages are rejected.",
|
||||||
suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
|
suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1617,6 +1673,7 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :base_url,
|
key: :base_url,
|
||||||
|
label: "Base URL",
|
||||||
type: :string,
|
type: :string,
|
||||||
description:
|
description:
|
||||||
"The base URL to access a user-uploaded file. Useful when you want to proxy the media files via another host/CDN fronts.",
|
"The base URL to access a user-uploaded file. Useful when you want to proxy the media files via another host/CDN fronts.",
|
||||||
|
@ -1649,6 +1706,7 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :proxy_opts,
|
key: :proxy_opts,
|
||||||
|
label: "Proxy Options",
|
||||||
type: :keyword,
|
type: :keyword,
|
||||||
description: "Options for Pleroma.ReverseProxy",
|
description: "Options for Pleroma.ReverseProxy",
|
||||||
suggestions: [
|
suggestions: [
|
||||||
|
@ -1676,6 +1734,7 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :http,
|
key: :http,
|
||||||
|
label: "HTTP",
|
||||||
type: :keyword,
|
type: :keyword,
|
||||||
description: "HTTP options",
|
description: "HTTP options",
|
||||||
children: [
|
children: [
|
||||||
|
@ -1771,6 +1830,7 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :ip,
|
key: :ip,
|
||||||
|
label: "IP",
|
||||||
type: :tuple,
|
type: :tuple,
|
||||||
description: "IP address to bind to",
|
description: "IP address to bind to",
|
||||||
suggestions: [{0, 0, 0, 0}]
|
suggestions: [{0, 0, 0, 0}]
|
||||||
|
@ -1784,7 +1844,7 @@
|
||||||
%{
|
%{
|
||||||
key: :dstport,
|
key: :dstport,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
description: "Port advertised in urls (optional, defaults to port)",
|
description: "Port advertised in URLs (optional, defaults to port)",
|
||||||
suggestions: [9999]
|
suggestions: [9999]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1792,6 +1852,7 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :activitypub,
|
key: :activitypub,
|
||||||
|
label: "ActivityPub",
|
||||||
type: :group,
|
type: :group,
|
||||||
description: "ActivityPub-related settings",
|
description: "ActivityPub-related settings",
|
||||||
children: [
|
children: [
|
||||||
|
@ -1814,7 +1875,7 @@
|
||||||
key: :note_replies_output_limit,
|
key: :note_replies_output_limit,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
description:
|
description:
|
||||||
"The number of Note replies' URIs to be included with outgoing federation (`5` to match Mastodon hardcoded value, `0` to disable the output)."
|
"The number of Note replies' URIs to be included with outgoing federation (`5` to match Mastodon hardcoded value, `0` to disable the output)"
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :follow_handshake_timeout,
|
key: :follow_handshake_timeout,
|
||||||
|
@ -1827,6 +1888,7 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :http_security,
|
key: :http_security,
|
||||||
|
label: "HTTP security",
|
||||||
type: :group,
|
type: :group,
|
||||||
description: "HTTP security settings",
|
description: "HTTP security settings",
|
||||||
children: [
|
children: [
|
||||||
|
@ -1865,7 +1927,7 @@
|
||||||
key: :report_uri,
|
key: :report_uri,
|
||||||
label: "Report URI",
|
label: "Report URI",
|
||||||
type: :string,
|
type: :string,
|
||||||
description: "Adds the specified url to report-uri and report-to group in CSP header",
|
description: "Adds the specified URL to report-uri and report-to group in CSP header",
|
||||||
suggestions: ["https://example.com/report-uri"]
|
suggestions: ["https://example.com/report-uri"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1873,9 +1935,10 @@
|
||||||
%{
|
%{
|
||||||
group: :web_push_encryption,
|
group: :web_push_encryption,
|
||||||
key: :vapid_details,
|
key: :vapid_details,
|
||||||
|
label: "Vapid Details",
|
||||||
type: :group,
|
type: :group,
|
||||||
description:
|
description:
|
||||||
"Web Push Notifications configuration. You can use the mix task mix web_push.gen.keypair to generate it",
|
"Web Push Notifications configuration. You can use the mix task mix web_push.gen.keypair to generate it.",
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
key: :subject,
|
key: :subject,
|
||||||
|
@ -1942,6 +2005,7 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
|
label: "Pleroma Admin Token",
|
||||||
type: :group,
|
type: :group,
|
||||||
description:
|
description:
|
||||||
"Allows to set a token that can be used to authenticate with the admin api without using an actual user by giving it as the `admin_token` parameter",
|
"Allows to set a token that can be used to authenticate with the admin api without using an actual user by giving it as the `admin_token` parameter",
|
||||||
|
@ -1949,7 +2013,7 @@
|
||||||
%{
|
%{
|
||||||
key: :admin_token,
|
key: :admin_token,
|
||||||
type: :string,
|
type: :string,
|
||||||
description: "Token",
|
description: "Admin token",
|
||||||
suggestions: ["We recommend a secure random string or UUID"]
|
suggestions: ["We recommend a secure random string or UUID"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -2114,24 +2178,24 @@
|
||||||
key: :rich_media,
|
key: :rich_media,
|
||||||
type: :group,
|
type: :group,
|
||||||
description:
|
description:
|
||||||
"If enabled the instance will parse metadata from attached links to generate link previews.",
|
"If enabled the instance will parse metadata from attached links to generate link previews",
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
key: :enabled,
|
key: :enabled,
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Enables RichMedia parsing of URLs."
|
description: "Enables RichMedia parsing of URLs"
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :ignore_hosts,
|
key: :ignore_hosts,
|
||||||
type: {:list, :string},
|
type: {:list, :string},
|
||||||
description: "List of hosts which will be ignored by the metadata parser.",
|
description: "List of hosts which will be ignored by the metadata parser",
|
||||||
suggestions: ["accounts.google.com", "xss.website"]
|
suggestions: ["accounts.google.com", "xss.website"]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :ignore_tld,
|
key: :ignore_tld,
|
||||||
label: "Ignore TLD",
|
label: "Ignore TLD",
|
||||||
type: {:list, :string},
|
type: {:list, :string},
|
||||||
description: "List TLDs (top-level domains) which will ignore for parse metadata.",
|
description: "List TLDs (top-level domains) which will ignore for parse metadata",
|
||||||
suggestions: ["local", "localdomain", "lan"]
|
suggestions: ["local", "localdomain", "lan"]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
|
@ -2159,31 +2223,32 @@
|
||||||
%{
|
%{
|
||||||
group: :auto_linker,
|
group: :auto_linker,
|
||||||
key: :opts,
|
key: :opts,
|
||||||
|
label: "Auto Linker",
|
||||||
type: :group,
|
type: :group,
|
||||||
description: "Configuration for the auto_linker library",
|
description: "Configuration for the auto_linker library",
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
key: :class,
|
key: :class,
|
||||||
type: [:string, false],
|
type: [:string, false],
|
||||||
description: "Specify the class to be added to the generated link. Disable to clear",
|
description: "Specify the class to be added to the generated link. Disable to clear.",
|
||||||
suggestions: ["auto-linker", false]
|
suggestions: ["auto-linker", false]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :rel,
|
key: :rel,
|
||||||
type: [:string, false],
|
type: [:string, false],
|
||||||
description: "Override the rel attribute. Disable to clear",
|
description: "Override the rel attribute. Disable to clear.",
|
||||||
suggestions: ["ugc", "noopener noreferrer", false]
|
suggestions: ["ugc", "noopener noreferrer", false]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :new_window,
|
key: :new_window,
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Link urls will open in new window/tab"
|
description: "Link URLs will open in new window/tab"
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :truncate,
|
key: :truncate,
|
||||||
type: [:integer, false],
|
type: [:integer, false],
|
||||||
description:
|
description:
|
||||||
"Set to a number to truncate urls longer then the number. Truncated urls will end in `..`",
|
"Set to a number to truncate URLs longer then the number. Truncated URLs will end in `..`",
|
||||||
suggestions: [15, false]
|
suggestions: [15, false]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
|
@ -2194,7 +2259,7 @@
|
||||||
%{
|
%{
|
||||||
key: :extra,
|
key: :extra,
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Link urls with rarely used schemes (magnet, ipfs, irc, etc.)"
|
description: "Link URLs with rarely used schemes (magnet, ipfs, irc, etc.)"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -2240,6 +2305,7 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
|
label: "Pleroma Authenticator",
|
||||||
type: :group,
|
type: :group,
|
||||||
description: "Authenticator",
|
description: "Authenticator",
|
||||||
children: [
|
children: [
|
||||||
|
@ -2253,6 +2319,7 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :ldap,
|
key: :ldap,
|
||||||
|
label: "LDAP",
|
||||||
type: :group,
|
type: :group,
|
||||||
description:
|
description:
|
||||||
"Use LDAP for user authentication. When a user logs in to the Pleroma instance, the name and password" <>
|
"Use LDAP for user authentication. When a user logs in to the Pleroma instance, the name and password" <>
|
||||||
|
@ -2339,6 +2406,7 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :uid,
|
key: :uid,
|
||||||
|
label: "UID",
|
||||||
type: :string,
|
type: :string,
|
||||||
description:
|
description:
|
||||||
"LDAP attribute name to authenticate the user, e.g. when \"cn\", the filter will be \"cn=username,base\"",
|
"LDAP attribute name to authenticate the user, e.g. when \"cn\", the filter will be \"cn=username,base\"",
|
||||||
|
@ -2354,6 +2422,7 @@
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
key: :enforce_oauth_admin_scope_usage,
|
key: :enforce_oauth_admin_scope_usage,
|
||||||
|
label: "Enforce OAuth admin scope usage",
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description:
|
description:
|
||||||
"OAuth admin scope requirement toggle. " <>
|
"OAuth admin scope requirement toggle. " <>
|
||||||
|
@ -2370,6 +2439,7 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :oauth_consumer_template,
|
key: :oauth_consumer_template,
|
||||||
|
label: "OAuth consumer template",
|
||||||
type: :string,
|
type: :string,
|
||||||
description:
|
description:
|
||||||
"OAuth consumer mode authentication form template. By default it's `consumer.html` which corresponds to" <>
|
"OAuth consumer mode authentication form template. By default it's `consumer.html` which corresponds to" <>
|
||||||
|
@ -2378,6 +2448,7 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :oauth_consumer_strategies,
|
key: :oauth_consumer_strategies,
|
||||||
|
label: "OAuth consumer strategies",
|
||||||
type: {:list, :string},
|
type: {:list, :string},
|
||||||
description:
|
description:
|
||||||
"The list of enabled OAuth consumer strategies. By default it's set by OAUTH_CONSUMER_STRATEGIES environment variable." <>
|
"The list of enabled OAuth consumer strategies. By default it's set by OAUTH_CONSUMER_STRATEGIES environment variable." <>
|
||||||
|
@ -2506,7 +2577,7 @@
|
||||||
%{
|
%{
|
||||||
key: :enabled,
|
key: :enabled,
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "enables new users admin digest email when `true`",
|
description: "Enables new users admin digest email when `true`",
|
||||||
suggestions: [false]
|
suggestions: [false]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -2514,6 +2585,7 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :oauth2,
|
key: :oauth2,
|
||||||
|
label: "OAuth2",
|
||||||
type: :group,
|
type: :group,
|
||||||
description: "Configure OAuth 2 provider capabilities",
|
description: "Configure OAuth 2 provider capabilities",
|
||||||
children: [
|
children: [
|
||||||
|
@ -2532,7 +2604,7 @@
|
||||||
%{
|
%{
|
||||||
key: :clean_expired_tokens,
|
key: :clean_expired_tokens,
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Enable a background job to clean expired oauth tokens. Default: disabled."
|
description: "Enable a background job to clean expired OAuth tokens. Default: disabled."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -2616,6 +2688,7 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :relation_id_action,
|
key: :relation_id_action,
|
||||||
|
label: "Relation ID action",
|
||||||
type: [:tuple, {:list, :tuple}],
|
type: [:tuple, {:list, :tuple}],
|
||||||
description: "For actions on relation with a specific user (follow, unfollow)",
|
description: "For actions on relation with a specific user (follow, unfollow)",
|
||||||
suggestions: [{1000, 10}, [{10_000, 10}, {10_000, 50}]]
|
suggestions: [{1000, 10}, [{10_000, 10}, {10_000, 50}]]
|
||||||
|
@ -2629,6 +2702,7 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :status_id_action,
|
key: :status_id_action,
|
||||||
|
label: "Status ID action",
|
||||||
type: [:tuple, {:list, :tuple}],
|
type: [:tuple, {:list, :tuple}],
|
||||||
description:
|
description:
|
||||||
"For fav / unfav or reblog / unreblog actions on the same status by the same user",
|
"For fav / unfav or reblog / unreblog actions on the same status by the same user",
|
||||||
|
@ -2644,6 +2718,7 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
group: :esshd,
|
group: :esshd,
|
||||||
|
label: "ESSHD",
|
||||||
type: :group,
|
type: :group,
|
||||||
description:
|
description:
|
||||||
"Before enabling this you must add :esshd to mix.exs as one of the extra_applications " <>
|
"Before enabling this you must add :esshd to mix.exs as one of the extra_applications " <>
|
||||||
|
@ -2682,8 +2757,9 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
group: :mime,
|
group: :mime,
|
||||||
|
label: "Mime Types",
|
||||||
type: :group,
|
type: :group,
|
||||||
description: "Mime types",
|
description: "Mime Types settings",
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
key: :types,
|
key: :types,
|
||||||
|
@ -2742,6 +2818,7 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :http,
|
key: :http,
|
||||||
|
label: "HTTP",
|
||||||
type: :group,
|
type: :group,
|
||||||
description: "HTTP settings",
|
description: "HTTP settings",
|
||||||
children: [
|
children: [
|
||||||
|
@ -2790,6 +2867,7 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :markup,
|
key: :markup,
|
||||||
|
label: "Markup Settings",
|
||||||
type: :group,
|
type: :group,
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
|
@ -2830,8 +2908,9 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
|
tab: :mrf,
|
||||||
key: :mrf_normalize_markup,
|
key: :mrf_normalize_markup,
|
||||||
label: "MRF normalize markup",
|
label: "MRF Normalize Markup",
|
||||||
description: "MRF NormalizeMarkup settings. Scrub configured hypertext markup.",
|
description: "MRF NormalizeMarkup settings. Scrub configured hypertext markup.",
|
||||||
type: :group,
|
type: :group,
|
||||||
children: [
|
children: [
|
||||||
|
@ -2887,6 +2966,7 @@
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
group: :cors_plug,
|
group: :cors_plug,
|
||||||
|
label: "CORS plug config",
|
||||||
type: :group,
|
type: :group,
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
|
@ -2959,6 +3039,7 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :web_cache_ttl,
|
key: :web_cache_ttl,
|
||||||
|
label: "Web cache TTL",
|
||||||
type: :group,
|
type: :group,
|
||||||
description:
|
description:
|
||||||
"The expiration time for the web responses cache. Values should be in milliseconds or `nil` to disable expiration.",
|
"The expiration time for the web responses cache. Values should be in milliseconds or `nil` to disable expiration.",
|
||||||
|
@ -2981,9 +3062,10 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :static_fe,
|
key: :static_fe,
|
||||||
|
label: "Static FE",
|
||||||
type: :group,
|
type: :group,
|
||||||
description:
|
description:
|
||||||
"Render profiles and posts using server-generated HTML that is viewable without using JavaScript.",
|
"Render profiles and posts using server-generated HTML that is viewable without using JavaScript",
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
key: :enabled,
|
key: :enabled,
|
||||||
|
@ -3001,18 +3083,18 @@
|
||||||
%{
|
%{
|
||||||
key: :post_title,
|
key: :post_title,
|
||||||
type: :map,
|
type: :map,
|
||||||
description: "Configure title rendering.",
|
description: "Configure title rendering",
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
key: :max_length,
|
key: :max_length,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
description: "Maximum number of characters before truncating title.",
|
description: "Maximum number of characters before truncating title",
|
||||||
suggestions: [100]
|
suggestions: [100]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :omission,
|
key: :omission,
|
||||||
type: :string,
|
type: :string,
|
||||||
description: "Replacement which will be used after truncating string.",
|
description: "Replacement which will be used after truncating string",
|
||||||
suggestions: ["..."]
|
suggestions: ["..."]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -3022,8 +3104,11 @@
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :mrf_object_age,
|
key: :mrf_object_age,
|
||||||
|
label: "MRF Object Age",
|
||||||
|
tab: :mrf,
|
||||||
type: :group,
|
type: :group,
|
||||||
description: "Rejects or delists posts based on their age when received.",
|
description:
|
||||||
|
"Rejects or delists posts based on their timestamp deviance from your server's clock.",
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
key: :threshold,
|
key: :threshold,
|
||||||
|
@ -3036,7 +3121,7 @@
|
||||||
type: {:list, :atom},
|
type: {:list, :atom},
|
||||||
description:
|
description:
|
||||||
"A list of actions to apply to the post. `:delist` removes the post from public timelines; " <>
|
"A list of actions to apply to the post. `:delist` removes the post from public timelines; " <>
|
||||||
"`:strip_followers` removes followers from the ActivityPub recipient list, ensuring they won't be delivered to home timelines; " <>
|
"`:strip_followers` removes followers from the ActivityPub recipient list ensuring they won't be delivered to home timelines; " <>
|
||||||
"`:reject` rejects the message entirely",
|
"`:reject` rejects the message entirely",
|
||||||
suggestions: [:delist, :strip_followers, :reject]
|
suggestions: [:delist, :strip_followers, :reject]
|
||||||
}
|
}
|
||||||
|
@ -3064,13 +3149,13 @@
|
||||||
%{
|
%{
|
||||||
key: :workers,
|
key: :workers,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
description: "Number of workers to send notifications.",
|
description: "Number of workers to send notifications",
|
||||||
suggestions: [3]
|
suggestions: [3]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :overflow_workers,
|
key: :overflow_workers,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
description: "Maximum number of workers created if pool is empty.",
|
description: "Maximum number of workers created if pool is empty",
|
||||||
suggestions: [2]
|
suggestions: [2]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -3361,41 +3446,5 @@
|
||||||
suggestions: [false]
|
suggestions: [false]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
|
||||||
%{
|
|
||||||
group: :pleroma,
|
|
||||||
key: :mrf,
|
|
||||||
type: :group,
|
|
||||||
description: "General MRF settings",
|
|
||||||
children: [
|
|
||||||
%{
|
|
||||||
key: :policies,
|
|
||||||
type: [:module, {:list, :module}],
|
|
||||||
description:
|
|
||||||
"A list of MRF policies enabled. Module names are shortened (removed leading `Pleroma.Web.ActivityPub.MRF.` part), but on adding custom module you need to use full name.",
|
|
||||||
suggestions:
|
|
||||||
Generator.list_modules_in_dir(
|
|
||||||
"lib/pleroma/web/activity_pub/mrf",
|
|
||||||
"Elixir.Pleroma.Web.ActivityPub.MRF."
|
|
||||||
)
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :transparency,
|
|
||||||
label: "MRF transparency",
|
|
||||||
type: :boolean,
|
|
||||||
description:
|
|
||||||
"Make the content of your Message Rewrite Facility settings public (via nodeinfo)"
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :transparency_exclusions,
|
|
||||||
label: "MRF transparency exclusions",
|
|
||||||
type: {:list, :string},
|
|
||||||
description:
|
|
||||||
"Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.",
|
|
||||||
suggestions: [
|
|
||||||
"exclusion.com"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -27,6 +27,7 @@ Has these additional fields under the `pleroma` object:
|
||||||
- `expires_at`: a datetime (iso8601) that states when the post will expire (be deleted automatically), or empty if the post won't expire
|
- `expires_at`: a datetime (iso8601) that states when the post will expire (be deleted automatically), or empty if the post won't expire
|
||||||
- `thread_muted`: true if the thread the post belongs to is muted
|
- `thread_muted`: true if the thread the post belongs to is muted
|
||||||
- `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 1, me: true}`. Contains no information about the reacting users, for that use the `/statuses/:id/reactions` endpoint.
|
- `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 1, me: true}`. Contains no information about the reacting users, for that use the `/statuses/:id/reactions` endpoint.
|
||||||
|
- `parent_visible`: If the parent of this post is visible to the user or not.
|
||||||
|
|
||||||
## Media Attachments
|
## Media Attachments
|
||||||
|
|
||||||
|
@ -51,11 +52,14 @@ The `id` parameter can also be the `nickname` of the user. This only works in th
|
||||||
|
|
||||||
Has these additional fields under the `pleroma` object:
|
Has these additional fields under the `pleroma` object:
|
||||||
|
|
||||||
|
- `ap_id`: nullable URL string, ActivityPub id of the user
|
||||||
|
- `background_image`: nullable URL string, background image of the user
|
||||||
- `tags`: Lists an array of tags for the user
|
- `tags`: Lists an array of tags for the user
|
||||||
- `relationship{}`: Includes fields as documented for Mastodon API https://docs.joinmastodon.org/entities/relationship/
|
- `relationship` (object): Includes fields as documented for Mastodon API https://docs.joinmastodon.org/entities/relationship/
|
||||||
- `is_moderator`: boolean, nullable, true if user is a moderator
|
- `is_moderator`: boolean, nullable, true if user is a moderator
|
||||||
- `is_admin`: boolean, nullable, true if user is an admin
|
- `is_admin`: boolean, nullable, true if user is an admin
|
||||||
- `confirmation_pending`: boolean, true if a new user account is waiting on email confirmation to be activated
|
- `confirmation_pending`: boolean, true if a new user account is waiting on email confirmation to be activated
|
||||||
|
- `hide_favorites`: boolean, true when the user has hiding favorites enabled
|
||||||
- `hide_followers`: boolean, true when the user has follower hiding enabled
|
- `hide_followers`: boolean, true when the user has follower hiding enabled
|
||||||
- `hide_follows`: boolean, true when the user has follow hiding enabled
|
- `hide_follows`: boolean, true when the user has follow hiding enabled
|
||||||
- `hide_followers_count`: boolean, true when the user has follower stat hiding enabled
|
- `hide_followers_count`: boolean, true when the user has follower stat hiding enabled
|
||||||
|
@ -66,6 +70,7 @@ Has these additional fields under the `pleroma` object:
|
||||||
- `allow_following_move`: boolean, true when the user allows automatically follow moved following accounts
|
- `allow_following_move`: boolean, true when the user allows automatically follow moved following accounts
|
||||||
- `unread_conversation_count`: The count of unread conversations. Only returned to the account owner.
|
- `unread_conversation_count`: The count of unread conversations. Only returned to the account owner.
|
||||||
- `unread_notifications_count`: The count of unread notifications. Only returned to the account owner.
|
- `unread_notifications_count`: The count of unread notifications. Only returned to the account owner.
|
||||||
|
- `notification_settings`: object, can be absent. See `/api/pleroma/notification_settings` for the parameters/keys returned.
|
||||||
|
|
||||||
### Source
|
### Source
|
||||||
|
|
||||||
|
@ -223,6 +228,7 @@ Has theses additional parameters (which are the same as in Pleroma-API):
|
||||||
- `background_image`: A background image that frontends can use
|
- `background_image`: A background image that frontends can use
|
||||||
- `pleroma.metadata.features`: A list of supported features
|
- `pleroma.metadata.features`: A list of supported features
|
||||||
- `pleroma.metadata.federation`: The federation restrictions of this instance
|
- `pleroma.metadata.federation`: The federation restrictions of this instance
|
||||||
|
- `pleroma.metadata.fields_limits`: A list of values detailing the length and count limitation for various instance-configurable fields.
|
||||||
- `vapid_public_key`: The public key needed for push messages
|
- `vapid_public_key`: The public key needed for push messages
|
||||||
|
|
||||||
## Markers
|
## Markers
|
||||||
|
|
|
@ -12,6 +12,11 @@ defmodule Pleroma.Config.Loader do
|
||||||
:swarm
|
:swarm
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@reject_groups [
|
||||||
|
:postgrex,
|
||||||
|
:tesla
|
||||||
|
]
|
||||||
|
|
||||||
if Code.ensure_loaded?(Config.Reader) do
|
if Code.ensure_loaded?(Config.Reader) do
|
||||||
@reader Config.Reader
|
@reader Config.Reader
|
||||||
|
|
||||||
|
@ -47,7 +52,8 @@ defp filter(configs) do
|
||||||
@spec filter_group(atom(), keyword()) :: keyword()
|
@spec filter_group(atom(), keyword()) :: keyword()
|
||||||
def filter_group(group, configs) do
|
def filter_group(group, configs) do
|
||||||
Enum.reject(configs[group], fn {key, _v} ->
|
Enum.reject(configs[group], fn {key, _v} ->
|
||||||
key in @reject_keys or (group == :phoenix and key == :serve_endpoints) or group == :postgrex
|
key in @reject_keys or group in @reject_groups or
|
||||||
|
(group == :phoenix and key == :serve_endpoints)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -109,7 +109,7 @@ def extract_first_external_url(object, content) do
|
||||||
result =
|
result =
|
||||||
content
|
content
|
||||||
|> Floki.parse_fragment!()
|
|> Floki.parse_fragment!()
|
||||||
|> Floki.filter_out("a.mention,a.hashtag,a[rel~=\"tag\"]")
|
|> Floki.filter_out("a.mention,a.hashtag,a.attachment,a[rel~=\"tag\"]")
|
||||||
|> Floki.attribute("a", "href")
|
|> Floki.attribute("a", "href")
|
||||||
|> Enum.at(0)
|
|> Enum.at(0)
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.MigrationHelper.NotificationBackfill do
|
defmodule Pleroma.MigrationHelper.NotificationBackfill do
|
||||||
alias Pleroma.Notification
|
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
@ -25,18 +24,27 @@ def fill_in_notification_types do
|
||||||
|> type_from_activity()
|
|> type_from_activity()
|
||||||
|
|
||||||
notification
|
notification
|
||||||
|> Notification.changeset(%{type: type})
|
|> Ecto.Changeset.change(%{type: type})
|
||||||
|> Repo.update()
|
|> Repo.update()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp get_by_ap_id(ap_id) do
|
||||||
|
q =
|
||||||
|
from(u in User,
|
||||||
|
select: u.id
|
||||||
|
)
|
||||||
|
|
||||||
|
Repo.get_by(q, ap_id: ap_id)
|
||||||
|
end
|
||||||
|
|
||||||
# This is copied over from Notifications to keep this stable.
|
# This is copied over from Notifications to keep this stable.
|
||||||
defp type_from_activity(%{data: %{"type" => type}} = activity) do
|
defp type_from_activity(%{data: %{"type" => type}} = activity) do
|
||||||
case type do
|
case type do
|
||||||
"Follow" ->
|
"Follow" ->
|
||||||
accepted_function = fn activity ->
|
accepted_function = fn activity ->
|
||||||
with %User{} = follower <- User.get_by_ap_id(activity.data["actor"]),
|
with %User{} = follower <- get_by_ap_id(activity.data["actor"]),
|
||||||
%User{} = followed <- User.get_by_ap_id(activity.data["object"]) do
|
%User{} = followed <- get_by_ap_id(activity.data["object"]) do
|
||||||
Pleroma.FollowingRelationship.following?(follower, followed)
|
Pleroma.FollowingRelationship.following?(follower, followed)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -367,6 +367,7 @@ defp do_create_notifications(%Activity{} = activity, options) do
|
||||||
do_send = do_send && user in enabled_receivers
|
do_send = do_send && user in enabled_receivers
|
||||||
create_notification(activity, user, do_send)
|
create_notification(activity, user, do_send)
|
||||||
end)
|
end)
|
||||||
|
|> Enum.reject(&is_nil/1)
|
||||||
|
|
||||||
{:ok, notifications}
|
{:ok, notifications}
|
||||||
end
|
end
|
||||||
|
|
|
@ -83,8 +83,8 @@ def fetch_object_from_id(id, options \\ []) do
|
||||||
{:transmogrifier, {:error, {:reject, nil}}} ->
|
{:transmogrifier, {:error, {:reject, nil}}} ->
|
||||||
{:reject, nil}
|
{:reject, nil}
|
||||||
|
|
||||||
{:transmogrifier, _} ->
|
{:transmogrifier, _} = e ->
|
||||||
{:error, "Transmogrifier failure."}
|
{:error, e}
|
||||||
|
|
||||||
{:object, data, nil} ->
|
{:object, data, nil} ->
|
||||||
reinject_object(%Object{}, data)
|
reinject_object(%Object{}, data)
|
||||||
|
|
|
@ -115,7 +115,7 @@ defmodule Pleroma.User do
|
||||||
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(:show_role, :boolean, default: true)
|
||||||
field(:settings, :map, default: nil)
|
field(:mastofe_settings, :map, default: nil)
|
||||||
field(:uri, ObjectValidators.Uri, default: nil)
|
field(:uri, ObjectValidators.Uri, default: nil)
|
||||||
field(:hide_followers_count, :boolean, default: false)
|
field(:hide_followers_count, :boolean, default: false)
|
||||||
field(:hide_follows_count, :boolean, default: false)
|
field(:hide_follows_count, :boolean, default: false)
|
||||||
|
@ -1309,7 +1309,8 @@ def block(%User{} = blocker, %User{} = blocked) do
|
||||||
|
|
||||||
unsubscribe(blocked, blocker)
|
unsubscribe(blocked, blocker)
|
||||||
|
|
||||||
if following?(blocked, blocker), do: unfollow(blocked, blocker)
|
unfollowing_blocked = Config.get([:activitypub, :unfollow_blocked], true)
|
||||||
|
if unfollowing_blocked && following?(blocked, blocker), do: unfollow(blocked, blocker)
|
||||||
|
|
||||||
{:ok, blocker} = update_follower_count(blocker)
|
{:ok, blocker} = update_follower_count(blocker)
|
||||||
{:ok, blocker, _} = Participation.mark_all_as_read(blocker, blocked)
|
{:ok, blocker, _} = Participation.mark_all_as_read(blocker, blocked)
|
||||||
|
@ -1527,8 +1528,7 @@ def perform(:blocks_import, %User{} = blocker, blocked_identifiers)
|
||||||
blocked_identifiers,
|
blocked_identifiers,
|
||||||
fn blocked_identifier ->
|
fn blocked_identifier ->
|
||||||
with {:ok, %User{} = blocked} <- get_or_fetch(blocked_identifier),
|
with {:ok, %User{} = blocked} <- get_or_fetch(blocked_identifier),
|
||||||
{:ok, _user_block} <- block(blocker, blocked),
|
{:ok, _block} <- CommonAPI.block(blocker, blocked) do
|
||||||
{:ok, _} <- ActivityPub.block(blocker, blocked) do
|
|
||||||
blocked
|
blocked
|
||||||
else
|
else
|
||||||
err ->
|
err ->
|
||||||
|
@ -2118,8 +2118,8 @@ def mascot_update(user, url) do
|
||||||
|
|
||||||
def mastodon_settings_update(user, settings) do
|
def mastodon_settings_update(user, settings) do
|
||||||
user
|
user
|
||||||
|> cast(%{settings: settings}, [:settings])
|
|> cast(%{mastofe_settings: settings}, [:mastofe_settings])
|
||||||
|> validate_required([:settings])
|
|> validate_required([:mastofe_settings])
|
||||||
|> update_and_set_cache()
|
|> update_and_set_cache()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ defp search_query(query_string, for_user, following) do
|
||||||
|> base_query(following)
|
|> base_query(following)
|
||||||
|> filter_blocked_user(for_user)
|
|> filter_blocked_user(for_user)
|
||||||
|> filter_invisible_users()
|
|> filter_invisible_users()
|
||||||
|
|> filter_internal_users()
|
||||||
|> filter_blocked_domains(for_user)
|
|> filter_blocked_domains(for_user)
|
||||||
|> fts_search(query_string)
|
|> fts_search(query_string)
|
||||||
|> trigram_rank(query_string)
|
|> trigram_rank(query_string)
|
||||||
|
@ -109,6 +110,10 @@ defp filter_invisible_users(query) do
|
||||||
from(q in query, where: q.invisible == false)
|
from(q in query, where: q.invisible == false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp filter_internal_users(query) do
|
||||||
|
from(q in query, where: q.actor_type != "Application")
|
||||||
|
end
|
||||||
|
|
||||||
defp filter_blocked_user(query, %User{} = blocker) do
|
defp filter_blocked_user(query, %User{} = blocker) do
|
||||||
query
|
query
|
||||||
|> join(:left, [u], b in Pleroma.UserRelationship,
|
|> join(:left, [u], b in Pleroma.UserRelationship,
|
||||||
|
|
|
@ -366,33 +366,6 @@ defp do_unfollow(follower, followed, activity_id, local) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec block(User.t(), User.t(), String.t() | nil, boolean()) ::
|
|
||||||
{:ok, Activity.t()} | {:error, any()}
|
|
||||||
def block(blocker, blocked, activity_id \\ nil, local \\ true) do
|
|
||||||
with {:ok, result} <-
|
|
||||||
Repo.transaction(fn -> do_block(blocker, blocked, activity_id, local) end) do
|
|
||||||
result
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp do_block(blocker, blocked, activity_id, local) do
|
|
||||||
unfollow_blocked = Config.get([:activitypub, :unfollow_blocked])
|
|
||||||
|
|
||||||
if unfollow_blocked and fetch_latest_follow(blocker, blocked) do
|
|
||||||
unfollow(blocker, blocked, nil, local)
|
|
||||||
end
|
|
||||||
|
|
||||||
block_data = make_block_data(blocker, blocked, activity_id)
|
|
||||||
|
|
||||||
with {:ok, activity} <- insert(block_data, local),
|
|
||||||
_ <- notify_and_stream(activity),
|
|
||||||
:ok <- maybe_federate(activity) do
|
|
||||||
{:ok, activity}
|
|
||||||
else
|
|
||||||
{:error, error} -> Repo.rollback(error)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@spec flag(map()) :: {:ok, Activity.t()} | {:error, any()}
|
@spec flag(map()) :: {:ok, Activity.t()} | {:error, any()}
|
||||||
def flag(
|
def flag(
|
||||||
%{
|
%{
|
||||||
|
@ -1398,6 +1371,16 @@ def fetch_and_prepare_user_from_ap_id(ap_id) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def maybe_handle_clashing_nickname(nickname) do
|
||||||
|
with %User{} = old_user <- User.get_by_nickname(nickname) do
|
||||||
|
Logger.info("Found an old user for #{nickname}, ap id is #{old_user.ap_id}, renaming.")
|
||||||
|
|
||||||
|
old_user
|
||||||
|
|> User.remote_user_changeset(%{nickname: "#{old_user.id}.#{old_user.nickname}"})
|
||||||
|
|> User.update_and_set_cache()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def make_user_from_ap_id(ap_id) do
|
def make_user_from_ap_id(ap_id) do
|
||||||
user = User.get_cached_by_ap_id(ap_id)
|
user = User.get_cached_by_ap_id(ap_id)
|
||||||
|
|
||||||
|
@ -1410,6 +1393,8 @@ def make_user_from_ap_id(ap_id) do
|
||||||
|> User.remote_user_changeset(data)
|
|> User.remote_user_changeset(data)
|
||||||
|> User.update_and_set_cache()
|
|> User.update_and_set_cache()
|
||||||
else
|
else
|
||||||
|
maybe_handle_clashing_nickname(data[:nickname])
|
||||||
|
|
||||||
data
|
data
|
||||||
|> User.remote_user_changeset()
|
|> User.remote_user_changeset()
|
||||||
|> Repo.insert()
|
|> Repo.insert()
|
||||||
|
|
|
@ -138,6 +138,18 @@ def update(actor, object) do
|
||||||
}, []}
|
}, []}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec block(User.t(), User.t()) :: {:ok, map(), keyword()}
|
||||||
|
def block(blocker, blocked) do
|
||||||
|
{:ok,
|
||||||
|
%{
|
||||||
|
"id" => Utils.generate_activity_id(),
|
||||||
|
"type" => "Block",
|
||||||
|
"actor" => blocker.ap_id,
|
||||||
|
"object" => blocked.ap_id,
|
||||||
|
"to" => [blocked.ap_id]
|
||||||
|
}, []}
|
||||||
|
end
|
||||||
|
|
||||||
@spec announce(User.t(), Object.t(), keyword()) :: {:ok, map(), keyword()}
|
@spec announce(User.t(), Object.t(), keyword()) :: {:ok, map(), keyword()}
|
||||||
def announce(actor, object, options \\ []) do
|
def announce(actor, object, options \\ []) do
|
||||||
public? = Keyword.get(options, :public, false)
|
public? = Keyword.get(options, :public, false)
|
||||||
|
|
|
@ -27,11 +27,14 @@ defp contains_links?(_), do: false
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def filter(%{"type" => "Create", "actor" => actor, "object" => object} = message) do
|
def filter(%{"type" => "Create", "actor" => actor, "object" => object} = message) do
|
||||||
with {:ok, %User{} = u} <- User.get_or_fetch_by_ap_id(actor),
|
with {:ok, %User{local: false} = u} <- User.get_or_fetch_by_ap_id(actor),
|
||||||
{:contains_links, true} <- {:contains_links, contains_links?(object)},
|
{:contains_links, true} <- {:contains_links, contains_links?(object)},
|
||||||
{:old_user, true} <- {:old_user, old_user?(u)} do
|
{:old_user, true} <- {:old_user, old_user?(u)} do
|
||||||
{:ok, message}
|
{:ok, message}
|
||||||
else
|
else
|
||||||
|
{:ok, %User{local: true}} ->
|
||||||
|
{:ok, message}
|
||||||
|
|
||||||
{:contains_links, false} ->
|
{:contains_links, false} ->
|
||||||
{:ok, message}
|
{:ok, message}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator
|
alias Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator
|
||||||
|
alias Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator
|
||||||
alias Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator
|
alias Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator
|
||||||
alias Pleroma.Web.ActivityPub.ObjectValidators.CreateChatMessageValidator
|
alias Pleroma.Web.ActivityPub.ObjectValidators.CreateChatMessageValidator
|
||||||
alias Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator
|
alias Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator
|
||||||
|
@ -24,6 +25,25 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
|
||||||
@spec validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
|
@spec validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
|
||||||
def validate(object, meta)
|
def validate(object, meta)
|
||||||
|
|
||||||
|
def validate(%{"type" => "Block"} = block_activity, meta) do
|
||||||
|
with {:ok, block_activity} <-
|
||||||
|
block_activity
|
||||||
|
|> BlockValidator.cast_and_validate()
|
||||||
|
|> Ecto.Changeset.apply_action(:insert) do
|
||||||
|
block_activity = stringify_keys(block_activity)
|
||||||
|
outgoing_blocks = Pleroma.Config.get([:activitypub, :outgoing_blocks])
|
||||||
|
|
||||||
|
meta =
|
||||||
|
if !outgoing_blocks do
|
||||||
|
Keyword.put(meta, :do_not_federate, true)
|
||||||
|
else
|
||||||
|
meta
|
||||||
|
end
|
||||||
|
|
||||||
|
{:ok, block_activity, meta}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def validate(%{"type" => "Update"} = update_activity, meta) do
|
def validate(%{"type" => "Update"} = update_activity, meta) do
|
||||||
with {:ok, update_activity} <-
|
with {:ok, update_activity} <-
|
||||||
update_activity
|
update_activity
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator do
|
||||||
|
use Ecto.Schema
|
||||||
|
|
||||||
|
alias Pleroma.EctoType.ActivityPub.ObjectValidators
|
||||||
|
|
||||||
|
import Ecto.Changeset
|
||||||
|
import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
|
||||||
|
|
||||||
|
@primary_key false
|
||||||
|
|
||||||
|
embedded_schema do
|
||||||
|
field(:id, ObjectValidators.ObjectID, primary_key: true)
|
||||||
|
field(:type, :string)
|
||||||
|
field(:actor, ObjectValidators.ObjectID)
|
||||||
|
field(:to, ObjectValidators.Recipients, default: [])
|
||||||
|
field(:cc, ObjectValidators.Recipients, default: [])
|
||||||
|
field(:object, ObjectValidators.ObjectID)
|
||||||
|
end
|
||||||
|
|
||||||
|
def cast_data(data) do
|
||||||
|
%__MODULE__{}
|
||||||
|
|> cast(data, __schema__(:fields))
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_data(cng) do
|
||||||
|
cng
|
||||||
|
|> validate_required([:id, :type, :actor, :to, :cc, :object])
|
||||||
|
|> validate_inclusion(:type, ["Block"])
|
||||||
|
|> validate_actor_presence()
|
||||||
|
|> validate_actor_presence(field_name: :object)
|
||||||
|
end
|
||||||
|
|
||||||
|
def cast_and_validate(data) do
|
||||||
|
data
|
||||||
|
|> cast_data
|
||||||
|
|> validate_data
|
||||||
|
end
|
||||||
|
end
|
|
@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
||||||
collection, and so on.
|
collection, and so on.
|
||||||
"""
|
"""
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
|
alias Pleroma.Activity.Ir.Topics
|
||||||
alias Pleroma.Chat
|
alias Pleroma.Chat
|
||||||
alias Pleroma.Chat.MessageReference
|
alias Pleroma.Chat.MessageReference
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
|
@ -20,6 +21,21 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
||||||
|
|
||||||
def handle(object, meta \\ [])
|
def handle(object, meta \\ [])
|
||||||
|
|
||||||
|
# Tasks this handles:
|
||||||
|
# - Unfollow and block
|
||||||
|
def handle(
|
||||||
|
%{data: %{"type" => "Block", "object" => blocked_user, "actor" => blocking_user}} =
|
||||||
|
object,
|
||||||
|
meta
|
||||||
|
) do
|
||||||
|
with %User{} = blocker <- User.get_cached_by_ap_id(blocking_user),
|
||||||
|
%User{} = blocked <- User.get_cached_by_ap_id(blocked_user) do
|
||||||
|
User.block(blocker, blocked)
|
||||||
|
end
|
||||||
|
|
||||||
|
{:ok, object, meta}
|
||||||
|
end
|
||||||
|
|
||||||
# Tasks this handles:
|
# Tasks this handles:
|
||||||
# - Update the user
|
# - Update the user
|
||||||
#
|
#
|
||||||
|
@ -82,7 +98,10 @@ def handle(%{data: %{"type" => "Announce"}} = object, meta) do
|
||||||
|
|
||||||
if !User.is_internal_user?(user) do
|
if !User.is_internal_user?(user) do
|
||||||
Notification.create_notifications(object)
|
Notification.create_notifications(object)
|
||||||
ActivityPub.stream_out(object)
|
|
||||||
|
object
|
||||||
|
|> Topics.get_activity_topics()
|
||||||
|
|> Streamer.stream(object)
|
||||||
end
|
end
|
||||||
|
|
||||||
{:ok, object, meta}
|
{:ok, object, meta}
|
||||||
|
|
|
@ -446,12 +446,9 @@ def handle_incoming(
|
||||||
when objtype in ["Article", "Event", "Note", "Video", "Page", "Question", "Answer", "Audio"] do
|
when objtype in ["Article", "Event", "Note", "Video", "Page", "Question", "Answer", "Audio"] do
|
||||||
actor = Containment.get_actor(data)
|
actor = Containment.get_actor(data)
|
||||||
|
|
||||||
data =
|
|
||||||
Map.put(data, "actor", actor)
|
|
||||||
|> fix_addressing
|
|
||||||
|
|
||||||
with nil <- Activity.get_create_by_object_ap_id(object["id"]),
|
with nil <- Activity.get_create_by_object_ap_id(object["id"]),
|
||||||
{:ok, %User{} = user} <- User.get_or_fetch_by_ap_id(data["actor"]) do
|
{:ok, %User{} = user} <- User.get_or_fetch_by_ap_id(actor),
|
||||||
|
data <- Map.put(data, "actor", actor) |> fix_addressing() do
|
||||||
object = fix_object(object, options)
|
object = fix_object(object, options)
|
||||||
|
|
||||||
params = %{
|
params = %{
|
||||||
|
@ -673,7 +670,7 @@ def handle_incoming(
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_incoming(%{"type" => type} = data, _options)
|
def handle_incoming(%{"type" => type} = data, _options)
|
||||||
when type in ["Like", "EmojiReact", "Announce"] do
|
when type in ~w{Like EmojiReact Announce} do
|
||||||
with :ok <- ObjectValidator.fetch_actor_and_object(data),
|
with :ok <- ObjectValidator.fetch_actor_and_object(data),
|
||||||
{:ok, activity, _meta} <-
|
{:ok, activity, _meta} <-
|
||||||
Pipeline.common_pipeline(data, local: false) do
|
Pipeline.common_pipeline(data, local: false) do
|
||||||
|
@ -684,9 +681,10 @@ def handle_incoming(%{"type" => type} = data, _options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_incoming(
|
def handle_incoming(
|
||||||
%{"type" => "Update"} = data,
|
%{"type" => type} = data,
|
||||||
_options
|
_options
|
||||||
) do
|
)
|
||||||
|
when type in ~w{Update Block} do
|
||||||
with {:ok, %User{}} <- ObjectValidator.fetch_actor(data),
|
with {:ok, %User{}} <- ObjectValidator.fetch_actor(data),
|
||||||
{:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do
|
{:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do
|
||||||
{:ok, activity}
|
{:ok, activity}
|
||||||
|
@ -765,21 +763,6 @@ def handle_incoming(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_incoming(
|
|
||||||
%{"type" => "Block", "object" => blocked, "actor" => blocker, "id" => id} = _data,
|
|
||||||
_options
|
|
||||||
) do
|
|
||||||
with %User{local: true} = blocked = User.get_cached_by_ap_id(blocked),
|
|
||||||
{:ok, %User{} = blocker} = User.get_or_fetch_by_ap_id(blocker),
|
|
||||||
{:ok, activity} <- ActivityPub.block(blocker, blocked, id, false) do
|
|
||||||
User.unfollow(blocker, blocked)
|
|
||||||
User.block(blocker, blocked)
|
|
||||||
{:ok, activity}
|
|
||||||
else
|
|
||||||
_e -> :error
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_incoming(
|
def handle_incoming(
|
||||||
%{
|
%{
|
||||||
"type" => "Move",
|
"type" => "Move",
|
||||||
|
|
|
@ -47,6 +47,10 @@ def is_list?(_), do: false
|
||||||
@spec visible_for_user?(Activity.t(), User.t() | nil) :: boolean()
|
@spec visible_for_user?(Activity.t(), User.t() | nil) :: boolean()
|
||||||
def visible_for_user?(%{actor: ap_id}, %User{ap_id: ap_id}), do: true
|
def visible_for_user?(%{actor: ap_id}, %User{ap_id: ap_id}), do: true
|
||||||
|
|
||||||
|
def visible_for_user?(nil, _), do: false
|
||||||
|
|
||||||
|
def visible_for_user?(%{data: %{"listMessage" => _}}, nil), do: false
|
||||||
|
|
||||||
def visible_for_user?(%{data: %{"listMessage" => list_ap_id}} = activity, %User{} = user) do
|
def visible_for_user?(%{data: %{"listMessage" => list_ap_id}} = activity, %User{} = user) do
|
||||||
user.ap_id in activity.data["to"] ||
|
user.ap_id in activity.data["to"] ||
|
||||||
list_ap_id
|
list_ap_id
|
||||||
|
@ -54,8 +58,6 @@ def visible_for_user?(%{data: %{"listMessage" => list_ap_id}} = activity, %User{
|
||||||
|> Pleroma.List.member?(user)
|
|> Pleroma.List.member?(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def visible_for_user?(%{data: %{"listMessage" => _}}, nil), do: false
|
|
||||||
|
|
||||||
def visible_for_user?(%{local: local} = activity, nil) do
|
def visible_for_user?(%{local: local} = activity, nil) do
|
||||||
cfg_key =
|
cfg_key =
|
||||||
if local,
|
if local,
|
||||||
|
|
|
@ -40,7 +40,7 @@ def call(%{private: %{open_api_spex: private_data}} = conn, %{
|
||||||
|> List.first()
|
|> List.first()
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
nil
|
"application/json"
|
||||||
end
|
end
|
||||||
|
|
||||||
private_data = Map.put(private_data, :operation_id, operation_id)
|
private_data = Map.put(private_data, :operation_id, operation_id)
|
||||||
|
|
|
@ -84,7 +84,7 @@ def delete_operation do
|
||||||
operationId: "StatusController.delete",
|
operationId: "StatusController.delete",
|
||||||
parameters: [id_param()],
|
parameters: [id_param()],
|
||||||
responses: %{
|
responses: %{
|
||||||
200 => empty_object_response(),
|
200 => status_response(),
|
||||||
403 => Operation.response("Forbidden", "application/json", ApiError),
|
403 => Operation.response("Forbidden", "application/json", ApiError),
|
||||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,20 +40,53 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
|
||||||
pleroma: %Schema{
|
pleroma: %Schema{
|
||||||
type: :object,
|
type: :object,
|
||||||
properties: %{
|
properties: %{
|
||||||
allow_following_move: %Schema{type: :boolean},
|
allow_following_move: %Schema{
|
||||||
background_image: %Schema{type: :string, nullable: true},
|
type: :boolean,
|
||||||
|
description: "whether the user allows automatically follow moved following accounts"
|
||||||
|
},
|
||||||
|
background_image: %Schema{type: :string, nullable: true, format: :uri},
|
||||||
chat_token: %Schema{type: :string},
|
chat_token: %Schema{type: :string},
|
||||||
confirmation_pending: %Schema{type: :boolean},
|
confirmation_pending: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description:
|
||||||
|
"whether the user account is waiting on email confirmation to be activated"
|
||||||
|
},
|
||||||
hide_favorites: %Schema{type: :boolean},
|
hide_favorites: %Schema{type: :boolean},
|
||||||
hide_followers_count: %Schema{type: :boolean},
|
hide_followers_count: %Schema{
|
||||||
hide_followers: %Schema{type: :boolean},
|
type: :boolean,
|
||||||
hide_follows_count: %Schema{type: :boolean},
|
description: "whether the user has follower stat hiding enabled"
|
||||||
hide_follows: %Schema{type: :boolean},
|
},
|
||||||
is_admin: %Schema{type: :boolean},
|
hide_followers: %Schema{
|
||||||
is_moderator: %Schema{type: :boolean},
|
type: :boolean,
|
||||||
|
description: "whether the user has follower hiding enabled"
|
||||||
|
},
|
||||||
|
hide_follows_count: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "whether the user has follow stat hiding enabled"
|
||||||
|
},
|
||||||
|
hide_follows: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "whether the user has follow hiding enabled"
|
||||||
|
},
|
||||||
|
is_admin: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "whether the user is an admin of the local instance"
|
||||||
|
},
|
||||||
|
is_moderator: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "whether the user is a moderator of the local instance"
|
||||||
|
},
|
||||||
skip_thread_containment: %Schema{type: :boolean},
|
skip_thread_containment: %Schema{type: :boolean},
|
||||||
tags: %Schema{type: :array, items: %Schema{type: :string}},
|
tags: %Schema{
|
||||||
unread_conversation_count: %Schema{type: :integer},
|
type: :array,
|
||||||
|
items: %Schema{type: :string},
|
||||||
|
description:
|
||||||
|
"List of tags being used for things like extra roles or moderation(ie. marking all media as nsfw all)."
|
||||||
|
},
|
||||||
|
unread_conversation_count: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
description: "The count of unread conversations. Only returned to the account owner."
|
||||||
|
},
|
||||||
notification_settings: %Schema{
|
notification_settings: %Schema{
|
||||||
type: :object,
|
type: :object,
|
||||||
properties: %{
|
properties: %{
|
||||||
|
@ -66,7 +99,9 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
|
||||||
},
|
},
|
||||||
relationship: AccountRelationship,
|
relationship: AccountRelationship,
|
||||||
settings_store: %Schema{
|
settings_store: %Schema{
|
||||||
type: :object
|
type: :object,
|
||||||
|
description:
|
||||||
|
"A generic map of settings for frontends. Opaque to the backend. Only returned in `verify_credentials` and `update_credentials`"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -74,16 +109,32 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
|
||||||
type: :object,
|
type: :object,
|
||||||
properties: %{
|
properties: %{
|
||||||
fields: %Schema{type: :array, items: AccountField},
|
fields: %Schema{type: :array, items: AccountField},
|
||||||
note: %Schema{type: :string},
|
note: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description:
|
||||||
|
"Plaintext version of the bio without formatting applied by the backend, used for editing the bio."
|
||||||
|
},
|
||||||
privacy: VisibilityScope,
|
privacy: VisibilityScope,
|
||||||
sensitive: %Schema{type: :boolean},
|
sensitive: %Schema{type: :boolean},
|
||||||
pleroma: %Schema{
|
pleroma: %Schema{
|
||||||
type: :object,
|
type: :object,
|
||||||
properties: %{
|
properties: %{
|
||||||
actor_type: ActorType,
|
actor_type: ActorType,
|
||||||
discoverable: %Schema{type: :boolean},
|
discoverable: %Schema{
|
||||||
no_rich_text: %Schema{type: :boolean},
|
type: :boolean,
|
||||||
show_role: %Schema{type: :boolean}
|
description:
|
||||||
|
"whether the user allows discovery of the account in search results and other services."
|
||||||
|
},
|
||||||
|
no_rich_text: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description:
|
||||||
|
"whether the HTML tags for rich-text formatting are stripped from all statuses requested from the API."
|
||||||
|
},
|
||||||
|
show_role: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description:
|
||||||
|
"whether the user wants their role (e.g admin, moderator) to be shown"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,11 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
content: %Schema{type: :string, format: :html, description: "HTML-encoded status content"},
|
content: %Schema{type: :string, format: :html, description: "HTML-encoded status content"},
|
||||||
|
text: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "Original unformatted content in plain text",
|
||||||
|
nullable: true
|
||||||
|
},
|
||||||
created_at: %Schema{
|
created_at: %Schema{
|
||||||
type: :string,
|
type: :string,
|
||||||
format: "date-time",
|
format: "date-time",
|
||||||
|
@ -184,6 +189,10 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
|
||||||
thread_muted: %Schema{
|
thread_muted: %Schema{
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "`true` if the thread the post belongs to is muted"
|
description: "`true` if the thread the post belongs to is muted"
|
||||||
|
},
|
||||||
|
parent_visible: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "`true` if the parent post is visible to the user"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -186,6 +186,7 @@ defp object(draft) do
|
||||||
draft.poll
|
draft.poll
|
||||||
)
|
)
|
||||||
|> Map.put("emoji", emoji)
|
|> Map.put("emoji", emoji)
|
||||||
|
|> Map.put("source", draft.status)
|
||||||
|
|
||||||
%__MODULE__{draft | object: object}
|
%__MODULE__{draft | object: object}
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,6 +25,13 @@ defmodule Pleroma.Web.CommonAPI do
|
||||||
require Pleroma.Constants
|
require Pleroma.Constants
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
|
def block(blocker, blocked) do
|
||||||
|
with {:ok, block_data, _} <- Builder.block(blocker, blocked),
|
||||||
|
{:ok, block, _} <- Pipeline.common_pipeline(block_data, local: true) do
|
||||||
|
{:ok, block}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def post_chat_message(%User{} = user, %User{} = recipient, content, opts \\ []) do
|
def post_chat_message(%User{} = user, %User{} = recipient, content, opts \\ []) do
|
||||||
with maybe_attachment <- opts[:media_id] && Object.get_by_id(opts[:media_id]),
|
with maybe_attachment <- opts[:media_id] && Object.get_by_id(opts[:media_id]),
|
||||||
:ok <- validate_chat_content_length(content, !!maybe_attachment),
|
:ok <- validate_chat_content_length(content, !!maybe_attachment),
|
||||||
|
|
|
@ -385,8 +385,7 @@ def unmute(%{assigns: %{user: muter, account: muted}} = conn, _params) do
|
||||||
|
|
||||||
@doc "POST /api/v1/accounts/:id/block"
|
@doc "POST /api/v1/accounts/:id/block"
|
||||||
def block(%{assigns: %{user: blocker, account: blocked}} = conn, _params) do
|
def block(%{assigns: %{user: blocker, account: blocked}} = conn, _params) do
|
||||||
with {:ok, _user_block} <- User.block(blocker, blocked),
|
with {:ok, _activity} <- CommonAPI.block(blocker, blocked) do
|
||||||
{:ok, _activity} <- ActivityPub.block(blocker, blocked) do
|
|
||||||
render(conn, "relationship.json", user: blocker, target: blocked)
|
render(conn, "relationship.json", user: blocker, target: blocked)
|
||||||
else
|
else
|
||||||
{:error, message} -> json_response(conn, :forbidden, %{error: message})
|
{:error, message} -> json_response(conn, :forbidden, %{error: message})
|
||||||
|
|
|
@ -44,6 +44,7 @@ def search2(conn, params), do: do_search(:v2, conn, params)
|
||||||
def search(conn, params), do: do_search(:v1, conn, params)
|
def search(conn, params), do: do_search(:v1, conn, params)
|
||||||
|
|
||||||
defp do_search(version, %{assigns: %{user: user}} = conn, %{q: query} = params) do
|
defp do_search(version, %{assigns: %{user: user}} = conn, %{q: query} = params) do
|
||||||
|
query = String.trim(query)
|
||||||
options = search_options(params, user)
|
options = search_options(params, user)
|
||||||
timeout = Keyword.get(Repo.config(), :timeout, 15_000)
|
timeout = Keyword.get(Repo.config(), :timeout, 15_000)
|
||||||
default_values = %{"statuses" => [], "accounts" => [], "hashtags" => []}
|
default_values = %{"statuses" => [], "accounts" => [], "hashtags" => []}
|
||||||
|
|
|
@ -200,11 +200,18 @@ def show(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||||
|
|
||||||
@doc "DELETE /api/v1/statuses/:id"
|
@doc "DELETE /api/v1/statuses/:id"
|
||||||
def delete(%{assigns: %{user: user}} = conn, %{id: id}) do
|
def delete(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||||
with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
|
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
||||||
json(conn, %{})
|
render <-
|
||||||
|
try_render(conn, "show.json",
|
||||||
|
activity: activity,
|
||||||
|
for: user,
|
||||||
|
with_direct_conversation_id: true,
|
||||||
|
with_source: true
|
||||||
|
),
|
||||||
|
{:ok, %Activity{}} <- CommonAPI.delete(id, user) do
|
||||||
|
render
|
||||||
else
|
else
|
||||||
{:error, :not_found} = e -> e
|
_e -> {:error, :not_found}
|
||||||
_e -> render_error(conn, :forbidden, "Can't delete this post")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,10 @@ def render("show.json", _) do
|
||||||
background_image: Keyword.get(instance, :background_image),
|
background_image: Keyword.get(instance, :background_image),
|
||||||
pleroma: %{
|
pleroma: %{
|
||||||
metadata: %{
|
metadata: %{
|
||||||
|
account_activation_required: Keyword.get(instance, :account_activation_required),
|
||||||
features: features(),
|
features: features(),
|
||||||
federation: federation()
|
federation: federation(),
|
||||||
|
fields_limits: fields_limits()
|
||||||
},
|
},
|
||||||
vapid_public_key: Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
|
vapid_public_key: Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
|
||||||
}
|
}
|
||||||
|
@ -88,4 +90,13 @@ def federation do
|
||||||
end
|
end
|
||||||
|> Map.put(:enabled, Config.get([:instance, :federating]))
|
|> Map.put(:enabled, Config.get([:instance, :federating]))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def fields_limits do
|
||||||
|
%{
|
||||||
|
max_fields: Config.get([:instance, :max_account_fields]),
|
||||||
|
max_remote_fields: Config.get([:instance, :max_remote_account_fields]),
|
||||||
|
name_length: Config.get([:instance, :account_field_name_length]),
|
||||||
|
value_length: Config.get([:instance, :account_field_value_length])
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,7 +21,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
alias Pleroma.Web.MediaProxy
|
alias Pleroma.Web.MediaProxy
|
||||||
|
|
||||||
import Pleroma.Web.ActivityPub.Visibility, only: [get_visibility: 1]
|
import Pleroma.Web.ActivityPub.Visibility, only: [get_visibility: 1, visible_for_user?: 2]
|
||||||
|
|
||||||
# TODO: Add cached version.
|
# TODO: Add cached version.
|
||||||
defp get_replied_to_activities([]), do: %{}
|
defp get_replied_to_activities([]), do: %{}
|
||||||
|
@ -333,6 +333,7 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity}
|
||||||
reblog: nil,
|
reblog: nil,
|
||||||
card: card,
|
card: card,
|
||||||
content: content_html,
|
content: content_html,
|
||||||
|
text: opts[:with_source] && object.data["source"],
|
||||||
created_at: created_at,
|
created_at: created_at,
|
||||||
reblogs_count: announcement_count,
|
reblogs_count: announcement_count,
|
||||||
replies_count: object.data["repliesCount"] || 0,
|
replies_count: object.data["repliesCount"] || 0,
|
||||||
|
@ -364,7 +365,8 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity}
|
||||||
expires_at: expires_at,
|
expires_at: expires_at,
|
||||||
direct_conversation_id: direct_conversation_id,
|
direct_conversation_id: direct_conversation_id,
|
||||||
thread_muted: thread_muted?,
|
thread_muted: thread_muted?,
|
||||||
emoji_reactions: emoji_reactions
|
emoji_reactions: emoji_reactions,
|
||||||
|
parent_visible: visible_for_user?(reply_to, opts[:for])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,14 +3,15 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Web.Preload.Providers.Instance do
|
defmodule Pleroma.Web.Preload.Providers.Instance do
|
||||||
|
alias Pleroma.Plugs.InstanceStatic
|
||||||
alias Pleroma.Web.MastodonAPI.InstanceView
|
alias Pleroma.Web.MastodonAPI.InstanceView
|
||||||
alias Pleroma.Web.Nodeinfo.Nodeinfo
|
alias Pleroma.Web.Nodeinfo.Nodeinfo
|
||||||
alias Pleroma.Web.Preload.Providers.Provider
|
alias Pleroma.Web.Preload.Providers.Provider
|
||||||
|
|
||||||
@behaviour Provider
|
@behaviour Provider
|
||||||
@instance_url :"/api/v1/instance"
|
@instance_url "/api/v1/instance"
|
||||||
@panel_url :"/instance/panel.html"
|
@panel_url "/instance/panel.html"
|
||||||
@nodeinfo_url :"/nodeinfo/2.0"
|
@nodeinfo_url "/nodeinfo/2.0.json"
|
||||||
|
|
||||||
@impl Provider
|
@impl Provider
|
||||||
def generate_terms(_params) do
|
def generate_terms(_params) do
|
||||||
|
@ -27,7 +28,7 @@ defp build_info_tag(acc) do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp build_panel_tag(acc) do
|
defp build_panel_tag(acc) do
|
||||||
instance_path = Path.join(:code.priv_dir(:pleroma), "static/instance/panel.html")
|
instance_path = InstanceStatic.file_path(@panel_url |> to_string())
|
||||||
|
|
||||||
if File.exists?(instance_path) do
|
if File.exists?(instance_path) do
|
||||||
panel_data = File.read!(instance_path)
|
panel_data = File.read!(instance_path)
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
|
|
||||||
defmodule Pleroma.Web.Preload.Providers.StatusNet do
|
defmodule Pleroma.Web.Preload.Providers.StatusNet do
|
||||||
alias Pleroma.Web.Preload.Providers.Provider
|
alias Pleroma.Web.Preload.Providers.Provider
|
||||||
alias Pleroma.Web.TwitterAPI.UtilView
|
alias Pleroma.Web.TwitterAPI.UtilController
|
||||||
|
|
||||||
@behaviour Provider
|
@behaviour Provider
|
||||||
@config_url :"/api/statusnet/config.json"
|
@config_url "/api/statusnet/config.json"
|
||||||
|
|
||||||
@impl Provider
|
@impl Provider
|
||||||
def generate_terms(_params) do
|
def generate_terms(_params) do
|
||||||
|
@ -16,9 +16,10 @@ def generate_terms(_params) do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp build_config_tag(acc) do
|
defp build_config_tag(acc) do
|
||||||
instance = Pleroma.Config.get(:instance)
|
resp =
|
||||||
info_data = UtilView.status_net_config(instance)
|
Plug.Test.conn(:get, @config_url |> to_string())
|
||||||
|
|> UtilController.config(nil)
|
||||||
|
|
||||||
Map.put(acc, @config_url, info_data)
|
Map.put(acc, @config_url, resp.resp_body)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ defmodule Pleroma.Web.Preload.Providers.Timelines do
|
||||||
alias Pleroma.Web.Preload.Providers.Provider
|
alias Pleroma.Web.Preload.Providers.Provider
|
||||||
|
|
||||||
@behaviour Provider
|
@behaviour Provider
|
||||||
@public_url :"/api/v1/timelines/public"
|
@public_url "/api/v1/timelines/public"
|
||||||
|
|
||||||
@impl Provider
|
@impl Provider
|
||||||
def generate_terms(params) do
|
def generate_terms(params) do
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Web.Preload.Providers.User do
|
defmodule Pleroma.Web.Preload.Providers.User do
|
||||||
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.MastodonAPI.AccountView
|
alias Pleroma.Web.MastodonAPI.AccountView
|
||||||
alias Pleroma.Web.Preload.Providers.Provider
|
alias Pleroma.Web.Preload.Providers.Provider
|
||||||
|
|
||||||
@behaviour Provider
|
@behaviour Provider
|
||||||
@account_url :"/api/v1/accounts"
|
@account_url_base "/api/v1/accounts"
|
||||||
|
|
||||||
@impl Provider
|
@impl Provider
|
||||||
def generate_terms(%{user: user}) do
|
def generate_terms(%{user: user}) do
|
||||||
|
@ -16,10 +17,10 @@ def generate_terms(%{user: user}) do
|
||||||
|
|
||||||
def generate_terms(_params), do: %{}
|
def generate_terms(_params), do: %{}
|
||||||
|
|
||||||
def build_accounts_tag(acc, nil), do: acc
|
def build_accounts_tag(acc, %User{} = user) do
|
||||||
|
|
||||||
def build_accounts_tag(acc, user) do
|
|
||||||
account_data = AccountView.render("show.json", %{user: user, for: user})
|
account_data = AccountView.render("show.json", %{user: user, for: user})
|
||||||
Map.put(acc, @account_url, account_data)
|
Map.put(acc, "#{@account_url_base}/#{user.id}", account_data)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def build_accounts_tag(acc, _), do: acc
|
||||||
end
|
end
|
||||||
|
|
|
@ -104,7 +104,9 @@ def stream(topics, items) do
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
def filtered_by_user?(%User{} = user, %Activity{} = item) do
|
def filtered_by_user?(user, item, streamed_type \\ :activity)
|
||||||
|
|
||||||
|
def filtered_by_user?(%User{} = user, %Activity{} = item, streamed_type) do
|
||||||
%{block: blocked_ap_ids, mute: muted_ap_ids, reblog_mute: reblog_muted_ap_ids} =
|
%{block: blocked_ap_ids, mute: muted_ap_ids, reblog_mute: reblog_muted_ap_ids} =
|
||||||
User.outgoing_relationships_ap_ids(user, [:block, :mute, :reblog_mute])
|
User.outgoing_relationships_ap_ids(user, [:block, :mute, :reblog_mute])
|
||||||
|
|
||||||
|
@ -116,6 +118,9 @@ def filtered_by_user?(%User{} = user, %Activity{} = item) do
|
||||||
true <-
|
true <-
|
||||||
Enum.all?([blocked_ap_ids, muted_ap_ids], &(item.actor not in &1)),
|
Enum.all?([blocked_ap_ids, muted_ap_ids], &(item.actor not in &1)),
|
||||||
true <- item.data["type"] != "Announce" || item.actor not in reblog_muted_ap_ids,
|
true <- item.data["type"] != "Announce" || item.actor not in reblog_muted_ap_ids,
|
||||||
|
true <-
|
||||||
|
!(streamed_type == :activity && item.data["type"] == "Announce" &&
|
||||||
|
parent.data["actor"] == user.ap_id),
|
||||||
true <- Enum.all?([blocked_ap_ids, muted_ap_ids], &(parent.data["actor"] not in &1)),
|
true <- Enum.all?([blocked_ap_ids, muted_ap_ids], &(parent.data["actor"] not in &1)),
|
||||||
true <- MapSet.disjoint?(recipients, recipient_blocks),
|
true <- MapSet.disjoint?(recipients, recipient_blocks),
|
||||||
%{host: item_host} <- URI.parse(item.actor),
|
%{host: item_host} <- URI.parse(item.actor),
|
||||||
|
@ -130,8 +135,8 @@ def filtered_by_user?(%User{} = user, %Activity{} = item) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def filtered_by_user?(%User{} = user, %Notification{activity: activity}) do
|
def filtered_by_user?(%User{} = user, %Notification{activity: activity}, _) do
|
||||||
filtered_by_user?(user, activity)
|
filtered_by_user?(user, activity, :notification)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_stream("direct", item) do
|
defp do_stream("direct", item) do
|
||||||
|
|
|
@ -86,7 +86,7 @@ def initial_state(token, user, custom_emojis) do
|
||||||
"video\/mp4"
|
"video\/mp4"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
settings: user.settings || @default_settings,
|
settings: user.mastofe_settings || @default_settings,
|
||||||
push_subscription: nil,
|
push_subscription: nil,
|
||||||
accounts: %{user.id => render(AccountView, "show.json", user: user, for: user)},
|
accounts: %{user.id => render(AccountView, "show.json", user: user, for: user)},
|
||||||
custom_emojis: render(CustomEmojiView, "index.json", custom_emojis: custom_emojis),
|
custom_emojis: render(CustomEmojiView, "index.json", custom_emojis: custom_emojis),
|
||||||
|
|
5
mix.exs
5
mix.exs
|
@ -159,7 +159,10 @@ defp deps do
|
||||||
{:cors_plug, "~> 1.5"},
|
{:cors_plug, "~> 1.5"},
|
||||||
{:ex_doc, "~> 0.21", only: :dev, runtime: false},
|
{:ex_doc, "~> 0.21", only: :dev, runtime: false},
|
||||||
{:web_push_encryption, "~> 0.2.1"},
|
{:web_push_encryption, "~> 0.2.1"},
|
||||||
{:swoosh, "~> 0.23.2"},
|
{:swoosh,
|
||||||
|
git: "https://github.com/swoosh/swoosh",
|
||||||
|
ref: "c96e0ca8a00d8f211ec1f042a4626b09f249caa5",
|
||||||
|
override: true},
|
||||||
{:phoenix_swoosh, "~> 0.2"},
|
{:phoenix_swoosh, "~> 0.2"},
|
||||||
{:gen_smtp, "~> 0.13"},
|
{:gen_smtp, "~> 0.13"},
|
||||||
{:websocket_client, git: "https://github.com/jeremyong/websocket_client.git", only: :test},
|
{:websocket_client, git: "https://github.com/jeremyong/websocket_client.git", only: :test},
|
||||||
|
|
4
mix.lock
4
mix.lock
|
@ -104,9 +104,9 @@
|
||||||
"sleeplocks": {:hex, :sleeplocks, "1.1.1", "3d462a0639a6ef36cc75d6038b7393ae537ab394641beb59830a1b8271faeed3", [:rebar3], [], "hexpm", "84ee37aeff4d0d92b290fff986d6a95ac5eedf9b383fadfd1d88e9b84a1c02e1"},
|
"sleeplocks": {:hex, :sleeplocks, "1.1.1", "3d462a0639a6ef36cc75d6038b7393ae537ab394641beb59830a1b8271faeed3", [:rebar3], [], "hexpm", "84ee37aeff4d0d92b290fff986d6a95ac5eedf9b383fadfd1d88e9b84a1c02e1"},
|
||||||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
|
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
|
||||||
"sweet_xml": {:hex, :sweet_xml, "0.6.6", "fc3e91ec5dd7c787b6195757fbcf0abc670cee1e4172687b45183032221b66b8", [:mix], [], "hexpm", "2e1ec458f892ffa81f9f8386e3f35a1af6db7a7a37748a64478f13163a1f3573"},
|
"sweet_xml": {:hex, :sweet_xml, "0.6.6", "fc3e91ec5dd7c787b6195757fbcf0abc670cee1e4172687b45183032221b66b8", [:mix], [], "hexpm", "2e1ec458f892ffa81f9f8386e3f35a1af6db7a7a37748a64478f13163a1f3573"},
|
||||||
"swoosh": {:hex, :swoosh, "0.23.5", "bfd9404bbf5069b1be2ffd317923ce57e58b332e25dbca2a35dedd7820dfee5a", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "e3928e1d2889a308aaf3e42755809ac21cffd77cb58eef01cbfdab4ce2fd1e21"},
|
"swoosh": {:git, "https://github.com/swoosh/swoosh", "c96e0ca8a00d8f211ec1f042a4626b09f249caa5", [ref: "c96e0ca8a00d8f211ec1f042a4626b09f249caa5"]},
|
||||||
"syslog": {:hex, :syslog, "1.1.0", "6419a232bea84f07b56dc575225007ffe34d9fdc91abe6f1b2f254fd71d8efc2", [:rebar3], [], "hexpm", "4c6a41373c7e20587be33ef841d3de6f3beba08519809329ecc4d27b15b659e1"},
|
"syslog": {:hex, :syslog, "1.1.0", "6419a232bea84f07b56dc575225007ffe34d9fdc91abe6f1b2f254fd71d8efc2", [:rebar3], [], "hexpm", "4c6a41373c7e20587be33ef841d3de6f3beba08519809329ecc4d27b15b659e1"},
|
||||||
"telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm", "4738382e36a0a9a2b6e25d67c960e40e1a2c95560b9f936d8e29de8cd858480f"},
|
"telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
|
||||||
"tesla": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/tesla.git", "61b7503cef33f00834f78ddfafe0d5d9dec2270b", [ref: "61b7503cef33f00834f78ddfafe0d5d9dec2270b"]},
|
"tesla": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/tesla.git", "61b7503cef33f00834f78ddfafe0d5d9dec2270b", [ref: "61b7503cef33f00834f78ddfafe0d5d9dec2270b"]},
|
||||||
"timex": {:hex, :timex, "3.6.1", "efdf56d0e67a6b956cc57774353b0329c8ab7726766a11547e529357ffdc1d56", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "f354efb2400dd7a80fd9eb6c8419068c4f632da4ac47f3d8822d6e33f08bc852"},
|
"timex": {:hex, :timex, "3.6.1", "efdf56d0e67a6b956cc57774353b0329c8ab7726766a11547e529357ffdc1d56", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "f354efb2400dd7a80fd9eb6c8419068c4f632da4ac47f3d8822d6e33f08bc852"},
|
||||||
"trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bd4fde4c15f3e993a999e019d64347489b91b7a9096af68b2bdadd192afa693f"},
|
"trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bd4fde4c15f3e993a999e019d64347489b91b7a9096af68b2bdadd192afa693f"},
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.RenameUserSettingsCol do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
rename(table(:users), :settings, to: :mastofe_settings)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
rename(table(:users), :mastofe_settings, to: :settings)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,10 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.RemoveTeslaFromConfig do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
execute("DELETE FROM config WHERE config.group = ':tesla'")
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
end
|
||||||
|
end
|
Binary file not shown.
BIN
priv/static/adminfe/chunk-43ca.af749c6c.css
Normal file
BIN
priv/static/adminfe/chunk-43ca.af749c6c.css
Normal file
Binary file not shown.
Binary file not shown.
BIN
priv/static/adminfe/chunk-c5f4.b1112f18.css
Normal file
BIN
priv/static/adminfe/chunk-c5f4.b1112f18.css
Normal file
Binary file not shown.
|
@ -1 +1 @@
|
||||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=renderer content=webkit><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><title>Admin FE</title><link rel="shortcut icon" href=favicon.ico><link href=chunk-elementUI.1abbc9b8.css rel=stylesheet><link href=chunk-libs.686b5876.css rel=stylesheet><link href=app.6684eb28.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=static/js/runtime.5bae86dc.js></script><script type=text/javascript src=static/js/chunk-elementUI.fba0efec.js></script><script type=text/javascript src=static/js/chunk-libs.b8c453ab.js></script><script type=text/javascript src=static/js/app.3fcec8f6.js></script></body></html>
|
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=renderer content=webkit><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><title>Admin FE</title><link rel="shortcut icon" href=favicon.ico><link href=chunk-elementUI.1abbc9b8.css rel=stylesheet><link href=chunk-libs.686b5876.css rel=stylesheet><link href=app.01bdb34a.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=static/js/runtime.0a70a9f5.js></script><script type=text/javascript src=static/js/chunk-elementUI.fba0efec.js></script><script type=text/javascript src=static/js/chunk-libs.b8c453ab.js></script><script type=text/javascript src=static/js/app.f220ac13.js></script></body></html>
|
Binary file not shown.
Binary file not shown.
BIN
priv/static/adminfe/static/js/app.f220ac13.js
Normal file
BIN
priv/static/adminfe/static/js/app.f220ac13.js
Normal file
Binary file not shown.
BIN
priv/static/adminfe/static/js/app.f220ac13.js.map
Normal file
BIN
priv/static/adminfe/static/js/app.f220ac13.js.map
Normal file
Binary file not shown.
Binary file not shown.
BIN
priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js.map
Normal file
BIN
priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js.map
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
priv/static/adminfe/static/js/chunk-43ca.aceb457c.js
Normal file
BIN
priv/static/adminfe/static/js/chunk-43ca.aceb457c.js
Normal file
Binary file not shown.
BIN
priv/static/adminfe/static/js/chunk-43ca.aceb457c.js.map
Normal file
BIN
priv/static/adminfe/static/js/chunk-43ca.aceb457c.js.map
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js
Normal file
BIN
priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js
Normal file
Binary file not shown.
BIN
priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js.map
Normal file
BIN
priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js.map
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -10,7 +10,6 @@ defmodule Pleroma.Config.HolderTest do
|
||||||
test "default_config/0" do
|
test "default_config/0" do
|
||||||
config = Holder.default_config()
|
config = Holder.default_config()
|
||||||
assert config[:pleroma][Pleroma.Uploaders.Local][:uploads] == "test/uploads"
|
assert config[:pleroma][Pleroma.Uploaders.Local][:uploads] == "test/uploads"
|
||||||
assert config[:tesla][:adapter] == Tesla.Mock
|
|
||||||
|
|
||||||
refute config[:pleroma][Pleroma.Repo]
|
refute config[:pleroma][Pleroma.Repo]
|
||||||
refute config[:pleroma][Pleroma.Web.Endpoint]
|
refute config[:pleroma][Pleroma.Web.Endpoint]
|
||||||
|
@ -18,17 +17,15 @@ test "default_config/0" do
|
||||||
refute config[:pleroma][:configurable_from_database]
|
refute config[:pleroma][:configurable_from_database]
|
||||||
refute config[:pleroma][:database]
|
refute config[:pleroma][:database]
|
||||||
refute config[:phoenix][:serve_endpoints]
|
refute config[:phoenix][:serve_endpoints]
|
||||||
|
refute config[:tesla][:adapter]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "default_config/1" do
|
test "default_config/1" do
|
||||||
pleroma_config = Holder.default_config(:pleroma)
|
pleroma_config = Holder.default_config(:pleroma)
|
||||||
assert pleroma_config[Pleroma.Uploaders.Local][:uploads] == "test/uploads"
|
assert pleroma_config[Pleroma.Uploaders.Local][:uploads] == "test/uploads"
|
||||||
tesla_config = Holder.default_config(:tesla)
|
|
||||||
assert tesla_config[:adapter] == Tesla.Mock
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "default_config/2" do
|
test "default_config/2" do
|
||||||
assert Holder.default_config(:pleroma, Pleroma.Uploaders.Local) == [uploads: "test/uploads"]
|
assert Holder.default_config(:pleroma, Pleroma.Uploaders.Local) == [uploads: "test/uploads"]
|
||||||
assert Holder.default_config(:tesla, :adapter) == Tesla.Mock
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
72
test/fixtures/fetch_mocks/104410921027210069.json
vendored
Normal file
72
test/fixtures/fetch_mocks/104410921027210069.json
vendored
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
{
|
||||||
|
"@context" : [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
{
|
||||||
|
"atomUri" : "ostatus:atomUri",
|
||||||
|
"conversation" : "ostatus:conversation",
|
||||||
|
"inReplyToAtomUri" : "ostatus:inReplyToAtomUri",
|
||||||
|
"ostatus" : "http://ostatus.org#",
|
||||||
|
"sensitive" : "as:sensitive",
|
||||||
|
"toot" : "http://joinmastodon.org/ns#",
|
||||||
|
"votersCount" : "toot:votersCount"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"atomUri" : "https://busshi.moe/users/tuxcrafting/statuses/104410921027210069",
|
||||||
|
"attachment" : [],
|
||||||
|
"attributedTo" : "https://busshi.moe/users/tuxcrafting",
|
||||||
|
"cc" : [
|
||||||
|
"https://busshi.moe/users/tuxcrafting/followers",
|
||||||
|
"https://stereophonic.space/users/fixpoint",
|
||||||
|
"https://blob.cat/users/blobyoumu",
|
||||||
|
"https://cawfee.club/users/grips",
|
||||||
|
"https://jaeger.website/users/igel"
|
||||||
|
],
|
||||||
|
"content" : "<p><span class=\"h-card\"><a href=\"https://stereophonic.space/users/fixpoint\" class=\"u-url mention\">@<span>fixpoint</span></a></span> <span class=\"h-card\"><a href=\"https://blob.cat/users/blobyoumu\" class=\"u-url mention\">@<span>blobyoumu</span></a></span> <span class=\"h-card\"><a href=\"https://cawfee.club/users/grips\" class=\"u-url mention\">@<span>grips</span></a></span> <span class=\"h-card\"><a href=\"https://jaeger.website/users/igel\" class=\"u-url mention\">@<span>igel</span></a></span> there's a difference between not liking nukes and not liking nuclear power<br />nukes are pretty bad as are all WMDs in general but disliking nuclear power just indicates you are unable of thought</p>",
|
||||||
|
"contentMap" : {
|
||||||
|
"en" : "<p><span class=\"h-card\"><a href=\"https://stereophonic.space/users/fixpoint\" class=\"u-url mention\">@<span>fixpoint</span></a></span> <span class=\"h-card\"><a href=\"https://blob.cat/users/blobyoumu\" class=\"u-url mention\">@<span>blobyoumu</span></a></span> <span class=\"h-card\"><a href=\"https://cawfee.club/users/grips\" class=\"u-url mention\">@<span>grips</span></a></span> <span class=\"h-card\"><a href=\"https://jaeger.website/users/igel\" class=\"u-url mention\">@<span>igel</span></a></span> there's a difference between not liking nukes and not liking nuclear power<br />nukes are pretty bad as are all WMDs in general but disliking nuclear power just indicates you are unable of thought</p>"
|
||||||
|
},
|
||||||
|
"conversation" : "https://cawfee.club/contexts/ad6c73d8-efc2-4e74-84ea-2dacf1a27a5e",
|
||||||
|
"id" : "https://busshi.moe/users/tuxcrafting/statuses/104410921027210069",
|
||||||
|
"inReplyTo" : "https://stereophonic.space/objects/02997b83-3ea7-4b63-94af-ef3aa2d4ed17",
|
||||||
|
"inReplyToAtomUri" : "https://stereophonic.space/objects/02997b83-3ea7-4b63-94af-ef3aa2d4ed17",
|
||||||
|
"published" : "2020-06-26T15:10:19Z",
|
||||||
|
"replies" : {
|
||||||
|
"first" : {
|
||||||
|
"items" : [],
|
||||||
|
"next" : "https://busshi.moe/users/tuxcrafting/statuses/104410921027210069/replies?only_other_accounts=true&page=true",
|
||||||
|
"partOf" : "https://busshi.moe/users/tuxcrafting/statuses/104410921027210069/replies",
|
||||||
|
"type" : "CollectionPage"
|
||||||
|
},
|
||||||
|
"id" : "https://busshi.moe/users/tuxcrafting/statuses/104410921027210069/replies",
|
||||||
|
"type" : "Collection"
|
||||||
|
},
|
||||||
|
"sensitive" : false,
|
||||||
|
"summary" : null,
|
||||||
|
"tag" : [
|
||||||
|
{
|
||||||
|
"href" : "https://stereophonic.space/users/fixpoint",
|
||||||
|
"name" : "@fixpoint@stereophonic.space",
|
||||||
|
"type" : "Mention"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href" : "https://blob.cat/users/blobyoumu",
|
||||||
|
"name" : "@blobyoumu@blob.cat",
|
||||||
|
"type" : "Mention"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href" : "https://cawfee.club/users/grips",
|
||||||
|
"name" : "@grips@cawfee.club",
|
||||||
|
"type" : "Mention"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href" : "https://jaeger.website/users/igel",
|
||||||
|
"name" : "@igel@jaeger.website",
|
||||||
|
"type" : "Mention"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"to" : [
|
||||||
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
],
|
||||||
|
"type" : "Note",
|
||||||
|
"url" : "https://busshi.moe/@tuxcrafting/104410921027210069"
|
||||||
|
}
|
59
test/fixtures/fetch_mocks/9wTkLEnuq47B25EehM.json
vendored
Normal file
59
test/fixtures/fetch_mocks/9wTkLEnuq47B25EehM.json
vendored
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
{
|
||||||
|
"@context" : [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://social.sakamoto.gq/schemas/litepub-0.1.jsonld",
|
||||||
|
{
|
||||||
|
"@language" : "und"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"actor" : "https://social.sakamoto.gq/users/eal",
|
||||||
|
"attachment" : [],
|
||||||
|
"attributedTo" : "https://social.sakamoto.gq/users/eal",
|
||||||
|
"cc" : [
|
||||||
|
"https://social.sakamoto.gq/users/eal/followers"
|
||||||
|
],
|
||||||
|
"content" : "<span class=\"h-card\"><a data-user=\"9uw2wH0iTYAMV7XnLU\" class=\"u-url mention\" href=\"https://busshi.moe/@tuxcrafting\" rel=\"ugc\">@<span>tuxcrafting</span></a></span> <span class=\"h-card\"><a data-user=\"9r5l8j8x23NI9KUFu4\" class=\"u-url mention\" href=\"https://stereophonic.space/users/fixpoint\" rel=\"ugc\">@<span>fixpoint</span></a></span> <span class=\"h-card\"><a data-user=\"9orDK545JwjY4Lxjge\" class=\"u-url mention\" href=\"https://blob.cat/users/blobyoumu\" rel=\"ugc\">@<span>blobyoumu</span></a></span> <span class=\"h-card\"><a data-user=\"68184\" class=\"u-url mention\" href=\"https://cawfee.club/users/grips\" rel=\"ugc\">@<span>grips</span></a></span> <span class=\"h-card\"><a data-user=\"9sAmMgHVKjTXKpgx84\" class=\"u-url mention\" href=\"https://jaeger.website/users/igel\" rel=\"ugc\">@<span>igel</span></a></span> What's bad about nukes?",
|
||||||
|
"context" : "https://cawfee.club/contexts/ad6c73d8-efc2-4e74-84ea-2dacf1a27a5e",
|
||||||
|
"conversation" : "https://cawfee.club/contexts/ad6c73d8-efc2-4e74-84ea-2dacf1a27a5e",
|
||||||
|
"id" : "https://social.sakamoto.gq/objects/f20f2497-66d9-4a52-a2e1-1be2a39c32c1",
|
||||||
|
"inReplyTo" : "https://busshi.moe/users/tuxcrafting/statuses/104410921027210069",
|
||||||
|
"published" : "2020-06-26T15:20:15.975737Z",
|
||||||
|
"sensitive" : false,
|
||||||
|
"summary" : "",
|
||||||
|
"tag" : [
|
||||||
|
{
|
||||||
|
"href" : "https://blob.cat/users/blobyoumu",
|
||||||
|
"name" : "@blobyoumu@blob.cat",
|
||||||
|
"type" : "Mention"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href" : "https://busshi.moe/users/tuxcrafting",
|
||||||
|
"name" : "@tuxcrafting@busshi.moe",
|
||||||
|
"type" : "Mention"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href" : "https://cawfee.club/users/grips",
|
||||||
|
"name" : "@grips@cawfee.club",
|
||||||
|
"type" : "Mention"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href" : "https://jaeger.website/users/igel",
|
||||||
|
"name" : "@igel@jaeger.website",
|
||||||
|
"type" : "Mention"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href" : "https://stereophonic.space/users/fixpoint",
|
||||||
|
"name" : "@fixpoint@stereophonic.space",
|
||||||
|
"type" : "Mention"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"to" : [
|
||||||
|
"https://busshi.moe/users/tuxcrafting",
|
||||||
|
"https://www.w3.org/ns/activitystreams#Public",
|
||||||
|
"https://blob.cat/users/blobyoumu",
|
||||||
|
"https://stereophonic.space/users/fixpoint",
|
||||||
|
"https://cawfee.club/users/grips",
|
||||||
|
"https://jaeger.website/users/igel"
|
||||||
|
],
|
||||||
|
"type" : "Note"
|
||||||
|
}
|
43
test/fixtures/fetch_mocks/eal.json
vendored
Normal file
43
test/fixtures/fetch_mocks/eal.json
vendored
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
{
|
||||||
|
"@context" : [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://social.sakamoto.gq/schemas/litepub-0.1.jsonld",
|
||||||
|
{
|
||||||
|
"@language" : "und"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attachment" : [],
|
||||||
|
"discoverable" : true,
|
||||||
|
"endpoints" : {
|
||||||
|
"oauthAuthorizationEndpoint" : "https://social.sakamoto.gq/oauth/authorize",
|
||||||
|
"oauthRegistrationEndpoint" : "https://social.sakamoto.gq/api/v1/apps",
|
||||||
|
"oauthTokenEndpoint" : "https://social.sakamoto.gq/oauth/token",
|
||||||
|
"sharedInbox" : "https://social.sakamoto.gq/inbox",
|
||||||
|
"uploadMedia" : "https://social.sakamoto.gq/api/ap/upload_media"
|
||||||
|
},
|
||||||
|
"followers" : "https://social.sakamoto.gq/users/eal/followers",
|
||||||
|
"following" : "https://social.sakamoto.gq/users/eal/following",
|
||||||
|
"icon" : {
|
||||||
|
"type" : "Image",
|
||||||
|
"url" : "https://social.sakamoto.gq/media/f1cb6f79bf6839f3223ca240441f766056b74ddd23c69bcaf8bb1ba1ecff6eec.jpg"
|
||||||
|
},
|
||||||
|
"id" : "https://social.sakamoto.gq/users/eal",
|
||||||
|
"image" : {
|
||||||
|
"type" : "Image",
|
||||||
|
"url" : "https://social.sakamoto.gq/media/e5cccf26421e8366f4e34be3c9d5042b8bc8dcceccc7c8e89785fa312dd9632c.jpg"
|
||||||
|
},
|
||||||
|
"inbox" : "https://social.sakamoto.gq/users/eal/inbox",
|
||||||
|
"manuallyApprovesFollowers" : false,
|
||||||
|
"name" : "ìì",
|
||||||
|
"outbox" : "https://social.sakamoto.gq/users/eal/outbox",
|
||||||
|
"preferredUsername" : "eal",
|
||||||
|
"publicKey" : {
|
||||||
|
"id" : "https://social.sakamoto.gq/users/eal#main-key",
|
||||||
|
"owner" : "https://social.sakamoto.gq/users/eal",
|
||||||
|
"publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz3pF85YOhhv2Zaxv9YQ7\nrCe1aEhetCMVHtrK63tUVGoGdsblyKnVeJNbFcr6k3y35OpHS3HXIi6GzgihYcTu\nONLP4eQMHTnLUNAQZi03mjJA4iIq8v/tm8ZkL2mXsQSAbWj6Iq518mHNN7OvCoNt\n3Xjepl/0kgkc2gsund7m8r+Wu0Fusx6UlUyyAk3PexdDRdSSlVLeskqtP8jtdQDo\nL70pMyL+VD+Qb9RKFdtgJ+M4OqYP+7FVzCqXN0QIPhFf/kvHSLr+c4Y3Wm0nAKHU\n9CwXWXz5Xqscpv41KlgnUCOkTXb5eBSt23lNulae5srVzWBiFb6guiCpNzBGa+Sq\nrwIDAQAB\n-----END PUBLIC KEY-----\n\n"
|
||||||
|
},
|
||||||
|
"summary" : "Pizza napoletana supremacist.<br><br>Any artworks posted here that are good are not mine.",
|
||||||
|
"tag" : [],
|
||||||
|
"type" : "Person",
|
||||||
|
"url" : "https://social.sakamoto.gq/users/eal"
|
||||||
|
}
|
59
test/fixtures/fetch_mocks/tuxcrafting.json
vendored
Normal file
59
test/fixtures/fetch_mocks/tuxcrafting.json
vendored
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
{
|
||||||
|
"@context" : [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1",
|
||||||
|
{
|
||||||
|
"IdentityProof" : "toot:IdentityProof",
|
||||||
|
"PropertyValue" : "schema:PropertyValue",
|
||||||
|
"alsoKnownAs" : {
|
||||||
|
"@id" : "as:alsoKnownAs",
|
||||||
|
"@type" : "@id"
|
||||||
|
},
|
||||||
|
"discoverable" : "toot:discoverable",
|
||||||
|
"featured" : {
|
||||||
|
"@id" : "toot:featured",
|
||||||
|
"@type" : "@id"
|
||||||
|
},
|
||||||
|
"focalPoint" : {
|
||||||
|
"@container" : "@list",
|
||||||
|
"@id" : "toot:focalPoint"
|
||||||
|
},
|
||||||
|
"manuallyApprovesFollowers" : "as:manuallyApprovesFollowers",
|
||||||
|
"movedTo" : {
|
||||||
|
"@id" : "as:movedTo",
|
||||||
|
"@type" : "@id"
|
||||||
|
},
|
||||||
|
"schema" : "http://schema.org#",
|
||||||
|
"toot" : "http://joinmastodon.org/ns#",
|
||||||
|
"value" : "schema:value"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attachment" : [],
|
||||||
|
"discoverable" : true,
|
||||||
|
"endpoints" : {
|
||||||
|
"sharedInbox" : "https://busshi.moe/inbox"
|
||||||
|
},
|
||||||
|
"featured" : "https://busshi.moe/users/tuxcrafting/collections/featured",
|
||||||
|
"followers" : "https://busshi.moe/users/tuxcrafting/followers",
|
||||||
|
"following" : "https://busshi.moe/users/tuxcrafting/following",
|
||||||
|
"icon" : {
|
||||||
|
"mediaType" : "image/jpeg",
|
||||||
|
"type" : "Image",
|
||||||
|
"url" : "https://blobcdn.busshi.moe/busshifiles/accounts/avatars/000/046/872/original/054f0806ccb303d0.jpg"
|
||||||
|
},
|
||||||
|
"id" : "https://busshi.moe/users/tuxcrafting",
|
||||||
|
"inbox" : "https://busshi.moe/users/tuxcrafting/inbox",
|
||||||
|
"manuallyApprovesFollowers" : true,
|
||||||
|
"name" : "@tuxcrafting@localhost:8080",
|
||||||
|
"outbox" : "https://busshi.moe/users/tuxcrafting/outbox",
|
||||||
|
"preferredUsername" : "tuxcrafting",
|
||||||
|
"publicKey" : {
|
||||||
|
"id" : "https://busshi.moe/users/tuxcrafting#main-key",
|
||||||
|
"owner" : "https://busshi.moe/users/tuxcrafting",
|
||||||
|
"publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwqWWTBf9OizsBiBhGS/M\nQTT6fB1VvQP6vvxouGZ5cGg1a97V67ouhjJ+nGMuWr++DNYjJYkk2TOynfykk0H/\n8rRSujSe3BNRKYGNzdnRJu/4XxgIE847Fqx5SijSP23JGYcn8TjeSUsN2u2YYVXK\n+Eb3Bu7DjGiqwNon6YB0h5qkGjkMSMVIFn0hZx6Z21bkfYWgra96Ok5OWf7Ck3je\nCuErlCMZcbQcHtFpBueJAxYchjNvm6fqwZxLX/NtaHdr7Fm2kin89mqzliapBlFH\nCXk7Jln6xV5I6ryggPAMzm3fuHzeo0RWlu8lrxLfARBVwaQQZS99bwqp6N9O2aUp\nYwIDAQAB\n-----END PUBLIC KEY-----\n"
|
||||||
|
},
|
||||||
|
"summary" : "<p>expert procrastinator</p><p>trans(humanist|gender|istorized)</p><p>web: <a href=\"https://tuxcrafting.port0.org\" rel=\"nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"\">tuxcrafting.port0.org</span><span class=\"invisible\"></span></a><br />pronouns: she/they<br />languages: french (native)/english (fluent)/hebrew (ok-ish)/esperanto (barely)</p>",
|
||||||
|
"tag" : [],
|
||||||
|
"type" : "Person",
|
||||||
|
"url" : "https://busshi.moe/@tuxcrafting"
|
||||||
|
}
|
1
test/fixtures/preload_static/instance/panel.html
vendored
Normal file
1
test/fixtures/preload_static/instance/panel.html
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
HEY!
|
File diff suppressed because one or more lines are too long
188
test/fixtures/tesla_mock/peertube.moe-vid.json
vendored
188
test/fixtures/tesla_mock/peertube.moe-vid.json
vendored
File diff suppressed because one or more lines are too long
|
@ -237,5 +237,19 @@ test "does not crash when there is an HTML entity in a link" do
|
||||||
|
|
||||||
assert {:ok, nil} = HTML.extract_first_external_url(object, object.data["content"])
|
assert {:ok, nil} = HTML.extract_first_external_url(object, object.data["content"])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "skips attachment links" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, activity} =
|
||||||
|
CommonAPI.post(user, %{
|
||||||
|
status:
|
||||||
|
"<a href=\"https://pleroma.gov/media/d24caa3a498e21e0298377a9ca0149a4f4f8b767178aacf837542282e2d94fb1.png?name=image.png\" class=\"attachment\">image.png</a>"
|
||||||
|
})
|
||||||
|
|
||||||
|
object = Object.normalize(activity)
|
||||||
|
|
||||||
|
assert {:ok, nil} = HTML.extract_first_external_url(object, object.data["content"])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,6 +22,16 @@ defmodule Pleroma.NotificationTest do
|
||||||
alias Pleroma.Web.Streamer
|
alias Pleroma.Web.Streamer
|
||||||
|
|
||||||
describe "create_notifications" do
|
describe "create_notifications" do
|
||||||
|
test "never returns nil" do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user, %{invisible: true})
|
||||||
|
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{status: "yeah"})
|
||||||
|
{:ok, activity} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
|
||||||
|
|
||||||
|
refute {:ok, [nil]} == Notification.create_notifications(activity)
|
||||||
|
end
|
||||||
|
|
||||||
test "creates a notification for an emoji reaction" do
|
test "creates a notification for an emoji reaction" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
|
|
|
@ -26,6 +26,46 @@ defmodule Pleroma.Object.FetcherTest do
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "error cases" do
|
||||||
|
setup do
|
||||||
|
mock(fn
|
||||||
|
%{method: :get, url: "https://social.sakamoto.gq/notice/9wTkLEnuq47B25EehM"} ->
|
||||||
|
%Tesla.Env{
|
||||||
|
status: 200,
|
||||||
|
body: File.read!("test/fixtures/fetch_mocks/9wTkLEnuq47B25EehM.json")
|
||||||
|
}
|
||||||
|
|
||||||
|
%{method: :get, url: "https://social.sakamoto.gq/users/eal"} ->
|
||||||
|
%Tesla.Env{
|
||||||
|
status: 200,
|
||||||
|
body: File.read!("test/fixtures/fetch_mocks/eal.json")
|
||||||
|
}
|
||||||
|
|
||||||
|
%{method: :get, url: "https://busshi.moe/users/tuxcrafting/statuses/104410921027210069"} ->
|
||||||
|
%Tesla.Env{
|
||||||
|
status: 200,
|
||||||
|
body: File.read!("test/fixtures/fetch_mocks/104410921027210069.json")
|
||||||
|
}
|
||||||
|
|
||||||
|
%{method: :get, url: "https://busshi.moe/users/tuxcrafting"} ->
|
||||||
|
%Tesla.Env{
|
||||||
|
status: 500
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag capture_log: true
|
||||||
|
test "it works when fetching the OP actor errors out" do
|
||||||
|
# Here we simulate a case where the author of the OP can't be read
|
||||||
|
assert {:ok, _} =
|
||||||
|
Fetcher.fetch_object_from_id(
|
||||||
|
"https://social.sakamoto.gq/notice/9wTkLEnuq47B25EehM"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "max thread distance restriction" do
|
describe "max thread distance restriction" do
|
||||||
@ap_id "http://mastodon.example.org/@admin/99541947525187367"
|
@ap_id "http://mastodon.example.org/@admin/99541947525187367"
|
||||||
setup do: clear_config([:instance, :federation_incoming_replies_max_depth])
|
setup do: clear_config([:instance, :federation_incoming_replies_max_depth])
|
||||||
|
|
|
@ -67,6 +67,7 @@ def note_factory(attrs \\ %{}) do
|
||||||
data = %{
|
data = %{
|
||||||
"type" => "Note",
|
"type" => "Note",
|
||||||
"content" => text,
|
"content" => text,
|
||||||
|
"source" => text,
|
||||||
"id" => Pleroma.Web.ActivityPub.Utils.generate_object_id(),
|
"id" => Pleroma.Web.ActivityPub.Utils.generate_object_id(),
|
||||||
"actor" => user.ap_id,
|
"actor" => user.ap_id,
|
||||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||||
|
|
|
@ -17,7 +17,7 @@ defmodule Pleroma.UserSearchTest do
|
||||||
describe "User.search" do
|
describe "User.search" do
|
||||||
setup do: clear_config([:instance, :limit_to_local_content])
|
setup do: clear_config([:instance, :limit_to_local_content])
|
||||||
|
|
||||||
test "excluded invisible users from results" do
|
test "excludes invisible users from results" do
|
||||||
user = insert(:user, %{nickname: "john t1000"})
|
user = insert(:user, %{nickname: "john t1000"})
|
||||||
insert(:user, %{invisible: true, nickname: "john t800"})
|
insert(:user, %{invisible: true, nickname: "john t800"})
|
||||||
|
|
||||||
|
@ -25,6 +25,15 @@ test "excluded invisible users from results" do
|
||||||
assert found_user.id == user.id
|
assert found_user.id == user.id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "excludes service actors from results" do
|
||||||
|
insert(:user, actor_type: "Application", nickname: "user1")
|
||||||
|
service = insert(:user, actor_type: "Service", nickname: "user2")
|
||||||
|
person = insert(:user, actor_type: "Person", nickname: "user3")
|
||||||
|
|
||||||
|
assert [found_user1, found_user2] = User.search("user")
|
||||||
|
assert [found_user1.id, found_user2.id] -- [service.id, person.id] == []
|
||||||
|
end
|
||||||
|
|
||||||
test "accepts limit parameter" do
|
test "accepts limit parameter" do
|
||||||
Enum.each(0..4, &insert(:user, %{nickname: "john#{&1}"}))
|
Enum.each(0..4, &insert(:user, %{nickname: "john#{&1}"}))
|
||||||
assert length(User.search("john", limit: 3)) == 3
|
assert length(User.search("john", limit: 3)) == 3
|
||||||
|
|
|
@ -597,6 +597,31 @@ test "updates an existing user, if stale" do
|
||||||
refute user.last_refreshed_at == orig_user.last_refreshed_at
|
refute user.last_refreshed_at == orig_user.last_refreshed_at
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "if nicknames clash, the old user gets a prefix with the old id to the nickname" do
|
||||||
|
a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
|
||||||
|
|
||||||
|
orig_user =
|
||||||
|
insert(
|
||||||
|
:user,
|
||||||
|
local: false,
|
||||||
|
nickname: "admin@mastodon.example.org",
|
||||||
|
ap_id: "http://mastodon.example.org/users/harinezumigari",
|
||||||
|
last_refreshed_at: a_week_ago
|
||||||
|
)
|
||||||
|
|
||||||
|
assert orig_user.last_refreshed_at == a_week_ago
|
||||||
|
|
||||||
|
{:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
|
||||||
|
|
||||||
|
assert user.inbox
|
||||||
|
|
||||||
|
refute user.id == orig_user.id
|
||||||
|
|
||||||
|
orig_user = User.get_by_id(orig_user.id)
|
||||||
|
|
||||||
|
assert orig_user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
|
||||||
|
end
|
||||||
|
|
||||||
@tag capture_log: true
|
@tag capture_log: true
|
||||||
test "it returns the old user if stale, but unfetchable" do
|
test "it returns the old user if stale, but unfetchable" do
|
||||||
a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
|
a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
|
||||||
|
|
|
@ -992,54 +992,6 @@ test "creates an undo activity for a pending follow request" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "blocking" do
|
|
||||||
test "reverts block activity on error" do
|
|
||||||
[blocker, blocked] = insert_list(2, :user)
|
|
||||||
|
|
||||||
with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
|
|
||||||
assert {:error, :reverted} = ActivityPub.block(blocker, blocked)
|
|
||||||
end
|
|
||||||
|
|
||||||
assert Repo.aggregate(Activity, :count, :id) == 0
|
|
||||||
assert Repo.aggregate(Object, :count, :id) == 0
|
|
||||||
end
|
|
||||||
|
|
||||||
test "creates a block activity" do
|
|
||||||
clear_config([:instance, :federating], true)
|
|
||||||
blocker = insert(:user)
|
|
||||||
blocked = insert(:user)
|
|
||||||
|
|
||||||
with_mock Pleroma.Web.Federator,
|
|
||||||
publish: fn _ -> nil end do
|
|
||||||
{:ok, activity} = ActivityPub.block(blocker, blocked)
|
|
||||||
|
|
||||||
assert activity.data["type"] == "Block"
|
|
||||||
assert activity.data["actor"] == blocker.ap_id
|
|
||||||
assert activity.data["object"] == blocked.ap_id
|
|
||||||
|
|
||||||
assert called(Pleroma.Web.Federator.publish(activity))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "works with outgoing blocks disabled, but doesn't federate" do
|
|
||||||
clear_config([:instance, :federating], true)
|
|
||||||
clear_config([:activitypub, :outgoing_blocks], false)
|
|
||||||
blocker = insert(:user)
|
|
||||||
blocked = insert(:user)
|
|
||||||
|
|
||||||
with_mock Pleroma.Web.Federator,
|
|
||||||
publish: fn _ -> nil end do
|
|
||||||
{:ok, activity} = ActivityPub.block(blocker, blocked)
|
|
||||||
|
|
||||||
assert activity.data["type"] == "Block"
|
|
||||||
assert activity.data["actor"] == blocker.ap_id
|
|
||||||
assert activity.data["object"] == blocked.ap_id
|
|
||||||
|
|
||||||
refute called(Pleroma.Web.Federator.publish(:_))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "timeline post-processing" do
|
describe "timeline post-processing" do
|
||||||
test "it filters broken threads" do
|
test "it filters broken threads" do
|
||||||
user1 = insert(:user)
|
user1 = insert(:user)
|
||||||
|
|
|
@ -33,7 +33,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
|
||||||
|
|
||||||
describe "with new user" do
|
describe "with new user" do
|
||||||
test "it allows posts without links" do
|
test "it allows posts without links" do
|
||||||
user = insert(:user)
|
user = insert(:user, local: false)
|
||||||
|
|
||||||
assert user.note_count == 0
|
assert user.note_count == 0
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ test "it allows posts without links" do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it disallows posts with links" do
|
test "it disallows posts with links" do
|
||||||
user = insert(:user)
|
user = insert(:user, local: false)
|
||||||
|
|
||||||
assert user.note_count == 0
|
assert user.note_count == 0
|
||||||
|
|
||||||
|
@ -55,6 +55,18 @@ test "it disallows posts with links" do
|
||||||
|
|
||||||
{:reject, _} = AntiLinkSpamPolicy.filter(message)
|
{:reject, _} = AntiLinkSpamPolicy.filter(message)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it allows posts with links for local users" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
assert user.note_count == 0
|
||||||
|
|
||||||
|
message =
|
||||||
|
@linkful_message
|
||||||
|
|> Map.put("actor", user.ap_id)
|
||||||
|
|
||||||
|
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "with old user" do
|
describe "with old user" do
|
||||||
|
|
|
@ -654,4 +654,31 @@ test "returns an error if the object can't be updated by the actor", %{
|
||||||
assert {:error, _cng} = ObjectValidator.validate(update, [])
|
assert {:error, _cng} = ObjectValidator.validate(update, [])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "blocks" do
|
||||||
|
setup do
|
||||||
|
user = insert(:user, local: false)
|
||||||
|
blocked = insert(:user)
|
||||||
|
|
||||||
|
{:ok, valid_block, []} = Builder.block(user, blocked)
|
||||||
|
|
||||||
|
%{user: user, valid_block: valid_block}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "validates a basic object", %{
|
||||||
|
valid_block: valid_block
|
||||||
|
} do
|
||||||
|
assert {:ok, _block, []} = ObjectValidator.validate(valid_block, [])
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns an error if we don't know the blocked user", %{
|
||||||
|
valid_block: valid_block
|
||||||
|
} do
|
||||||
|
block =
|
||||||
|
valid_block
|
||||||
|
|> Map.put("object", "https://gensokyo.2hu/users/raymoo")
|
||||||
|
|
||||||
|
assert {:error, _cng} = ObjectValidator.validate(block, [])
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -64,6 +64,47 @@ test "it streams out notifications and streams" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "blocking users" do
|
||||||
|
setup do
|
||||||
|
user = insert(:user)
|
||||||
|
blocked = insert(:user)
|
||||||
|
User.follow(blocked, user)
|
||||||
|
User.follow(user, blocked)
|
||||||
|
|
||||||
|
{:ok, block_data, []} = Builder.block(user, blocked)
|
||||||
|
{:ok, block, _meta} = ActivityPub.persist(block_data, local: true)
|
||||||
|
|
||||||
|
%{user: user, blocked: blocked, block: block}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it unfollows and blocks", %{user: user, blocked: blocked, block: block} do
|
||||||
|
assert User.following?(user, blocked)
|
||||||
|
assert User.following?(blocked, user)
|
||||||
|
|
||||||
|
{:ok, _, _} = SideEffects.handle(block)
|
||||||
|
|
||||||
|
refute User.following?(user, blocked)
|
||||||
|
refute User.following?(blocked, user)
|
||||||
|
assert User.blocks?(user, blocked)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it blocks but does not unfollow if the relevant setting is set", %{
|
||||||
|
user: user,
|
||||||
|
blocked: blocked,
|
||||||
|
block: block
|
||||||
|
} do
|
||||||
|
clear_config([:activitypub, :unfollow_blocked], false)
|
||||||
|
assert User.following?(user, blocked)
|
||||||
|
assert User.following?(blocked, user)
|
||||||
|
|
||||||
|
{:ok, _, _} = SideEffects.handle(block)
|
||||||
|
|
||||||
|
refute User.following?(user, blocked)
|
||||||
|
assert User.following?(blocked, user)
|
||||||
|
assert User.blocks?(user, blocked)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "update users" do
|
describe "update users" do
|
||||||
setup do
|
setup do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
@ -242,8 +283,7 @@ test "when activation is required", %{delete: delete, user: user} do
|
||||||
{:ok, like} = CommonAPI.favorite(user, post.id)
|
{:ok, like} = CommonAPI.favorite(user, post.id)
|
||||||
{:ok, reaction} = CommonAPI.react_with_emoji(post.id, user, "👍")
|
{:ok, reaction} = CommonAPI.react_with_emoji(post.id, user, "👍")
|
||||||
{:ok, announce} = CommonAPI.repeat(post.id, user)
|
{:ok, announce} = CommonAPI.repeat(post.id, user)
|
||||||
{:ok, block} = ActivityPub.block(user, poster)
|
{:ok, block} = CommonAPI.block(user, poster)
|
||||||
User.block(user, poster)
|
|
||||||
|
|
||||||
{:ok, undo_data, _meta} = Builder.undo(user, like)
|
{:ok, undo_data, _meta} = Builder.undo(user, like)
|
||||||
{:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true)
|
{:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true)
|
||||||
|
@ -549,10 +589,29 @@ test "creates a notification", %{announce: announce, poster: poster} do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it streams out the announce", %{announce: announce} do
|
test "it streams out the announce", %{announce: announce} do
|
||||||
with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough], stream_out: fn _ -> nil end do
|
with_mocks([
|
||||||
|
{
|
||||||
|
Pleroma.Web.Streamer,
|
||||||
|
[],
|
||||||
|
[
|
||||||
|
stream: fn _, _ -> nil end
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Pleroma.Web.Push,
|
||||||
|
[],
|
||||||
|
[
|
||||||
|
send: fn _ -> nil end
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]) do
|
||||||
{:ok, announce, _} = SideEffects.handle(announce)
|
{:ok, announce, _} = SideEffects.handle(announce)
|
||||||
|
|
||||||
assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(announce))
|
assert called(
|
||||||
|
Pleroma.Web.Streamer.stream(["user", "list", "public", "public:local"], announce)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert called(Pleroma.Web.Push.send(:_))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
63
test/web/activity_pub/transmogrifier/block_handling_test.exs
Normal file
63
test/web/activity_pub/transmogrifier/block_handling_test.exs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ActivityPub.Transmogrifier.BlockHandlingTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
|
||||||
|
alias Pleroma.Activity
|
||||||
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||||
|
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
test "it works for incoming blocks" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
data =
|
||||||
|
File.read!("test/fixtures/mastodon-block-activity.json")
|
||||||
|
|> Poison.decode!()
|
||||||
|
|> Map.put("object", user.ap_id)
|
||||||
|
|
||||||
|
blocker = insert(:user, ap_id: data["actor"])
|
||||||
|
|
||||||
|
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
|
assert data["type"] == "Block"
|
||||||
|
assert data["object"] == user.ap_id
|
||||||
|
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||||
|
|
||||||
|
assert User.blocks?(blocker, user)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "incoming blocks successfully tear down any follow relationship" do
|
||||||
|
blocker = insert(:user)
|
||||||
|
blocked = insert(:user)
|
||||||
|
|
||||||
|
data =
|
||||||
|
File.read!("test/fixtures/mastodon-block-activity.json")
|
||||||
|
|> Poison.decode!()
|
||||||
|
|> Map.put("object", blocked.ap_id)
|
||||||
|
|> Map.put("actor", blocker.ap_id)
|
||||||
|
|
||||||
|
{:ok, blocker} = User.follow(blocker, blocked)
|
||||||
|
{:ok, blocked} = User.follow(blocked, blocker)
|
||||||
|
|
||||||
|
assert User.following?(blocker, blocked)
|
||||||
|
assert User.following?(blocked, blocker)
|
||||||
|
|
||||||
|
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
|
assert data["type"] == "Block"
|
||||||
|
assert data["object"] == blocked.ap_id
|
||||||
|
assert data["actor"] == blocker.ap_id
|
||||||
|
|
||||||
|
blocker = User.get_cached_by_ap_id(data["actor"])
|
||||||
|
blocked = User.get_cached_by_ap_id(data["object"])
|
||||||
|
|
||||||
|
assert User.blocks?(blocker, blocked)
|
||||||
|
|
||||||
|
refute User.following?(blocker, blocked)
|
||||||
|
refute User.following?(blocked, blocker)
|
||||||
|
end
|
||||||
|
end
|
|
@ -445,56 +445,6 @@ test "it works for incoming follows to locked account" do
|
||||||
assert [^pending_follower] = User.get_follow_requests(user)
|
assert [^pending_follower] = User.get_follow_requests(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it works for incoming blocks" do
|
|
||||||
user = insert(:user)
|
|
||||||
|
|
||||||
data =
|
|
||||||
File.read!("test/fixtures/mastodon-block-activity.json")
|
|
||||||
|> Poison.decode!()
|
|
||||||
|> Map.put("object", user.ap_id)
|
|
||||||
|
|
||||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
|
||||||
|
|
||||||
assert data["type"] == "Block"
|
|
||||||
assert data["object"] == user.ap_id
|
|
||||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
|
||||||
|
|
||||||
blocker = User.get_cached_by_ap_id(data["actor"])
|
|
||||||
|
|
||||||
assert User.blocks?(blocker, user)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "incoming blocks successfully tear down any follow relationship" do
|
|
||||||
blocker = insert(:user)
|
|
||||||
blocked = insert(:user)
|
|
||||||
|
|
||||||
data =
|
|
||||||
File.read!("test/fixtures/mastodon-block-activity.json")
|
|
||||||
|> Poison.decode!()
|
|
||||||
|> Map.put("object", blocked.ap_id)
|
|
||||||
|> Map.put("actor", blocker.ap_id)
|
|
||||||
|
|
||||||
{:ok, blocker} = User.follow(blocker, blocked)
|
|
||||||
{:ok, blocked} = User.follow(blocked, blocker)
|
|
||||||
|
|
||||||
assert User.following?(blocker, blocked)
|
|
||||||
assert User.following?(blocked, blocker)
|
|
||||||
|
|
||||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
|
||||||
|
|
||||||
assert data["type"] == "Block"
|
|
||||||
assert data["object"] == blocked.ap_id
|
|
||||||
assert data["actor"] == blocker.ap_id
|
|
||||||
|
|
||||||
blocker = User.get_cached_by_ap_id(data["actor"])
|
|
||||||
blocked = User.get_cached_by_ap_id(data["object"])
|
|
||||||
|
|
||||||
assert User.blocks?(blocker, blocked)
|
|
||||||
|
|
||||||
refute User.following?(blocker, blocked)
|
|
||||||
refute User.following?(blocked, blocker)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "it works for incoming accepts which were pre-accepted" do
|
test "it works for incoming accepts which were pre-accepted" do
|
||||||
follower = insert(:user)
|
follower = insert(:user)
|
||||||
followed = insert(:user)
|
followed = insert(:user)
|
||||||
|
|
|
@ -27,16 +27,6 @@ test "fetches the latest Follow activity" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "fetch the latest Block" do
|
|
||||||
test "fetches the latest Block activity" do
|
|
||||||
blocker = insert(:user)
|
|
||||||
blocked = insert(:user)
|
|
||||||
{:ok, activity} = ActivityPub.block(blocker, blocked)
|
|
||||||
|
|
||||||
assert activity == Utils.fetch_latest_block(blocker, blocked)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "determine_explicit_mentions()" do
|
describe "determine_explicit_mentions()" do
|
||||||
test "works with an object that has mentions" do
|
test "works with an object that has mentions" do
|
||||||
object = %{
|
object = %{
|
||||||
|
@ -344,9 +334,9 @@ test "fetches last block activities" do
|
||||||
user1 = insert(:user)
|
user1 = insert(:user)
|
||||||
user2 = insert(:user)
|
user2 = insert(:user)
|
||||||
|
|
||||||
assert {:ok, %Activity{} = _} = ActivityPub.block(user1, user2)
|
assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2)
|
||||||
assert {:ok, %Activity{} = _} = ActivityPub.block(user1, user2)
|
assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2)
|
||||||
assert {:ok, %Activity{} = activity} = ActivityPub.block(user1, user2)
|
assert {:ok, %Activity{} = activity} = CommonAPI.block(user1, user2)
|
||||||
|
|
||||||
assert Utils.fetch_latest_block(user1, user2) == activity
|
assert Utils.fetch_latest_block(user1, user2) == activity
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,6 +25,52 @@ defmodule Pleroma.Web.CommonAPITest do
|
||||||
setup do: clear_config([:instance, :limit])
|
setup do: clear_config([:instance, :limit])
|
||||||
setup do: clear_config([:instance, :max_pinned_statuses])
|
setup do: clear_config([:instance, :max_pinned_statuses])
|
||||||
|
|
||||||
|
describe "blocking" do
|
||||||
|
setup do
|
||||||
|
blocker = insert(:user)
|
||||||
|
blocked = insert(:user)
|
||||||
|
User.follow(blocker, blocked)
|
||||||
|
User.follow(blocked, blocker)
|
||||||
|
%{blocker: blocker, blocked: blocked}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it blocks and federates", %{blocker: blocker, blocked: blocked} do
|
||||||
|
clear_config([:instance, :federating], true)
|
||||||
|
|
||||||
|
with_mock Pleroma.Web.Federator,
|
||||||
|
publish: fn _ -> nil end do
|
||||||
|
assert {:ok, block} = CommonAPI.block(blocker, blocked)
|
||||||
|
|
||||||
|
assert block.local
|
||||||
|
assert User.blocks?(blocker, blocked)
|
||||||
|
refute User.following?(blocker, blocked)
|
||||||
|
refute User.following?(blocked, blocker)
|
||||||
|
|
||||||
|
assert called(Pleroma.Web.Federator.publish(block))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it blocks and does not federate if outgoing blocks are disabled", %{
|
||||||
|
blocker: blocker,
|
||||||
|
blocked: blocked
|
||||||
|
} do
|
||||||
|
clear_config([:instance, :federating], true)
|
||||||
|
clear_config([:activitypub, :outgoing_blocks], false)
|
||||||
|
|
||||||
|
with_mock Pleroma.Web.Federator,
|
||||||
|
publish: fn _ -> nil end do
|
||||||
|
assert {:ok, block} = CommonAPI.block(blocker, blocked)
|
||||||
|
|
||||||
|
assert block.local
|
||||||
|
assert User.blocks?(blocker, blocked)
|
||||||
|
refute User.following?(blocker, blocked)
|
||||||
|
refute User.following?(blocked, blocker)
|
||||||
|
|
||||||
|
refute called(Pleroma.Web.Federator.publish(block))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "posting chat messages" do
|
describe "posting chat messages" do
|
||||||
setup do: clear_config([:instance, :chat_limit])
|
setup do: clear_config([:instance, :chat_limit])
|
||||||
|
|
||||||
|
@ -445,6 +491,7 @@ test "it filters out obviously bad tags when accepting a post as HTML" do
|
||||||
object = Object.normalize(activity)
|
object = Object.normalize(activity)
|
||||||
|
|
||||||
assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')"
|
assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')"
|
||||||
|
assert object.data["source"] == post
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it filters out obviously bad tags when accepting a post as Markdown" do
|
test "it filters out obviously bad tags when accepting a post as Markdown" do
|
||||||
|
@ -461,6 +508,7 @@ test "it filters out obviously bad tags when accepting a post as Markdown" do
|
||||||
object = Object.normalize(activity)
|
object = Object.normalize(activity)
|
||||||
|
|
||||||
assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')"
|
assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')"
|
||||||
|
assert object.data["source"] == post
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it does not allow replies to direct messages that are not direct messages themselves" do
|
test "it does not allow replies to direct messages that are not direct messages themselves" do
|
||||||
|
|
|
@ -24,7 +24,7 @@ test "put settings", %{conn: conn} do
|
||||||
assert _result = json_response(conn, 200)
|
assert _result = json_response(conn, 200)
|
||||||
|
|
||||||
user = User.get_cached_by_ap_id(user.ap_id)
|
user = User.get_cached_by_ap_id(user.ap_id)
|
||||||
assert user.settings == %{"programming" => "socks"}
|
assert user.mastofe_settings == %{"programming" => "socks"}
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "index/2 redirections" do
|
describe "index/2 redirections" do
|
||||||
|
|
|
@ -780,7 +780,6 @@ test "with notifications", %{conn: conn} do
|
||||||
|
|
||||||
assert %{"id" => _id, "muting" => true, "muting_notifications" => true} =
|
assert %{"id" => _id, "muting" => true, "muting_notifications" => true} =
|
||||||
conn
|
conn
|
||||||
|> put_req_header("content-type", "application/json")
|
|
||||||
|> post("/api/v1/accounts/#{other_user.id}/mute")
|
|> post("/api/v1/accounts/#{other_user.id}/mute")
|
||||||
|> json_response_and_validate_schema(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,10 @@ test "get instance information", %{conn: conn} do
|
||||||
"background_image" => _
|
"background_image" => _
|
||||||
} = result
|
} = result
|
||||||
|
|
||||||
|
assert result["pleroma"]["metadata"]["account_activation_required"] != nil
|
||||||
assert result["pleroma"]["metadata"]["features"]
|
assert result["pleroma"]["metadata"]["features"]
|
||||||
assert result["pleroma"]["metadata"]["federation"]
|
assert result["pleroma"]["metadata"]["federation"]
|
||||||
|
assert result["pleroma"]["metadata"]["fields_limits"]
|
||||||
assert result["pleroma"]["vapid_public_key"]
|
assert result["pleroma"]["vapid_public_key"]
|
||||||
|
|
||||||
assert email == from_config_email
|
assert email == from_config_email
|
||||||
|
|
|
@ -79,6 +79,7 @@ test "search", %{conn: conn} do
|
||||||
assert status["id"] == to_string(activity.id)
|
assert status["id"] == to_string(activity.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@tag capture_log: true
|
||||||
test "constructs hashtags from search query", %{conn: conn} do
|
test "constructs hashtags from search query", %{conn: conn} do
|
||||||
results =
|
results =
|
||||||
conn
|
conn
|
||||||
|
@ -318,11 +319,13 @@ test "search doesn't show statuses that it shouldn't", %{conn: conn} do
|
||||||
test "search fetches remote accounts", %{conn: conn} do
|
test "search fetches remote accounts", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
|
query = URI.encode_query(%{q: " mike@osada.macgirvin.com ", resolve: true})
|
||||||
|
|
||||||
results =
|
results =
|
||||||
conn
|
conn
|
||||||
|> assign(:user, user)
|
|> assign(:user, user)
|
||||||
|> assign(:token, insert(:oauth_token, user: user, scopes: ["read"]))
|
|> assign(:token, insert(:oauth_token, user: user, scopes: ["read"]))
|
||||||
|> get("/api/v1/search?q=mike@osada.macgirvin.com&resolve=true")
|
|> get("/api/v1/search?#{query}")
|
||||||
|> json_response_and_validate_schema(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
[account] = results["accounts"]
|
[account] = results["accounts"]
|
||||||
|
|
|
@ -760,13 +760,18 @@ test "if user is authenticated", %{local: local, remote: remote} do
|
||||||
test "when you created it" do
|
test "when you created it" do
|
||||||
%{user: author, conn: conn} = oauth_access(["write:statuses"])
|
%{user: author, conn: conn} = oauth_access(["write:statuses"])
|
||||||
activity = insert(:note_activity, user: author)
|
activity = insert(:note_activity, user: author)
|
||||||
|
object = Object.normalize(activity)
|
||||||
|
|
||||||
conn =
|
content = object.data["content"]
|
||||||
|
source = object.data["source"]
|
||||||
|
|
||||||
|
result =
|
||||||
conn
|
conn
|
||||||
|> assign(:user, author)
|
|> assign(:user, author)
|
||||||
|> delete("/api/v1/statuses/#{activity.id}")
|
|> delete("/api/v1/statuses/#{activity.id}")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert %{} = json_response_and_validate_schema(conn, 200)
|
assert match?(%{"content" => ^content, "text" => ^source}, result)
|
||||||
|
|
||||||
refute Activity.get_by_id(activity.id)
|
refute Activity.get_by_id(activity.id)
|
||||||
end
|
end
|
||||||
|
@ -789,7 +794,7 @@ test "when you didn't create it" do
|
||||||
|
|
||||||
conn = delete(conn, "/api/v1/statuses/#{activity.id}")
|
conn = delete(conn, "/api/v1/statuses/#{activity.id}")
|
||||||
|
|
||||||
assert %{"error" => _} = json_response_and_validate_schema(conn, 403)
|
assert %{"error" => "Record not found"} == json_response_and_validate_schema(conn, 404)
|
||||||
|
|
||||||
assert Activity.get_by_id(activity.id) == activity
|
assert Activity.get_by_id(activity.id) == activity
|
||||||
end
|
end
|
||||||
|
|
|
@ -183,6 +183,7 @@ test "a note activity" do
|
||||||
card: nil,
|
card: nil,
|
||||||
reblog: nil,
|
reblog: nil,
|
||||||
content: HTML.filter_tags(object_data["content"]),
|
content: HTML.filter_tags(object_data["content"]),
|
||||||
|
text: nil,
|
||||||
created_at: created_at,
|
created_at: created_at,
|
||||||
reblogs_count: 0,
|
reblogs_count: 0,
|
||||||
replies_count: 0,
|
replies_count: 0,
|
||||||
|
@ -226,7 +227,8 @@ test "a note activity" do
|
||||||
expires_at: nil,
|
expires_at: nil,
|
||||||
direct_conversation_id: nil,
|
direct_conversation_id: nil,
|
||||||
thread_muted: false,
|
thread_muted: false,
|
||||||
emoji_reactions: []
|
emoji_reactions: [],
|
||||||
|
parent_visible: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -620,4 +622,20 @@ test "visibility/list" do
|
||||||
|
|
||||||
assert status.visibility == "list"
|
assert status.visibility == "list"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "has a field for parent visibility" do
|
||||||
|
user = insert(:user)
|
||||||
|
poster = insert(:user)
|
||||||
|
|
||||||
|
{:ok, invisible} = CommonAPI.post(poster, %{status: "hey", visibility: "private"})
|
||||||
|
|
||||||
|
{:ok, visible} =
|
||||||
|
CommonAPI.post(poster, %{status: "hey", visibility: "private", in_reply_to_id: invisible.id})
|
||||||
|
|
||||||
|
status = StatusView.render("show.json", activity: visible, for: user)
|
||||||
|
refute status.pleroma.parent_visible
|
||||||
|
|
||||||
|
status = StatusView.render("show.json", activity: visible, for: poster)
|
||||||
|
assert status.pleroma.parent_visible
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ defmodule Pleroma.Web.Preload.Providers.InstanceTest do
|
||||||
|
|
||||||
setup do: {:ok, Instance.generate_terms(nil)}
|
setup do: {:ok, Instance.generate_terms(nil)}
|
||||||
|
|
||||||
test "it renders the info", %{"/api/v1/instance": info} do
|
test "it renders the info", %{"/api/v1/instance" => info} do
|
||||||
assert %{
|
assert %{
|
||||||
description: description,
|
description: description,
|
||||||
email: "admin@example.com",
|
email: "admin@example.com",
|
||||||
|
@ -18,14 +18,25 @@ test "it renders the info", %{"/api/v1/instance": info} do
|
||||||
assert String.equivalent?(description, "Pleroma: An efficient and flexible fediverse server")
|
assert String.equivalent?(description, "Pleroma: An efficient and flexible fediverse server")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it renders the panel", %{"/instance/panel.html": panel} do
|
test "it renders the panel", %{"/instance/panel.html" => panel} do
|
||||||
assert String.contains?(
|
assert String.contains?(
|
||||||
panel,
|
panel,
|
||||||
"<p>Welcome to <a href=\"https://pleroma.social\" target=\"_blank\">Pleroma!</a></p>"
|
"<p>Welcome to <a href=\"https://pleroma.social\" target=\"_blank\">Pleroma!</a></p>"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it renders the node_info", %{"/nodeinfo/2.0": nodeinfo} do
|
test "it works with overrides" do
|
||||||
|
clear_config([:instance, :static_dir], "test/fixtures/preload_static")
|
||||||
|
|
||||||
|
%{"/instance/panel.html" => panel} = Instance.generate_terms(nil)
|
||||||
|
|
||||||
|
assert String.contains?(
|
||||||
|
panel,
|
||||||
|
"HEY!"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it renders the node_info", %{"/nodeinfo/2.0.json" => nodeinfo} do
|
||||||
%{
|
%{
|
||||||
metadata: metadata,
|
metadata: metadata,
|
||||||
version: "2.0"
|
version: "2.0"
|
||||||
|
|
|
@ -8,7 +8,8 @@ defmodule Pleroma.Web.Preload.Providers.StatusNetTest do
|
||||||
|
|
||||||
setup do: {:ok, StatusNet.generate_terms(nil)}
|
setup do: {:ok, StatusNet.generate_terms(nil)}
|
||||||
|
|
||||||
test "it renders the info", %{"/api/statusnet/config.json": info} do
|
test "it renders the info", %{"/api/statusnet/config.json" => info} do
|
||||||
assert info =~ "<name>Pleroma</name>"
|
assert {:ok, res} = Jason.decode(info)
|
||||||
|
assert res["site"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,7 +9,7 @@ defmodule Pleroma.Web.Preload.Providers.TimelineTest do
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.Preload.Providers.Timelines
|
alias Pleroma.Web.Preload.Providers.Timelines
|
||||||
|
|
||||||
@public_url :"/api/v1/timelines/public"
|
@public_url "/api/v1/timelines/public"
|
||||||
|
|
||||||
describe "unauthenticated timeliness when restricted" do
|
describe "unauthenticated timeliness when restricted" do
|
||||||
setup do
|
setup do
|
||||||
|
|
|
@ -9,13 +9,11 @@ defmodule Pleroma.Web.Preload.Providers.UserTest do
|
||||||
|
|
||||||
describe "returns empty when user doesn't exist" do
|
describe "returns empty when user doesn't exist" do
|
||||||
test "nil user specified" do
|
test "nil user specified" do
|
||||||
refute User.generate_terms(%{user: nil})
|
assert User.generate_terms(%{user: nil}) == %{}
|
||||||
|> Map.has_key?("/api/v1/accounts")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "missing user specified" do
|
test "missing user specified" do
|
||||||
refute User.generate_terms(%{user: :not_a_user})
|
assert User.generate_terms(%{user: :not_a_user}) == %{}
|
||||||
|> Map.has_key?("/api/v1/accounts")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -23,11 +21,13 @@ test "missing user specified" do
|
||||||
setup do
|
setup do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
{:ok, User.generate_terms(%{user: user})}
|
terms = User.generate_terms(%{user: user})
|
||||||
|
%{terms: terms, user: user}
|
||||||
end
|
end
|
||||||
|
|
||||||
test "account is rendered", %{"/api/v1/accounts": accounts} do
|
test "account is rendered", %{terms: terms, user: user} do
|
||||||
assert %{acct: user, username: user} = accounts
|
account = terms["/api/v1/accounts/#{user.id}"]
|
||||||
|
assert %{acct: user, username: user} = account
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -116,6 +116,35 @@ test "it streams boosts of the user in the 'user' stream", %{user: user} do
|
||||||
refute Streamer.filtered_by_user?(user, announce)
|
refute Streamer.filtered_by_user?(user, announce)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it does not stream announces of the user's own posts in the 'user' stream", %{
|
||||||
|
user: user
|
||||||
|
} do
|
||||||
|
Streamer.get_topic_and_add_socket("user", user)
|
||||||
|
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{status: "hey"})
|
||||||
|
{:ok, announce} = CommonAPI.repeat(activity.id, other_user)
|
||||||
|
|
||||||
|
assert Streamer.filtered_by_user?(user, announce)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it does stream notifications announces of the user's own posts in the 'user' stream", %{
|
||||||
|
user: user
|
||||||
|
} do
|
||||||
|
Streamer.get_topic_and_add_socket("user", user)
|
||||||
|
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{status: "hey"})
|
||||||
|
{:ok, announce} = CommonAPI.repeat(activity.id, other_user)
|
||||||
|
|
||||||
|
notification =
|
||||||
|
Pleroma.Notification
|
||||||
|
|> Repo.get_by(%{user_id: user.id, activity_id: announce.id})
|
||||||
|
|> Repo.preload(:activity)
|
||||||
|
|
||||||
|
refute Streamer.filtered_by_user?(user, notification)
|
||||||
|
end
|
||||||
|
|
||||||
test "it streams boosts of mastodon user in the 'user' stream", %{user: user} do
|
test "it streams boosts of mastodon user in the 'user' stream", %{user: user} do
|
||||||
Streamer.get_topic_and_add_socket("user", user)
|
Streamer.get_topic_and_add_socket("user", user)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue