diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md
index 66fbc510e..9ce9b6918 100644
--- a/.gitlab/issue_templates/Bug.md
+++ b/.gitlab/issue_templates/Bug.md
@@ -14,7 +14,7 @@
* 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):
* Operating system:
-* PostgreSQL version (`postgres -V`):
+* PostgreSQL version (`psql -V`):
### Bug description
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5b6928dcd..85401809a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
API Changes
- **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.
diff --git a/config/description.exs b/config/description.exs
index f54ac2a2a..370af80a6 100644
--- a/config/description.exs
+++ b/config/description.exs
@@ -40,12 +40,13 @@
key: :link_name,
type: :boolean,
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,
+ label: "Base URL",
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: [
"https://cdn-host.com"
]
@@ -58,6 +59,7 @@
},
%{
key: :proxy_opts,
+ label: "Proxy Options",
type: :keyword,
description: "Options for Pleroma.ReverseProxy",
suggestions: [
@@ -85,6 +87,7 @@
},
%{
key: :http,
+ label: "HTTP",
type: :keyword,
description: "HTTP options",
children: [
@@ -193,7 +196,9 @@
%{
key: :args,
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: [
"strip",
"auto-orient",
@@ -479,6 +484,7 @@
%{
group: :pleroma,
key: :uri_schemes,
+ label: "URI Schemes",
type: :group,
description: "URI schemes related settings",
children: [
@@ -651,17 +657,17 @@
key: :invites_enabled,
type: :boolean,
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,
type: :boolean,
- description: "Require users to confirm their emails before signing in."
+ description: "Require users to confirm their emails before signing in"
},
%{
key: :federating,
type: :boolean,
- description: "Enable federation with other instances."
+ description: "Enable federation with other instances"
},
%{
key: :federation_incoming_replies_max_depth,
@@ -679,7 +685,7 @@
label: "Fed. reachability timeout days",
type: :integer,
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: [
7
]
@@ -801,6 +807,7 @@
},
%{
key: :safe_dm_mentions,
+ label: "Safe DM mentions",
type: :boolean,
description:
"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,
type: :boolean,
- description: "Skip filtering out broken threads. Default: enabled"
+ description: "Skip filtering out broken threads. Default: enabled."
},
%{
key: :limit_to_local_content,
@@ -904,6 +911,7 @@
children: [
%{
key: :totp,
+ label: "TOTP settings",
type: :keyword,
description: "TOTP settings",
suggestions: [digits: 6, period: 30],
@@ -920,7 +928,7 @@
type: :integer,
suggestions: [30],
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,
type: :integer,
suggestions: [5],
- description: "number of backup codes to generate."
+ description: "Number of backup codes to generate."
},
%{
key: :length,
@@ -974,6 +982,7 @@
group: :logger,
type: :group,
key: :ex_syslogger,
+ label: "ExSyslogger",
description: "ExSyslogger-related settings",
children: [
%{
@@ -992,7 +1001,7 @@
%{
key: :format,
type: :string,
- description: "Default: \"$date $time [$level] $levelpad$node $metadata $message\".",
+ description: "Default: \"$date $time [$level] $levelpad$node $metadata $message\"",
suggestions: ["$metadata[$level] $message"]
},
%{
@@ -1006,6 +1015,7 @@
group: :logger,
type: :group,
key: :console,
+ label: "Console Logger",
description: "Console logger settings",
children: [
%{
@@ -1017,7 +1027,7 @@
%{
key: :format,
type: :string,
- description: "Default: \"$date $time [$level] $levelpad$node $metadata $message\".",
+ description: "Default: \"$date $time [$level] $levelpad$node $metadata $message\"",
suggestions: ["$metadata[$level] $message"]
},
%{
@@ -1030,6 +1040,7 @@
%{
group: :quack,
type: :group,
+ label: "Quack Logger",
description: "Quack-related settings",
children: [
%{
@@ -1140,19 +1151,19 @@
key: :greentext,
label: "Greentext",
type: :boolean,
- description: "Enables green text on lines prefixed with the > character."
+ description: "Enables green text on lines prefixed with the > character"
},
%{
key: :hideFilteredStatuses,
label: "Hide Filtered Statuses",
type: :boolean,
- description: "Hides filtered statuses from timelines."
+ description: "Hides filtered statuses from timelines"
},
%{
key: :hideMutedPosts,
label: "Hide Muted Posts",
type: :boolean,
- description: "Hides muted statuses from timelines."
+ description: "Hides muted statuses from timelines"
},
%{
key: :hidePostStats,
@@ -1164,7 +1175,7 @@
key: :hideSitename,
label: "Hide Sitename",
type: :boolean,
- description: "Hides instance name from PleromaFE banner."
+ description: "Hides instance name from PleromaFE banner"
},
%{
key: :hideUserStats,
@@ -1209,14 +1220,14 @@
label: "NSFW Censor Image",
type: :string,
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"]
},
%{
key: :postContentType,
label: "Post Content Type",
type: {:dropdown, :atom},
- description: "Default post formatting option.",
+ description: "Default post formatting option",
suggestions: ["text/plain", "text/html", "text/markdown", "text/bbcode"]
},
%{
@@ -1245,14 +1256,14 @@
key: :sidebarRight,
label: "Sidebar on Right",
type: :boolean,
- description: "Change alignment of sidebar and panels to the right."
+ description: "Change alignment of sidebar and panels to the right"
},
%{
key: :showFeaturesPanel,
label: "Show instance features panel",
type: :boolean,
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,
@@ -1310,7 +1321,7 @@
key: :mascots,
type: {:keyword, :map},
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: [
pleroma_fox_tan: %{
url: "/images/pleroma-fox-tan-smol.png",
@@ -1334,7 +1345,7 @@
%{
key: :default_user_avatar,
type: :string,
- description: "URL of the default user avatar.",
+ description: "URL of the default user avatar",
suggestions: ["/images/avi.png"]
}
]
@@ -1344,7 +1355,7 @@
key: :manifest,
type: :group,
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: [
%{
key: :icons,
@@ -1380,10 +1391,49 @@
},
%{
group: :pleroma,
- key: :mrf_simple,
- label: "MRF simple",
+ key: :mrf,
+ tab: :mrf,
+ label: "MRF",
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: [
%{
key: :media_removal,
@@ -1402,7 +1452,7 @@
key: :federated_timeline_removal,
type: {:list, :string},
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"]
},
%{
@@ -1446,14 +1496,15 @@
%{
group: :pleroma,
key: :mrf_activity_expiration,
+ tab: :mrf,
label: "MRF Activity Expiration Policy",
type: :group,
- description: "Adds expiration to all local Create Note activities",
+ description: "Adds automatic expiration to all local activities",
children: [
%{
key: :days,
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]
}
]
@@ -1461,7 +1512,8 @@
%{
group: :pleroma,
key: :mrf_subchain,
- label: "MRF subchain",
+ tab: :mrf,
+ label: "MRF Subchain",
type: :group,
description:
"This policy processes messages through an alternate pipeline when a given message matches certain criteria." <>
@@ -1482,9 +1534,9 @@
%{
group: :pleroma,
key: :mrf_rejectnonpublic,
- description:
- "MRF RejectNonPublic settings. RejectNonPublic drops posts with non-public visibility settings.",
- label: "MRF reject non public",
+ tab: :mrf,
+ description: "RejectNonPublic drops posts with non-public visibility settings.",
+ label: "MRF Reject Non Public",
type: :group,
children: [
%{
@@ -1503,16 +1555,17 @@
%{
group: :pleroma,
key: :mrf_hellthread,
- label: "MRF hellthread",
+ tab: :mrf,
+ label: "MRF Hellthread",
type: :group,
- description: "Block messages with too much mentions",
+ description: "Block messages with excessive user mentions",
children: [
%{
key: :delist_threshold,
type: :integer,
description:
- "Number of mentioned users after which the message gets delisted (the message can still be seen, " <>
- " but it will not show up in public timelines and mentioned users won't get notifications about it). Set to 0 to disable.",
+ "Number of mentioned users after which the message gets removed from timelines and" <>
+ "disables notifications. Set to 0 to disable.",
suggestions: [10]
},
%{
@@ -1527,7 +1580,8 @@
%{
group: :pleroma,
key: :mrf_keyword,
- label: "MRF keyword",
+ tab: :mrf,
+ label: "MRF Keyword",
type: :group,
description: "Reject or Word-Replace messages with a keyword or regex",
children: [
@@ -1557,14 +1611,15 @@
%{
group: :pleroma,
key: :mrf_mention,
- label: "MRF mention",
+ tab: :mrf,
+ label: "MRF Mention",
type: :group,
- description: "Block messages which mention a user",
+ description: "Block messages which mention a specific user",
children: [
%{
key: :actors,
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"]
}
]
@@ -1572,7 +1627,8 @@
%{
group: :pleroma,
key: :mrf_vocabulary,
- label: "MRF vocabulary",
+ tab: :mrf,
+ label: "MRF Vocabulary",
type: :group,
description: "Filter messages which belong to certain activity vocabularies",
children: [
@@ -1580,14 +1636,14 @@
key: :accept,
type: {:list, :string},
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"]
},
%{
key: :reject,
type: {:list, :string},
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"]
}
]
@@ -1617,6 +1673,7 @@
},
%{
key: :base_url,
+ label: "Base URL",
type: :string,
description:
"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,
+ label: "Proxy Options",
type: :keyword,
description: "Options for Pleroma.ReverseProxy",
suggestions: [
@@ -1676,6 +1734,7 @@
},
%{
key: :http,
+ label: "HTTP",
type: :keyword,
description: "HTTP options",
children: [
@@ -1771,6 +1830,7 @@
},
%{
key: :ip,
+ label: "IP",
type: :tuple,
description: "IP address to bind to",
suggestions: [{0, 0, 0, 0}]
@@ -1784,7 +1844,7 @@
%{
key: :dstport,
type: :integer,
- description: "Port advertised in urls (optional, defaults to port)",
+ description: "Port advertised in URLs (optional, defaults to port)",
suggestions: [9999]
}
]
@@ -1792,6 +1852,7 @@
%{
group: :pleroma,
key: :activitypub,
+ label: "ActivityPub",
type: :group,
description: "ActivityPub-related settings",
children: [
@@ -1814,7 +1875,7 @@
key: :note_replies_output_limit,
type: :integer,
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,
@@ -1827,6 +1888,7 @@
%{
group: :pleroma,
key: :http_security,
+ label: "HTTP security",
type: :group,
description: "HTTP security settings",
children: [
@@ -1865,7 +1927,7 @@
key: :report_uri,
label: "Report URI",
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"]
}
]
@@ -1873,9 +1935,10 @@
%{
group: :web_push_encryption,
key: :vapid_details,
+ label: "Vapid Details",
type: :group,
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: [
%{
key: :subject,
@@ -1942,6 +2005,7 @@
},
%{
group: :pleroma,
+ label: "Pleroma Admin Token",
type: :group,
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",
@@ -1949,7 +2013,7 @@
%{
key: :admin_token,
type: :string,
- description: "Token",
+ description: "Admin token",
suggestions: ["We recommend a secure random string or UUID"]
}
]
@@ -2114,24 +2178,24 @@
key: :rich_media,
type: :group,
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: [
%{
key: :enabled,
type: :boolean,
- description: "Enables RichMedia parsing of URLs."
+ description: "Enables RichMedia parsing of URLs"
},
%{
key: :ignore_hosts,
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"]
},
%{
key: :ignore_tld,
label: "Ignore TLD",
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"]
},
%{
@@ -2159,31 +2223,32 @@
%{
group: :auto_linker,
key: :opts,
+ label: "Auto Linker",
type: :group,
description: "Configuration for the auto_linker library",
children: [
%{
key: :class,
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]
},
%{
key: :rel,
type: [:string, false],
- description: "Override the rel attribute. Disable to clear",
+ description: "Override the rel attribute. Disable to clear.",
suggestions: ["ugc", "noopener noreferrer", false]
},
%{
key: :new_window,
type: :boolean,
- description: "Link urls will open in new window/tab"
+ description: "Link URLs will open in new window/tab"
},
%{
key: :truncate,
type: [:integer, false],
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]
},
%{
@@ -2194,7 +2259,7 @@
%{
key: :extra,
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,
+ label: "Pleroma Authenticator",
type: :group,
description: "Authenticator",
children: [
@@ -2253,6 +2319,7 @@
%{
group: :pleroma,
key: :ldap,
+ label: "LDAP",
type: :group,
description:
"Use LDAP for user authentication. When a user logs in to the Pleroma instance, the name and password" <>
@@ -2339,6 +2406,7 @@
},
%{
key: :uid,
+ label: "UID",
type: :string,
description:
"LDAP attribute name to authenticate the user, e.g. when \"cn\", the filter will be \"cn=username,base\"",
@@ -2354,11 +2422,12 @@
children: [
%{
key: :enforce_oauth_admin_scope_usage,
+ label: "Enforce OAuth admin scope usage",
type: :boolean,
description:
"OAuth admin scope requirement toggle. " <>
"If enabled, admin actions explicitly demand admin OAuth scope(s) presence in OAuth token " <>
- "(client app must support admin scopes). If disabled and token doesn't have admin scope(s)," <>
+ "(client app must support admin scopes). If disabled and token doesn't have admin scope(s), " <>
"`is_admin` user flag grants access to admin-specific actions."
},
%{
@@ -2370,6 +2439,7 @@
},
%{
key: :oauth_consumer_template,
+ label: "OAuth consumer template",
type: :string,
description:
"OAuth consumer mode authentication form template. By default it's `consumer.html` which corresponds to" <>
@@ -2378,6 +2448,7 @@
},
%{
key: :oauth_consumer_strategies,
+ label: "OAuth consumer strategies",
type: {:list, :string},
description:
"The list of enabled OAuth consumer strategies. By default it's set by OAUTH_CONSUMER_STRATEGIES environment variable." <>
@@ -2506,7 +2577,7 @@
%{
key: :enabled,
type: :boolean,
- description: "enables new users admin digest email when `true`",
+ description: "Enables new users admin digest email when `true`",
suggestions: [false]
}
]
@@ -2514,6 +2585,7 @@
%{
group: :pleroma,
key: :oauth2,
+ label: "OAuth2",
type: :group,
description: "Configure OAuth 2 provider capabilities",
children: [
@@ -2532,7 +2604,7 @@
%{
key: :clean_expired_tokens,
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,
+ label: "Relation ID action",
type: [:tuple, {:list, :tuple}],
description: "For actions on relation with a specific user (follow, unfollow)",
suggestions: [{1000, 10}, [{10_000, 10}, {10_000, 50}]]
@@ -2629,6 +2702,7 @@
},
%{
key: :status_id_action,
+ label: "Status ID action",
type: [:tuple, {:list, :tuple}],
description:
"For fav / unfav or reblog / unreblog actions on the same status by the same user",
@@ -2644,6 +2718,7 @@
},
%{
group: :esshd,
+ label: "ESSHD",
type: :group,
description:
"Before enabling this you must add :esshd to mix.exs as one of the extra_applications " <>
@@ -2682,8 +2757,9 @@
},
%{
group: :mime,
+ label: "Mime Types",
type: :group,
- description: "Mime types",
+ description: "Mime Types settings",
children: [
%{
key: :types,
@@ -2742,6 +2818,7 @@
%{
group: :pleroma,
key: :http,
+ label: "HTTP",
type: :group,
description: "HTTP settings",
children: [
@@ -2790,6 +2867,7 @@
%{
group: :pleroma,
key: :markup,
+ label: "Markup Settings",
type: :group,
children: [
%{
@@ -2830,8 +2908,9 @@
},
%{
group: :pleroma,
+ tab: :mrf,
key: :mrf_normalize_markup,
- label: "MRF normalize markup",
+ label: "MRF Normalize Markup",
description: "MRF NormalizeMarkup settings. Scrub configured hypertext markup.",
type: :group,
children: [
@@ -2887,6 +2966,7 @@
},
%{
group: :cors_plug,
+ label: "CORS plug config",
type: :group,
children: [
%{
@@ -2959,6 +3039,7 @@
%{
group: :pleroma,
key: :web_cache_ttl,
+ label: "Web cache TTL",
type: :group,
description:
"The expiration time for the web responses cache. Values should be in milliseconds or `nil` to disable expiration.",
@@ -2981,9 +3062,10 @@
%{
group: :pleroma,
key: :static_fe,
+ label: "Static FE",
type: :group,
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: [
%{
key: :enabled,
@@ -3001,18 +3083,18 @@
%{
key: :post_title,
type: :map,
- description: "Configure title rendering.",
+ description: "Configure title rendering",
children: [
%{
key: :max_length,
type: :integer,
- description: "Maximum number of characters before truncating title.",
+ description: "Maximum number of characters before truncating title",
suggestions: [100]
},
%{
key: :omission,
type: :string,
- description: "Replacement which will be used after truncating string.",
+ description: "Replacement which will be used after truncating string",
suggestions: ["..."]
}
]
@@ -3022,8 +3104,11 @@
%{
group: :pleroma,
key: :mrf_object_age,
+ label: "MRF Object Age",
+ tab: :mrf,
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: [
%{
key: :threshold,
@@ -3036,7 +3121,7 @@
type: {:list, :atom},
description:
"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",
suggestions: [:delist, :strip_followers, :reject]
}
@@ -3064,13 +3149,13 @@
%{
key: :workers,
type: :integer,
- description: "Number of workers to send notifications.",
+ description: "Number of workers to send notifications",
suggestions: [3]
},
%{
key: :overflow_workers,
type: :integer,
- description: "Maximum number of workers created if pool is empty.",
+ description: "Maximum number of workers created if pool is empty",
suggestions: [2]
}
]
@@ -3361,41 +3446,5 @@
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"
- ]
- }
- ]
}
]
diff --git a/docs/API/differences_in_mastoapi_responses.md b/docs/API/differences_in_mastoapi_responses.md
index 13920e5f9..72b5984ae 100644
--- a/docs/API/differences_in_mastoapi_responses.md
+++ b/docs/API/differences_in_mastoapi_responses.md
@@ -228,6 +228,7 @@ Has theses additional parameters (which are the same as in Pleroma-API):
- `background_image`: A background image that frontends can use
- `pleroma.metadata.features`: A list of supported features
- `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
## Markers
diff --git a/lib/pleroma/config/loader.ex b/lib/pleroma/config/loader.ex
index 0f3ecf1ed..64e7de6df 100644
--- a/lib/pleroma/config/loader.ex
+++ b/lib/pleroma/config/loader.ex
@@ -12,6 +12,11 @@ defmodule Pleroma.Config.Loader do
:swarm
]
+ @reject_groups [
+ :postgrex,
+ :tesla
+ ]
+
if Code.ensure_loaded?(Config.Reader) do
@reader Config.Reader
@@ -47,7 +52,8 @@ defp filter(configs) do
@spec filter_group(atom(), keyword()) :: keyword()
def filter_group(group, configs) do
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
diff --git a/lib/pleroma/html.ex b/lib/pleroma/html.ex
index d78c5f202..dc1b9b840 100644
--- a/lib/pleroma/html.ex
+++ b/lib/pleroma/html.ex
@@ -109,7 +109,7 @@ def extract_first_external_url(object, content) do
result =
content
|> 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")
|> Enum.at(0)
diff --git a/lib/pleroma/migration_helper/notification_backfill.ex b/lib/pleroma/migration_helper/notification_backfill.ex
index b3770307a..d260e62ca 100644
--- a/lib/pleroma/migration_helper/notification_backfill.ex
+++ b/lib/pleroma/migration_helper/notification_backfill.ex
@@ -3,7 +3,6 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.MigrationHelper.NotificationBackfill do
- alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
@@ -25,18 +24,27 @@ def fill_in_notification_types do
|> type_from_activity()
notification
- |> Notification.changeset(%{type: type})
+ |> Ecto.Changeset.change(%{type: type})
|> Repo.update()
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.
defp type_from_activity(%{data: %{"type" => type}} = activity) do
case type do
"Follow" ->
accepted_function = fn activity ->
- with %User{} = follower <- User.get_by_ap_id(activity.data["actor"]),
- %User{} = followed <- User.get_by_ap_id(activity.data["object"]) do
+ with %User{} = follower <- get_by_ap_id(activity.data["actor"]),
+ %User{} = followed <- get_by_ap_id(activity.data["object"]) do
Pleroma.FollowingRelationship.following?(follower, followed)
end
end
diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex
index 9ee9606be..2ef1a80c5 100644
--- a/lib/pleroma/notification.ex
+++ b/lib/pleroma/notification.ex
@@ -367,6 +367,7 @@ defp do_create_notifications(%Activity{} = activity, options) do
do_send = do_send && user in enabled_receivers
create_notification(activity, user, do_send)
end)
+ |> Enum.reject(&is_nil/1)
{:ok, notifications}
end
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 9d5c61e79..8a54546d6 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -115,7 +115,7 @@ defmodule Pleroma.User do
field(:is_moderator, :boolean, default: false)
field(:is_admin, :boolean, default: false)
field(:show_role, :boolean, default: true)
- field(:settings, :map, default: nil)
+ field(:mastofe_settings, :map, default: nil)
field(:uri, ObjectValidators.Uri, default: nil)
field(:hide_followers_count, :boolean, default: false)
field(:hide_follows_count, :boolean, default: false)
@@ -2118,8 +2118,8 @@ def mascot_update(user, url) do
def mastodon_settings_update(user, settings) do
user
- |> cast(%{settings: settings}, [:settings])
- |> validate_required([:settings])
+ |> cast(%{mastofe_settings: settings}, [:mastofe_settings])
+ |> validate_required([:mastofe_settings])
|> update_and_set_cache()
end
diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex
index cec59c372..42ff1de78 100644
--- a/lib/pleroma/user/search.ex
+++ b/lib/pleroma/user/search.ex
@@ -52,6 +52,7 @@ defp search_query(query_string, for_user, following) do
|> base_query(following)
|> filter_blocked_user(for_user)
|> filter_invisible_users()
+ |> filter_internal_users()
|> filter_blocked_domains(for_user)
|> fts_search(query_string)
|> trigram_rank(query_string)
@@ -109,6 +110,10 @@ defp filter_invisible_users(query) do
from(q in query, where: q.invisible == false)
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
query
|> join(:left, [u], b in Pleroma.UserRelationship,
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 05bd824f5..94117202c 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -1371,6 +1371,16 @@ def fetch_and_prepare_user_from_ap_id(ap_id) do
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
user = User.get_cached_by_ap_id(ap_id)
@@ -1383,6 +1393,8 @@ def make_user_from_ap_id(ap_id) do
|> User.remote_user_changeset(data)
|> User.update_and_set_cache()
else
+ maybe_handle_clashing_nickname(data[:nickname])
+
data
|> User.remote_user_changeset()
|> Repo.insert()
diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex
index 5cc2eb378..61feeae4d 100644
--- a/lib/pleroma/web/activity_pub/side_effects.ex
+++ b/lib/pleroma/web/activity_pub/side_effects.ex
@@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
collection, and so on.
"""
alias Pleroma.Activity
+ alias Pleroma.Activity.Ir.Topics
alias Pleroma.Chat
alias Pleroma.Chat.MessageReference
alias Pleroma.Notification
@@ -97,7 +98,10 @@ def handle(%{data: %{"type" => "Announce"}} = object, meta) do
if !User.is_internal_user?(user) do
Notification.create_notifications(object)
- ActivityPub.stream_out(object)
+
+ object
+ |> Topics.get_activity_topics()
+ |> Streamer.stream(object)
end
{:ok, object, meta}
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 278fbbeab..bc6fc4bd8 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -446,12 +446,9 @@ def handle_incoming(
when objtype in ["Article", "Event", "Note", "Video", "Page", "Question", "Answer", "Audio"] do
actor = Containment.get_actor(data)
- data =
- Map.put(data, "actor", actor)
- |> fix_addressing
-
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)
params = %{
diff --git a/lib/pleroma/web/api_spec/cast_and_validate.ex b/lib/pleroma/web/api_spec/cast_and_validate.ex
index bd9026237..fbfc27d6f 100644
--- a/lib/pleroma/web/api_spec/cast_and_validate.ex
+++ b/lib/pleroma/web/api_spec/cast_and_validate.ex
@@ -40,7 +40,7 @@ def call(%{private: %{open_api_spex: private_data}} = conn, %{
|> List.first()
_ ->
- nil
+ "application/json"
end
private_data = Map.put(private_data, :operation_id, operation_id)
diff --git a/lib/pleroma/web/api_spec/operations/status_operation.ex b/lib/pleroma/web/api_spec/operations/status_operation.ex
index 0b7fad793..5bd4619d5 100644
--- a/lib/pleroma/web/api_spec/operations/status_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/status_operation.ex
@@ -84,7 +84,7 @@ def delete_operation do
operationId: "StatusController.delete",
parameters: [id_param()],
responses: %{
- 200 => empty_object_response(),
+ 200 => status_response(),
403 => Operation.response("Forbidden", "application/json", ApiError),
404 => Operation.response("Not Found", "application/json", ApiError)
}
diff --git a/lib/pleroma/web/api_spec/schemas/status.ex b/lib/pleroma/web/api_spec/schemas/status.ex
index 28cde963e..947e42890 100644
--- a/lib/pleroma/web/api_spec/schemas/status.ex
+++ b/lib/pleroma/web/api_spec/schemas/status.ex
@@ -62,6 +62,11 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
}
},
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{
type: :string,
format: "date-time",
diff --git a/lib/pleroma/web/common_api/activity_draft.ex b/lib/pleroma/web/common_api/activity_draft.ex
index 9bcb9f587..f849b2e01 100644
--- a/lib/pleroma/web/common_api/activity_draft.ex
+++ b/lib/pleroma/web/common_api/activity_draft.ex
@@ -186,6 +186,7 @@ defp object(draft) do
draft.poll
)
|> Map.put("emoji", emoji)
+ |> Map.put("source", draft.status)
%__MODULE__{draft | object: object}
end
diff --git a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex
index e50980122..29affa7d5 100644
--- a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex
@@ -44,6 +44,7 @@ def search2(conn, params), do: do_search(:v2, conn, params)
def search(conn, params), do: do_search(:v1, conn, params)
defp do_search(version, %{assigns: %{user: user}} = conn, %{q: query} = params) do
+ query = String.trim(query)
options = search_options(params, user)
timeout = Keyword.get(Repo.config(), :timeout, 15_000)
default_values = %{"statuses" => [], "accounts" => [], "hashtags" => []}
diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
index 468b44b67..3f4c53437 100644
--- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
@@ -200,11 +200,18 @@ def show(%{assigns: %{user: user}} = conn, %{id: id}) do
@doc "DELETE /api/v1/statuses/:id"
def delete(%{assigns: %{user: user}} = conn, %{id: id}) do
- with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
- json(conn, %{})
+ with %Activity{} = activity <- Activity.get_by_id_with_object(id),
+ 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
- {:error, :not_found} = e -> e
- _e -> render_error(conn, :forbidden, "Can't delete this post")
+ _e -> {:error, :not_found}
end
end
diff --git a/lib/pleroma/web/mastodon_api/views/instance_view.ex b/lib/pleroma/web/mastodon_api/views/instance_view.ex
index 35c2fc25c..89e48fba5 100644
--- a/lib/pleroma/web/mastodon_api/views/instance_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/instance_view.ex
@@ -36,8 +36,10 @@ def render("show.json", _) do
background_image: Keyword.get(instance, :background_image),
pleroma: %{
metadata: %{
+ account_activation_required: Keyword.get(instance, :account_activation_required),
features: features(),
- federation: federation()
+ federation: federation(),
+ fields_limits: fields_limits()
},
vapid_public_key: Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
}
@@ -88,4 +90,13 @@ def federation do
end
|> Map.put(:enabled, Config.get([:instance, :federating]))
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
diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex
index 6ee17f4dd..fa9d695f3 100644
--- a/lib/pleroma/web/mastodon_api/views/status_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -333,6 +333,7 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity}
reblog: nil,
card: card,
content: content_html,
+ text: opts[:with_source] && object.data["source"],
created_at: created_at,
reblogs_count: announcement_count,
replies_count: object.data["repliesCount"] || 0,
diff --git a/lib/pleroma/web/preload/instance.ex b/lib/pleroma/web/preload/instance.ex
index 0b6fd3313..50d1f3382 100644
--- a/lib/pleroma/web/preload/instance.ex
+++ b/lib/pleroma/web/preload/instance.ex
@@ -3,14 +3,15 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Preload.Providers.Instance do
+ alias Pleroma.Plugs.InstanceStatic
alias Pleroma.Web.MastodonAPI.InstanceView
alias Pleroma.Web.Nodeinfo.Nodeinfo
alias Pleroma.Web.Preload.Providers.Provider
@behaviour Provider
- @instance_url :"/api/v1/instance"
- @panel_url :"/instance/panel.html"
- @nodeinfo_url :"/nodeinfo/2.0"
+ @instance_url "/api/v1/instance"
+ @panel_url "/instance/panel.html"
+ @nodeinfo_url "/nodeinfo/2.0.json"
@impl Provider
def generate_terms(_params) do
@@ -27,7 +28,7 @@ defp build_info_tag(acc) do
end
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
panel_data = File.read!(instance_path)
diff --git a/lib/pleroma/web/preload/status_net.ex b/lib/pleroma/web/preload/status_net.ex
index 367442d5c..9b62f87a2 100644
--- a/lib/pleroma/web/preload/status_net.ex
+++ b/lib/pleroma/web/preload/status_net.ex
@@ -4,10 +4,10 @@
defmodule Pleroma.Web.Preload.Providers.StatusNet do
alias Pleroma.Web.Preload.Providers.Provider
- alias Pleroma.Web.TwitterAPI.UtilView
+ alias Pleroma.Web.TwitterAPI.UtilController
@behaviour Provider
- @config_url :"/api/statusnet/config.json"
+ @config_url "/api/statusnet/config.json"
@impl Provider
def generate_terms(_params) do
@@ -16,9 +16,10 @@ def generate_terms(_params) do
end
defp build_config_tag(acc) do
- instance = Pleroma.Config.get(:instance)
- info_data = UtilView.status_net_config(instance)
+ resp =
+ 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
diff --git a/lib/pleroma/web/preload/timelines.ex b/lib/pleroma/web/preload/timelines.ex
index e531b8960..57de04051 100644
--- a/lib/pleroma/web/preload/timelines.ex
+++ b/lib/pleroma/web/preload/timelines.ex
@@ -8,7 +8,7 @@ defmodule Pleroma.Web.Preload.Providers.Timelines do
alias Pleroma.Web.Preload.Providers.Provider
@behaviour Provider
- @public_url :"/api/v1/timelines/public"
+ @public_url "/api/v1/timelines/public"
@impl Provider
def generate_terms(params) do
diff --git a/lib/pleroma/web/preload/user.ex b/lib/pleroma/web/preload/user.ex
index 3a244845b..b3d2e9b8d 100644
--- a/lib/pleroma/web/preload/user.ex
+++ b/lib/pleroma/web/preload/user.ex
@@ -3,11 +3,12 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Preload.Providers.User do
+ alias Pleroma.User
alias Pleroma.Web.MastodonAPI.AccountView
alias Pleroma.Web.Preload.Providers.Provider
@behaviour Provider
- @account_url :"/api/v1/accounts"
+ @account_url_base "/api/v1/accounts"
@impl Provider
def generate_terms(%{user: user}) do
@@ -16,10 +17,10 @@ def generate_terms(%{user: user}) do
def generate_terms(_params), do: %{}
- def build_accounts_tag(acc, nil), do: acc
-
- def build_accounts_tag(acc, user) do
+ def build_accounts_tag(acc, %User{} = user) do
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
+
+ def build_accounts_tag(acc, _), do: acc
end
diff --git a/lib/pleroma/web/streamer/streamer.ex b/lib/pleroma/web/streamer/streamer.ex
index d1d2c9b9c..d1d70e556 100644
--- a/lib/pleroma/web/streamer/streamer.ex
+++ b/lib/pleroma/web/streamer/streamer.ex
@@ -104,7 +104,9 @@ def stream(topics, items) do
:ok
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} =
User.outgoing_relationships_ap_ids(user, [:block, :mute, :reblog_mute])
@@ -116,6 +118,9 @@ def filtered_by_user?(%User{} = user, %Activity{} = item) do
true <-
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 <-
+ !(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 <- MapSet.disjoint?(recipients, recipient_blocks),
%{host: item_host} <- URI.parse(item.actor),
@@ -130,8 +135,8 @@ def filtered_by_user?(%User{} = user, %Activity{} = item) do
end
end
- def filtered_by_user?(%User{} = user, %Notification{activity: activity}) do
- filtered_by_user?(user, activity)
+ def filtered_by_user?(%User{} = user, %Notification{activity: activity}, _) do
+ filtered_by_user?(user, activity, :notification)
end
defp do_stream("direct", item) do
diff --git a/lib/pleroma/web/views/masto_fe_view.ex b/lib/pleroma/web/views/masto_fe_view.ex
index c3096006e..f739dacb6 100644
--- a/lib/pleroma/web/views/masto_fe_view.ex
+++ b/lib/pleroma/web/views/masto_fe_view.ex
@@ -86,7 +86,7 @@ def initial_state(token, user, custom_emojis) do
"video\/mp4"
]
},
- settings: user.settings || @default_settings,
+ settings: user.mastofe_settings || @default_settings,
push_subscription: nil,
accounts: %{user.id => render(AccountView, "show.json", user: user, for: user)},
custom_emojis: render(CustomEmojiView, "index.json", custom_emojis: custom_emojis),
diff --git a/mix.exs b/mix.exs
index b638be541..e2ab53bde 100644
--- a/mix.exs
+++ b/mix.exs
@@ -159,7 +159,10 @@ defp deps do
{:cors_plug, "~> 1.5"},
{:ex_doc, "~> 0.21", only: :dev, runtime: false},
{: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"},
{:gen_smtp, "~> 0.13"},
{:websocket_client, git: "https://github.com/jeremyong/websocket_client.git", only: :test},
diff --git a/mix.lock b/mix.lock
index 5ad49391d..4f2777fa7 100644
--- a/mix.lock
+++ b/mix.lock
@@ -104,9 +104,9 @@
"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"},
"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"},
- "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"]},
"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"},
diff --git a/priv/repo/migrations/20200630162024_rename_user_settings_col.exs b/priv/repo/migrations/20200630162024_rename_user_settings_col.exs
new file mode 100644
index 000000000..2355eb681
--- /dev/null
+++ b/priv/repo/migrations/20200630162024_rename_user_settings_col.exs
@@ -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
diff --git a/priv/repo/migrations/20200706060258_remove_tesla_from_config.exs b/priv/repo/migrations/20200706060258_remove_tesla_from_config.exs
new file mode 100644
index 000000000..798687f8a
--- /dev/null
+++ b/priv/repo/migrations/20200706060258_remove_tesla_from_config.exs
@@ -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
diff --git a/priv/static/adminfe/app.6684eb28.css b/priv/static/adminfe/app.01bdb34a.css
similarity index 100%
rename from priv/static/adminfe/app.6684eb28.css
rename to priv/static/adminfe/app.01bdb34a.css
diff --git a/priv/static/adminfe/chunk-43ca.0de86b6d.css b/priv/static/adminfe/chunk-43ca.0de86b6d.css
deleted file mode 100644
index 817a6be44..000000000
Binary files a/priv/static/adminfe/chunk-43ca.0de86b6d.css and /dev/null differ
diff --git a/priv/static/adminfe/chunk-43ca.af749c6c.css b/priv/static/adminfe/chunk-43ca.af749c6c.css
new file mode 100644
index 000000000..504affb93
Binary files /dev/null and b/priv/static/adminfe/chunk-43ca.af749c6c.css differ
diff --git a/priv/static/adminfe/chunk-c5f4.0827b1ce.css b/priv/static/adminfe/chunk-c5f4.0827b1ce.css
deleted file mode 100644
index eb59ca31a..000000000
Binary files a/priv/static/adminfe/chunk-c5f4.0827b1ce.css and /dev/null differ
diff --git a/priv/static/adminfe/chunk-c5f4.b1112f18.css b/priv/static/adminfe/chunk-c5f4.b1112f18.css
new file mode 100644
index 000000000..d3b7604aa
Binary files /dev/null and b/priv/static/adminfe/chunk-c5f4.b1112f18.css differ
diff --git a/priv/static/adminfe/index.html b/priv/static/adminfe/index.html
index c8f62d0c7..22b3143d2 100644
--- a/priv/static/adminfe/index.html
+++ b/priv/static/adminfe/index.html
@@ -1 +1 @@
-Admin FE
\ No newline at end of file
+Admin FE
\ No newline at end of file
diff --git a/priv/static/adminfe/static/js/app.3fcec8f6.js b/priv/static/adminfe/static/js/app.3fcec8f6.js
deleted file mode 100644
index 9a6fb1307..000000000
Binary files a/priv/static/adminfe/static/js/app.3fcec8f6.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/app.3fcec8f6.js.map b/priv/static/adminfe/static/js/app.3fcec8f6.js.map
deleted file mode 100644
index cc4ce87b3..000000000
Binary files a/priv/static/adminfe/static/js/app.3fcec8f6.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/app.f220ac13.js b/priv/static/adminfe/static/js/app.f220ac13.js
new file mode 100644
index 000000000..e5e1eda91
Binary files /dev/null and b/priv/static/adminfe/static/js/app.f220ac13.js differ
diff --git a/priv/static/adminfe/static/js/app.f220ac13.js.map b/priv/static/adminfe/static/js/app.f220ac13.js.map
new file mode 100644
index 000000000..90c22121e
Binary files /dev/null and b/priv/static/adminfe/static/js/app.f220ac13.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-0cbc.43ff796f.js b/priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js
similarity index 61%
rename from priv/static/adminfe/static/js/chunk-0cbc.43ff796f.js
rename to priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js
index 232f0d447..d29070b62 100644
Binary files a/priv/static/adminfe/static/js/chunk-0cbc.43ff796f.js and b/priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js differ
diff --git a/priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js.map b/priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js.map
new file mode 100644
index 000000000..7c99d9d48
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-0cbc.43ff796f.js.map b/priv/static/adminfe/static/js/chunk-0cbc.43ff796f.js.map
deleted file mode 100644
index dbca0ba8e..000000000
Binary files a/priv/static/adminfe/static/js/chunk-0cbc.43ff796f.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-43ca.3debeff7.js b/priv/static/adminfe/static/js/chunk-43ca.3debeff7.js
deleted file mode 100644
index 6d653cf62..000000000
Binary files a/priv/static/adminfe/static/js/chunk-43ca.3debeff7.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-43ca.3debeff7.js.map b/priv/static/adminfe/static/js/chunk-43ca.3debeff7.js.map
deleted file mode 100644
index f7976891f..000000000
Binary files a/priv/static/adminfe/static/js/chunk-43ca.3debeff7.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-43ca.aceb457c.js b/priv/static/adminfe/static/js/chunk-43ca.aceb457c.js
new file mode 100644
index 000000000..f9fcbc288
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-43ca.aceb457c.js differ
diff --git a/priv/static/adminfe/static/js/chunk-43ca.aceb457c.js.map b/priv/static/adminfe/static/js/chunk-43ca.aceb457c.js.map
new file mode 100644
index 000000000..3c71ad178
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-43ca.aceb457c.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-c5f4.304479e7.js b/priv/static/adminfe/static/js/chunk-c5f4.304479e7.js
deleted file mode 100644
index 4220621be..000000000
Binary files a/priv/static/adminfe/static/js/chunk-c5f4.304479e7.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-c5f4.304479e7.js.map b/priv/static/adminfe/static/js/chunk-c5f4.304479e7.js.map
deleted file mode 100644
index 2ab89731d..000000000
Binary files a/priv/static/adminfe/static/js/chunk-c5f4.304479e7.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js b/priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js
new file mode 100644
index 000000000..2d5308031
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js differ
diff --git a/priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js.map b/priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js.map
new file mode 100644
index 000000000..d5fc047ee
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js.map differ
diff --git a/priv/static/adminfe/static/js/runtime.5bae86dc.js b/priv/static/adminfe/static/js/runtime.0a70a9f5.js
similarity index 91%
rename from priv/static/adminfe/static/js/runtime.5bae86dc.js
rename to priv/static/adminfe/static/js/runtime.0a70a9f5.js
index e5fb1554b..a99d1d369 100644
Binary files a/priv/static/adminfe/static/js/runtime.5bae86dc.js and b/priv/static/adminfe/static/js/runtime.0a70a9f5.js differ
diff --git a/priv/static/adminfe/static/js/runtime.5bae86dc.js.map b/priv/static/adminfe/static/js/runtime.0a70a9f5.js.map
similarity index 98%
rename from priv/static/adminfe/static/js/runtime.5bae86dc.js.map
rename to priv/static/adminfe/static/js/runtime.0a70a9f5.js.map
index 46c6380d9..62e726b22 100644
Binary files a/priv/static/adminfe/static/js/runtime.5bae86dc.js.map and b/priv/static/adminfe/static/js/runtime.0a70a9f5.js.map differ
diff --git a/test/config/holder_test.exs b/test/config/holder_test.exs
index 15d48b5c7..abcaa27dd 100644
--- a/test/config/holder_test.exs
+++ b/test/config/holder_test.exs
@@ -10,7 +10,6 @@ defmodule Pleroma.Config.HolderTest do
test "default_config/0" do
config = Holder.default_config()
assert config[:pleroma][Pleroma.Uploaders.Local][:uploads] == "test/uploads"
- assert config[:tesla][:adapter] == Tesla.Mock
refute config[:pleroma][Pleroma.Repo]
refute config[:pleroma][Pleroma.Web.Endpoint]
@@ -18,17 +17,15 @@ test "default_config/0" do
refute config[:pleroma][:configurable_from_database]
refute config[:pleroma][:database]
refute config[:phoenix][:serve_endpoints]
+ refute config[:tesla][:adapter]
end
test "default_config/1" do
pleroma_config = Holder.default_config(:pleroma)
assert pleroma_config[Pleroma.Uploaders.Local][:uploads] == "test/uploads"
- tesla_config = Holder.default_config(:tesla)
- assert tesla_config[:adapter] == Tesla.Mock
end
test "default_config/2" do
assert Holder.default_config(:pleroma, Pleroma.Uploaders.Local) == [uploads: "test/uploads"]
- assert Holder.default_config(:tesla, :adapter) == Tesla.Mock
end
end
diff --git a/test/fixtures/fetch_mocks/104410921027210069.json b/test/fixtures/fetch_mocks/104410921027210069.json
new file mode 100644
index 000000000..583f7a4dc
--- /dev/null
+++ b/test/fixtures/fetch_mocks/104410921027210069.json
@@ -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" : "
@fixpoint@blobyoumu@grips@igel there's a difference between not liking nukes and not liking nuclear power nukes are pretty bad as are all WMDs in general but disliking nuclear power just indicates you are unable of thought
",
+ "contentMap" : {
+ "en" : "
@fixpoint@blobyoumu@grips@igel there's a difference between not liking nukes and not liking nuclear power nukes are pretty bad as are all WMDs in general but disliking nuclear power just indicates you are unable of thought
It has been one month since the last \"This Month in Plume\" article, so it is time for another edition of our monthly changelog!
\n
Bug Fixes and Security
\n
Let's start with the hidden, but still (very) important changes: bug fixes and security patches.
\n
First of all, @Trinity protected us against two major security flaws, called XSS and CSRF. The first one allows the attacker to run malicious code if you visit a Plume page where some of their personal data is present. The second one lets them post data with your Plume account by visiting one of their own website. It is two very common attack, and it is great we are now protected against them!
\n
The other big change in this area, is that we are now validating the data you are sending before doing anything with it. It means that, for instance, you will no longer be able to register with an empty username and to break everything.
\n
On the federation side, many issues were reported by @kaniini and redmatrix (respectively contributing to Pleroma and Hubzilla). By fixing some of them, we made it possible to federate Plume articles to Pleroma!
\n
@Trinity hopefully noticed that there was a bug in our password check code: we were not checking that your password was correct, but only that the verification process went without errors. Concretely, it means that you could login to any account with any password. I wrote this part of the code when I was still the only contributor to the project, so nobody could review my work. We will now be trying to check every change, especially when it deals with critical parts of Plume, to avoid similar issues in the future, and we I'm really sorry this happened (even if I think nobody exploited it).
\n
Zanfib and stephenburgess8 also commited some small bugfixes, improving the general experience.
\n
New Features
\n
Let's now talk about the features that we introduced during this month.
\n
One of the most easy to spot is the redesign of Plume, made by @Madeorsk. I personaly love what he did, it really improved the readability and gave Plume a bit more of identity than the previous design. And he is still improving it.
\n
We also enabled Mardown in comment, to let you write more structured and nicely formatted responses.
\n
As you may have noticed, I have used mentions in this post. Indeed, it is now possible to mention someone in your articles or in comments. It works exactly the same way as in other apps, and you should receive a notification if someone mentionned you.
\n
A dashboard to manage your blogs has also been introduced. In the future it may be used to manage your drafts, and eventually to show some statistics. The goal is to have a more specific homepage for authors.
\n
The federation with other ActivityPub softwares, like Mastodon or Pleroma is starting to work quite well, but the federation between Plume instances is far from being complete. However, we started to work on it, and it is now possible to view a distant user profile or blog from your instance, even if only basic informations are fetched yet (the articles are not loaded for instance).
\n
Another new feature that may not be visible for everyone, is the new NodeInfo endpoint. NodeInfo is a protocol allowing to get informations about a specific federated instance (whatever software it runs). It means that Plume instances can now be listed on sites like fediverse.network.
\n
Maybe you wanted to host a Plume instance, but you don't like long install process during which you are just copy/pasting commands that you don't really understand from the documentation. That's why we introduced a setup script: the first you'll launch Plume, it will ask you a few questions and automatically setup your instance in a few minutes. We hope that this feature will help to host small instances, run by non-professional adminsys. You can see a demo of this tool on asciinema.
\n
Last but not least, Plume is now translatable! It is already available in English, French, Polish (thanks to @m4sk1n)) and German (thanks to bitkeks). If your browser is configured to display pages in these languages, you should normally see the interface in your language. And if your language is not present yet, feel free to add your translation.
\n
Other Changes
\n
We also improved the code a lot. We tried to separate each part as much as possible, making it easier to re-use for other projects. For instance, our database code is now isolated from the rest of the app, which means it will be easier to make import tools from other blogging engines. Some parts of the code are even shared with another project, Aardwolf a federated Facebook alternative. For instance, both of our projects use the same internationalization code, and once Aardwolf will implement federation, this part of the code will probably be shared too. Since the WebFinger module (used to find new users and blogs) and the CSRF protection code (see the \"Bug fixes and Security\" section) have been isolated in their own modules, they may be shared by both projects too.
\n
We also worked a lot on documentation. We now have articles explaining how to setup your Plume instance on various operating systems, but also documenting the translation process. I want to thank BanjoFox (who imported some documentation from their project, Aardwolf, as the setup is quite similar), Kushal and @gled@plume.mastodon.host for working on this.
\n
As you can see, there were many changes this month, but there still a lot to do. Your help will of course be welcome. If you want to contribute to the code, translate Plume in your language, write some documentation, or anything else (or even if you're just curious about the project), feel free to join our Matrix room: #plume:disroot.org. Otherwise, as BanjoFoxsaid on the Aardwolf Team Mastodon account, talking about the project around you is one of the easiest way to help.
It has been one month since the last \"This Month in Plume\" article, so it is time for another edition of our monthly changelog!
\n
Bug Fixes and Security
\n
Let's start with the hidden, but still (very) important changes: bug fixes and security patches.
\n
First of all, @Trinity protected us against two major security flaws, called XSS and CSRF. The first one allows the attacker to run malicious code if you visit a Plume page where some of their personal data is present. The second one lets them post data with your Plume account by visiting one of their own website. It is two very common attack, and it is great we are now protected against them!
\n
The other big change in this area, is that we are now validating the data you are sending before doing anything with it. It means that, for instance, you will no longer be able to register with an empty username and to break everything.
\n
On the federation side, many issues were reported by @kaniini and redmatrix (respectively contributing to Pleroma and Hubzilla). By fixing some of them, we made it possible to federate Plume articles to Pleroma!
\n
@Trinity hopefully noticed that there was a bug in our password check code: we were not checking that your password was correct, but only that the verification process went without errors. Concretely, it means that you could login to any account with any password. I wrote this part of the code when I was still the only contributor to the project, so nobody could review my work. We will now be trying to check every change, especially when it deals with critical parts of Plume, to avoid similar issues in the future, and we I'm really sorry this happened (even if I think nobody exploited it).
\n
Zanfib and stephenburgess8 also commited some small bugfixes, improving the general experience.
\n
New Features
\n
Let's now talk about the features that we introduced during this month.
\n
One of the most easy to spot is the redesign of Plume, made by @Madeorsk. I personaly love what he did, it really improved the readability and gave Plume a bit more of identity than the previous design. And he is still improving it.
\n
We also enabled Mardown in comment, to let you write more structured and nicely formatted responses.
\n
As you may have noticed, I have used mentions in this post. Indeed, it is now possible to mention someone in your articles or in comments. It works exactly the same way as in other apps, and you should receive a notification if someone mentionned you.
\n
A dashboard to manage your blogs has also been introduced. In the future it may be used to manage your drafts, and eventually to show some statistics. The goal is to have a more specific homepage for authors.
\n
The federation with other ActivityPub softwares, like Mastodon or Pleroma is starting to work quite well, but the federation between Plume instances is far from being complete. However, we started to work on it, and it is now possible to view a distant user profile or blog from your instance, even if only basic informations are fetched yet (the articles are not loaded for instance).
\n
Another new feature that may not be visible for everyone, is the new NodeInfo endpoint. NodeInfo is a protocol allowing to get informations about a specific federated instance (whatever software it runs). It means that Plume instances can now be listed on sites like fediverse.network.
\n
Maybe you wanted to host a Plume instance, but you don't like long install process during which you are just copy/pasting commands that you don't really understand from the documentation. That's why we introduced a setup script: the first you'll launch Plume, it will ask you a few questions and automatically setup your instance in a few minutes. We hope that this feature will help to host small instances, run by non-professional adminsys. You can see a demo of this tool on asciinema.
\n
Last but not least, Plume is now translatable! It is already available in English, French, Polish (thanks to @m4sk1n)) and German (thanks to bitkeks). If your browser is configured to display pages in these languages, you should normally see the interface in your language. And if your language is not present yet, feel free to add your translation.
\n
Other Changes
\n
We also improved the code a lot. We tried to separate each part as much as possible, making it easier to re-use for other projects. For instance, our database code is now isolated from the rest of the app, which means it will be easier to make import tools from other blogging engines. Some parts of the code are even shared with another project, Aardwolf a federated Facebook alternative. For instance, both of our projects use the same internationalization code, and once Aardwolf will implement federation, this part of the code will probably be shared too. Since the WebFinger module (used to find new users and blogs) and the CSRF protection code (see the \"Bug fixes and Security\" section) have been isolated in their own modules, they may be shared by both projects too.
\n
We also worked a lot on documentation. We now have articles explaining how to setup your Plume instance on various operating systems, but also documenting the translation process. I want to thank BanjoFox (who imported some documentation from their project, Aardwolf, as the setup is quite similar), Kushal and @gled@plume.mastodon.host for working on this.
\n
As you can see, there were many changes this month, but there still a lot to do. Your help will of course be welcome. If you want to contribute to the code, translate Plume in your language, write some documentation, or anything else (or even if you're just curious about the project), feel free to join our Matrix room: #plume:disroot.org. Otherwise, as BanjoFoxsaid on the Aardwolf Team Mastodon account, talking about the project around you is one of the easiest way to help.
alert('xss')"
+ assert object.data["source"] == post
end
test "it filters out obviously bad tags when accepting a post as Markdown" do
@@ -507,6 +508,7 @@ test "it filters out obviously bad tags when accepting a post as Markdown" do
object = Object.normalize(activity)
assert object.data["content"] == "
2hu
alert('xss')"
+ assert object.data["source"] == post
end
test "it does not allow replies to direct messages that are not direct messages themselves" do
diff --git a/test/web/masto_fe_controller_test.exs b/test/web/masto_fe_controller_test.exs
index 1d107d56c..f3b54b5f2 100644
--- a/test/web/masto_fe_controller_test.exs
+++ b/test/web/masto_fe_controller_test.exs
@@ -24,7 +24,7 @@ test "put settings", %{conn: conn} do
assert _result = json_response(conn, 200)
user = User.get_cached_by_ap_id(user.ap_id)
- assert user.settings == %{"programming" => "socks"}
+ assert user.mastofe_settings == %{"programming" => "socks"}
end
describe "index/2 redirections" do
diff --git a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs
index 31f0edf97..f67d294ba 100644
--- a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs
+++ b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs
@@ -216,20 +216,10 @@ test "updates the user's avatar", %{user: user, conn: conn} do
filename: "an_image.jpg"
}
- res =
- conn
- |> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
+ conn = patch(conn, "/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
- assert user_response = json_response_and_validate_schema(res, 200)
+ assert user_response = json_response_and_validate_schema(conn, 200)
assert user_response["avatar"] != User.avatar_url(user)
-
- # Also removes it
- res =
- conn
- |> patch("/api/v1/accounts/update_credentials", %{"avatar" => nil})
-
- assert user_response = json_response_and_validate_schema(res, 200)
- assert user_response["avatar"] == User.avatar_url(user)
end
test "updates the user's banner", %{user: user, conn: conn} do
@@ -239,21 +229,10 @@ test "updates the user's banner", %{user: user, conn: conn} do
filename: "an_image.jpg"
}
- res =
- conn
- |> patch("/api/v1/accounts/update_credentials", %{"header" => new_header})
+ conn = patch(conn, "/api/v1/accounts/update_credentials", %{"header" => new_header})
- assert user_response = json_response_and_validate_schema(res, 200)
+ assert user_response = json_response_and_validate_schema(conn, 200)
assert user_response["header"] != User.banner_url(user)
-
- # Also removes it
-
- res =
- conn
- |> patch("/api/v1/accounts/update_credentials", %{"header" => nil})
-
- assert user_response = json_response_and_validate_schema(res, 200)
- assert user_response["header"] == User.banner_url(user)
end
test "updates the user's background", %{conn: conn} do
@@ -263,25 +242,13 @@ test "updates the user's background", %{conn: conn} do
filename: "an_image.jpg"
}
- res =
- conn
- |> patch("/api/v1/accounts/update_credentials", %{
+ conn =
+ patch(conn, "/api/v1/accounts/update_credentials", %{
"pleroma_background_image" => new_header
})
- assert user_response = json_response_and_validate_schema(res, 200)
+ assert user_response = json_response_and_validate_schema(conn, 200)
assert user_response["pleroma"]["background_image"]
-
- # Also removes it
-
- res =
- conn
- |> patch("/api/v1/accounts/update_credentials", %{
- "pleroma_background_image" => nil
- })
-
- assert user_response = json_response_and_validate_schema(res, 200)
- refute user_response["pleroma"]["background_image"]
end
test "requires 'write:accounts' permission" do
diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs
index ebfcedd01..260ad2306 100644
--- a/test/web/mastodon_api/controllers/account_controller_test.exs
+++ b/test/web/mastodon_api/controllers/account_controller_test.exs
@@ -780,7 +780,6 @@ test "with notifications", %{conn: conn} do
assert %{"id" => _id, "muting" => true, "muting_notifications" => true} =
conn
- |> put_req_header("content-type", "application/json")
|> post("/api/v1/accounts/#{other_user.id}/mute")
|> json_response_and_validate_schema(200)
diff --git a/test/web/mastodon_api/controllers/instance_controller_test.exs b/test/web/mastodon_api/controllers/instance_controller_test.exs
index 8bdfdddd1..95ee26416 100644
--- a/test/web/mastodon_api/controllers/instance_controller_test.exs
+++ b/test/web/mastodon_api/controllers/instance_controller_test.exs
@@ -35,8 +35,10 @@ test "get instance information", %{conn: conn} do
"background_image" => _
} = result
+ assert result["pleroma"]["metadata"]["account_activation_required"] != nil
assert result["pleroma"]["metadata"]["features"]
assert result["pleroma"]["metadata"]["federation"]
+ assert result["pleroma"]["metadata"]["fields_limits"]
assert result["pleroma"]["vapid_public_key"]
assert email == from_config_email
diff --git a/test/web/mastodon_api/controllers/search_controller_test.exs b/test/web/mastodon_api/controllers/search_controller_test.exs
index 826f37fbc..24d1959f8 100644
--- a/test/web/mastodon_api/controllers/search_controller_test.exs
+++ b/test/web/mastodon_api/controllers/search_controller_test.exs
@@ -79,6 +79,7 @@ test "search", %{conn: conn} do
assert status["id"] == to_string(activity.id)
end
+ @tag capture_log: true
test "constructs hashtags from search query", %{conn: conn} do
results =
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
user = insert(:user)
+ query = URI.encode_query(%{q: " mike@osada.macgirvin.com ", resolve: true})
+
results =
conn
|> assign(:user, user)
|> 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)
[account] = results["accounts"]
diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs
index a98e939e8..fd2de8d80 100644
--- a/test/web/mastodon_api/controllers/status_controller_test.exs
+++ b/test/web/mastodon_api/controllers/status_controller_test.exs
@@ -760,13 +760,18 @@ test "if user is authenticated", %{local: local, remote: remote} do
test "when you created it" do
%{user: author, conn: conn} = oauth_access(["write:statuses"])
activity = insert(:note_activity, user: author)
+ object = Object.normalize(activity)
- conn =
+ content = object.data["content"]
+ source = object.data["source"]
+
+ result =
conn
|> assign(:user, author)
|> 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)
end
@@ -789,7 +794,7 @@ test "when you didn't create it" do
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
end
diff --git a/test/web/mastodon_api/views/status_view_test.exs b/test/web/mastodon_api/views/status_view_test.exs
index f90a0c273..fa26b3129 100644
--- a/test/web/mastodon_api/views/status_view_test.exs
+++ b/test/web/mastodon_api/views/status_view_test.exs
@@ -183,6 +183,7 @@ test "a note activity" do
card: nil,
reblog: nil,
content: HTML.filter_tags(object_data["content"]),
+ text: nil,
created_at: created_at,
reblogs_count: 0,
replies_count: 0,
diff --git a/test/web/preload/instance_test.exs b/test/web/preload/instance_test.exs
index 42a0d87bc..a46f28312 100644
--- a/test/web/preload/instance_test.exs
+++ b/test/web/preload/instance_test.exs
@@ -8,7 +8,7 @@ defmodule Pleroma.Web.Preload.Providers.InstanceTest do
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 %{
description: description,
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")
end
- test "it renders the panel", %{"/instance/panel.html": panel} do
+ test "it renders the panel", %{"/instance/panel.html" => panel} do
assert String.contains?(
panel,
"
"
)
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,
version: "2.0"
diff --git a/test/web/preload/status_net_test.exs b/test/web/preload/status_net_test.exs
index ab6823a7e..df7acdb11 100644
--- a/test/web/preload/status_net_test.exs
+++ b/test/web/preload/status_net_test.exs
@@ -8,7 +8,8 @@ defmodule Pleroma.Web.Preload.Providers.StatusNetTest do
setup do: {:ok, StatusNet.generate_terms(nil)}
- test "it renders the info", %{"/api/statusnet/config.json": info} do
- assert info =~ "Pleroma"
+ test "it renders the info", %{"/api/statusnet/config.json" => info} do
+ assert {:ok, res} = Jason.decode(info)
+ assert res["site"]
end
end
diff --git a/test/web/preload/timeline_test.exs b/test/web/preload/timeline_test.exs
index da6a3aded..fea95a6a4 100644
--- a/test/web/preload/timeline_test.exs
+++ b/test/web/preload/timeline_test.exs
@@ -9,7 +9,7 @@ defmodule Pleroma.Web.Preload.Providers.TimelineTest do
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.Preload.Providers.Timelines
- @public_url :"/api/v1/timelines/public"
+ @public_url "/api/v1/timelines/public"
describe "unauthenticated timeliness when restricted" do
setup do
diff --git a/test/web/preload/user_test.exs b/test/web/preload/user_test.exs
index 99232cdfa..83f065e27 100644
--- a/test/web/preload/user_test.exs
+++ b/test/web/preload/user_test.exs
@@ -9,13 +9,11 @@ defmodule Pleroma.Web.Preload.Providers.UserTest do
describe "returns empty when user doesn't exist" do
test "nil user specified" do
- refute User.generate_terms(%{user: nil})
- |> Map.has_key?("/api/v1/accounts")
+ assert User.generate_terms(%{user: nil}) == %{}
end
test "missing user specified" do
- refute User.generate_terms(%{user: :not_a_user})
- |> Map.has_key?("/api/v1/accounts")
+ assert User.generate_terms(%{user: :not_a_user}) == %{}
end
end
@@ -23,11 +21,13 @@ test "missing user specified" do
setup do
user = insert(:user)
- {:ok, User.generate_terms(%{user: user})}
+ terms = User.generate_terms(%{user: user})
+ %{terms: terms, user: user}
end
- test "account is rendered", %{"/api/v1/accounts": accounts} do
- assert %{acct: user, username: user} = accounts
+ test "account is rendered", %{terms: terms, user: user} do
+ account = terms["/api/v1/accounts/#{user.id}"]
+ assert %{acct: user, username: user} = account
end
end
end
diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs
index 245f6e63f..d56d74464 100644
--- a/test/web/streamer/streamer_test.exs
+++ b/test/web/streamer/streamer_test.exs
@@ -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)
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
Streamer.get_topic_and_add_socket("user", user)