...
 
Commits (34)
......@@ -127,7 +127,10 @@ config :pleroma, :fe,
formatting_options_enabled: true,
collapse_message_with_subject: true,
hide_post_stats: false,
hide_user_stats: false
hide_user_stats: false,
scope_copy: true,
subject_line_behavior: "email",
always_show_subject_input: true
config :pleroma, :activitypub,
accept_blocks: true,
......
......@@ -19,6 +19,17 @@ Note: `strip_exif` has been replaced by `Pleroma.Upload.Filter.Mogrify`.
* `args`: List of actions for the `mogrify` command like `"strip"` or `["strip", {"impode", "1"}]`.
## Pleroma.Upload.Filter.Dedupe
No specific configuration.
## Pleroma.Upload.Filter.AnonymizeFilename
This filter replaces the filename (not the path) of an upload. For complete obfuscation, add
`Pleroma.Upload.Filter.Dedupe` before AnonymizeFilename.
* `text`: Text to replace filenames in links. If empty, `{random}.extension` will be used.
## :uri_schemes
* `valid_schemes`: List of the scheme part that is considered valid to be an URL
......@@ -30,9 +41,9 @@ Note: `strip_exif` has been replaced by `Pleroma.Upload.Filter.Mogrify`.
* `upload_limit`: File size limit of uploads (except for avatar, background, banner)
* `avatar_upload_limit`: File size limit of user’s profile avatars
* `background_upload_limit`: File size limit of user’s profile backgrounds
* `banner_upload_limit`: File size limit of user’s profile backgrounds
* `registerations_open`: Enable registerations for anyone, invitations can be used when false.
* `federating`
* `banner_upload_limit`: File size limit of user’s profile banners
* `registrations_open`: Enable registrations for anyone, invitations can be used when false.
* `federating`: Enable federation with other instances
* `allow_relay`: Enable Pleroma’s Relay, which makes it possible to follow a whole instance
* `rewrite_policy`: Message Rewrite Policy, either one or a list. Here are the ones available by default:
* `Pleroma.Web.ActivityPub.MRF.NoOpPolicy`: Doesn’t modify activities (default)
......@@ -46,6 +57,12 @@ Note: `strip_exif` has been replaced by `Pleroma.Upload.Filter.Mogrify`.
* `allowed_post_formats`: MIME-type list of formats allowed to be posted (transformed into HTML)
* `finmoji_enabled`: Whenether to enable the finmojis in the custom emojis.
* `mrf_transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo).
* `scope_copy`: Copy the scope (private/unlisted/public) in replies to posts by default.
* `subject_line_behavior`: Allows changing the default behaviour of subject lines in replies. Valid values:
* "email": Copy and preprend re:, as in email.
* "masto": Copy verbatim, as in Mastodon.
* "noop": Don't copy the subject.
* `always_show_subject_input`: When set to false, auto-hide the subject field when it's empty.
## :fe
This section is used to configure Pleroma-FE, unless ``:managed_config`` in ``:instance`` is set to false.
......
......@@ -72,6 +72,11 @@ server {
location ~ ^/(media|proxy) {
proxy_cache pleroma_media_cache;
slice 1m;
proxy_cache_key $host$uri$is_args$args$slice_range;
proxy_set_header Range $slice_range;
proxy_http_version 1.1;
proxy_cache_valid 200 206 301 304 1h;
proxy_cache_lock on;
proxy_ignore_client_abort on;
proxy_buffering off;
......
defmodule Mix.Tasks.Pleroma.Common do
@shortdoc "Common functions to be reused in mix tasks"
@doc "Common functions to be reused in mix tasks"
def start_pleroma do
Mix.Task.run("app.start")
end
......
defmodule Mix.Tasks.Pleroma.Instance do
use Mix.Task
alias Pleroma.{Repo, User}
alias Mix.Tasks.Pleroma.Common
@shortdoc "Manages Pleroma instance"
......
......@@ -22,7 +22,7 @@ defmodule Mix.Tasks.Pleroma.Relay do
def run(["follow", target]) do
Common.start_pleroma()
with {:ok, activity} <- Relay.follow(target) do
with {:ok, _activity} <- Relay.follow(target) do
# put this task to sleep to allow the genserver to push out the messages
:timer.sleep(500)
else
......@@ -33,7 +33,7 @@ defmodule Mix.Tasks.Pleroma.Relay do
def run(["unfollow", target]) do
Common.start_pleroma()
with {:ok, activity} <- Relay.unfollow(target) do
with {:ok, _activity} <- Relay.unfollow(target) do
# put this task to sleep to allow the genserver to push out the messages
:timer.sleep(500)
else
......
defmodule Mix.Tasks.Pleroma.Uploads do
use Mix.Task
import Mix.Ecto
alias Pleroma.{Upload, Uploaders.Local, Uploaders.S3}
alias Pleroma.{Upload, Uploaders.Local}
alias Mix.Tasks.Pleroma.Common
require Logger
@log_every 50
@shortdoc "Migrate uploads from local to remote storage"
@longdoc """
@shortdoc "Migrates uploads from local to remote storage"
@moduledoc """
Manages uploads
## Migrate uploads from local to remote storage
mix pleroma.uploads migrate_local TARGET_UPLOADER [OPTIONS...]
Options:
- `--delete` - delete local uploads after migrating them to the target uploader
"""
A list of avalible uploaders can be seen in config.exs
"""
def run(["migrate_local", target_uploader | args]) do
delete? = Enum.member?(args, "--delete")
Common.start_pleroma()
......@@ -59,7 +64,7 @@ defmodule Mix.Tasks.Pleroma.Uploads do
File.exists?(root_path) ->
file = Path.basename(id)
[hash, ext] = String.split(id, ".")
hash = Path.rootname(id)
{%Pleroma.Upload{id: hash, name: file, path: file, tempfile: root_path}, root_path}
true ->
......
......@@ -20,7 +20,7 @@ defmodule Mix.Tasks.Pleroma.User do
- `--admin`/`--no-admin` - whether the user is an admin
## Generate an invite link.
mix pleroma.user invite
## Delete the user's account.
......@@ -32,7 +32,7 @@ defmodule Mix.Tasks.Pleroma.User do
mix pleroma.user toggle_activated NICKNAME
## Unsubscribe local users from user's account and deactivate it
mix pleroma.user unsubscribe NICKNAME
## Create a password reset link.
......@@ -235,6 +235,26 @@ defmodule Mix.Tasks.Pleroma.User do
end
end
def run(["invite"]) do
Common.start_pleroma()
with {:ok, token} <- Pleroma.UserInviteToken.create_token() do
Mix.shell().info("Generated user invite token")
url =
Pleroma.Web.Router.Helpers.redirect_url(
Pleroma.Web.Endpoint,
:registration_page,
token.token
)
IO.puts(url)
else
_ ->
Mix.shell().error("Could not create invite token.")
end
end
defp set_moderator(user, value) do
info_cng = User.Info.admin_api_update(user.info, %{is_moderator: value})
......@@ -270,24 +290,4 @@ defmodule Mix.Tasks.Pleroma.User do
Mix.shell().info("Locked status of #{user.nickname}: #{user.info.locked}")
end
def run(["invite"]) do
Common.start_pleroma()
with {:ok, token} <- Pleroma.UserInviteToken.create_token() do
Mix.shell().info("Generated user invite token")
url =
Pleroma.Web.Router.Helpers.redirect_url(
Pleroma.Web.Endpoint,
:registration_page,
token.token
)
IO.puts(url)
else
_ ->
Mix.shell().error("Could not create invite token.")
end
end
end
......@@ -15,7 +15,6 @@ defmodule Pleroma.Application do
# See http://elixir-lang.org/docs/stable/elixir/Application.html
# for more information on OTP Applications
@env Mix.env()
def start(_type, _args) do
import Cachex.Spec
......
......@@ -165,7 +165,7 @@ defmodule Pleroma.Emoji do
defp load_from_file_stream(stream) do
stream
|> Stream.map(&String.strip/1)
|> Stream.map(&String.trim/1)
|> Stream.map(fn line ->
case String.split(line, ~r/,\s*/) do
[name, file] -> {name, file}
......
defmodule Pleroma.Filter do
use Ecto.Schema
import Ecto.{Changeset, Query}
alias Pleroma.{User, Repo, Activity}
alias Pleroma.{User, Repo}
schema "filters" do
belongs_to(:user, Pleroma.User)
belongs_to(:user, User)
field(:filter_id, :integer)
field(:hide, :boolean, default: false)
field(:whole_word, :boolean, default: true)
......@@ -26,7 +26,7 @@ defmodule Pleroma.Filter do
Repo.one(query)
end
def get_filters(%Pleroma.User{id: user_id} = user) do
def get_filters(%User{id: user_id} = _user) do
query =
from(
f in Pleroma.Filter,
......@@ -38,9 +38,9 @@ defmodule Pleroma.Filter do
def create(%Pleroma.Filter{user_id: user_id, filter_id: nil} = filter) do
# If filter_id wasn't given, use the max filter_id for this user plus 1.
# XXX This could result in a race condition if a user tries to add two
# different filters for their account from two different clients at the
# same time, but that should be unlikely.
# XXX This could result in a race condition if a user tries to add two
# different filters for their account from two different clients at the
# same time, but that should be unlikely.
max_id_query =
from(
......
......@@ -166,7 +166,7 @@ defmodule Pleroma.HTML.Transform.MediaProxy do
{"src", media_url}
end
def scrub_attribute(tag, attribute), do: attribute
def scrub_attribute(_tag, attribute), do: attribute
def scrub({"img", attributes, children}) do
attributes =
......@@ -177,9 +177,9 @@ defmodule Pleroma.HTML.Transform.MediaProxy do
{"img", attributes, children}
end
def scrub({:comment, children}), do: ""
def scrub({:comment, _children}), do: ""
def scrub({tag, attributes, children}), do: {tag, attributes, children}
def scrub({tag, children}), do: children
def scrub({_tag, children}), do: children
def scrub(text), do: text
end
......@@ -25,7 +25,7 @@ defmodule Pleroma.HTTP.Connection do
# fetch Hackney options
#
defp hackney_options(opts \\ []) do
defp hackney_options(opts) do
options = Keyword.get(opts, :adapter, [])
@hackney_options ++ options
end
......
......@@ -23,7 +23,7 @@ defmodule Pleroma.List do
|> validate_required([:following])
end
def for_user(user, opts) do
def for_user(user, _opts) do
query =
from(
l in Pleroma.List,
......@@ -46,7 +46,7 @@ defmodule Pleroma.List do
Repo.one(query)
end
def get_following(%Pleroma.List{following: following} = list) do
def get_following(%Pleroma.List{following: following} = _list) do
q =
from(
u in User,
......
......@@ -3,7 +3,7 @@ defmodule Pleroma.MIME do
Returns the mime-type of a binary and optionally a normalized file-name.
"""
@default "application/octet-stream"
@read_bytes 31
@read_bytes 35
@spec file_mime_type(String.t()) ::
{:ok, content_type :: String.t(), filename :: String.t()} | {:error, any()} | :error
......@@ -33,10 +33,10 @@ defmodule Pleroma.MIME do
{:ok, check_mime_type(head)}
end
def mime_type(<<_::binary>>), do: {:ok, @default}
def bin_mime_type(_), do: :error
def mime_type(<<_::binary>>), do: {:ok, @default}
defp fix_extension(filename, content_type) do
parts = String.split(filename, ".")
......
......@@ -118,7 +118,7 @@ defmodule Pleroma.Notification do
def get_notified_from_activity(activity, local_only \\ true)
def get_notified_from_activity(
%Activity{data: %{"to" => _, "type" => type} = data} = activity,
%Activity{data: %{"to" => _, "type" => type} = _data} = activity,
local_only
)
when type in ["Create", "Like", "Announce", "Follow"] do
......@@ -131,18 +131,18 @@ defmodule Pleroma.Notification do
User.get_users_from_set(recipients, local_only)
end
def get_notified_from_activity(_, local_only), do: []
def get_notified_from_activity(_, _local_only), do: []
defp maybe_notify_to_recipients(
recipients,
%Activity{data: %{"to" => to, "type" => type}} = activity
%Activity{data: %{"to" => to, "type" => _type}} = _activity
) do
recipients ++ to
end
defp maybe_notify_mentioned_recipients(
recipients,
%Activity{data: %{"to" => to, "type" => type} = data} = activity
%Activity{data: %{"to" => _to, "type" => type} = data} = _activity
)
when type == "Create" do
object = Object.normalize(data["object"])
......
......@@ -26,14 +26,7 @@ defmodule Pleroma.Plugs.AuthenticationPlug do
end
end
def call(
%{
assigns: %{
auth_credentials: %{password: password}
}
} = conn,
_
) do
def call(%{assigns: %{auth_credentials: %{password: _}}} = conn, _) do
Pbkdf2.dummy_checkpw()
conn
end
......
......@@ -5,7 +5,7 @@ defmodule Pleroma.Plugs.BasicAuthDecoderPlug do
options
end
def call(conn, opts) do
def call(conn, _opts) do
with ["Basic " <> header] <- get_req_header(conn, "authorization"),
{:ok, userinfo} <- Base.decode64(header),
[username, password] <- String.split(userinfo, ":", parts: 2) do
......
......@@ -5,7 +5,7 @@ defmodule Pleroma.Web.FederatingPlug do
options
end
def call(conn, opts) do
def call(conn, _opts) do
if Keyword.get(Application.get_env(:pleroma, :instance), :federating) do
conn
else
......
......@@ -4,11 +4,11 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do
def init(opts), do: opts
def call(conn, options) do
def call(conn, _options) do
if Config.get([:http_security, :enabled]) do
conn =
merge_resp_headers(conn, headers())
|> maybe_send_sts_header(Config.get([:http_security, :sts]))
conn
|> merge_resp_headers(headers())
|> maybe_send_sts_header(Config.get([:http_security, :sts]))
else
conn
end
......@@ -42,7 +42,7 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do
"script-src 'self'",
"connect-src 'self' " <> String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws"),
"manifest-src 'self'",
if @protocol == "https" do
if protocol == "https" do
"upgrade-insecure-requests"
end
]
......
defmodule Pleroma.Plugs.SessionAuthenticationPlug do
import Plug.Conn
alias Pleroma.User
def init(options) do
options
......
......@@ -8,10 +8,6 @@ defmodule Pleroma.Plugs.UploadedMedia do
@behaviour Plug
# no slashes
@path "media"
@cache_control %{
default: "public, max-age=1209600",
error: "public, must-revalidate, max-age=160"
}
def init(_opts) do
static_plug_opts =
......
......@@ -7,7 +7,7 @@ defmodule Pleroma.Plugs.UserFetcherPlug do
options
end
def call(conn, options) do
def call(conn, _options) do
with %{auth_credentials: %{username: username}} <- conn.assigns,
{:ok, %User{} = user} <- user_fetcher(username) do
conn
......
......@@ -85,7 +85,9 @@ defmodule Pleroma.ReverseProxy do
| {:redirect_on_failure, boolean()}
@spec call(Plug.Conn.t(), url :: String.t(), [option()]) :: Plug.Conn.t()
def call(conn = %{method: method}, url, opts \\ []) when method in @methods do
def call(_conn, _url, _opts \\ [])
def call(conn = %{method: method}, url, opts) when method in @methods do
hackney_opts =
@default_hackney_options
|> Keyword.merge(Keyword.get(opts, :http, []))
......@@ -240,24 +242,23 @@ defmodule Pleroma.ReverseProxy do
end
defp build_req_headers(headers, opts) do
headers =
headers
|> downcase_headers()
|> Enum.filter(fn {k, _} -> k in @keep_req_headers end)
|> (fn headers ->
headers = headers ++ Keyword.get(opts, :req_headers, [])
if Keyword.get(opts, :keep_user_agent, false) do
List.keystore(
headers,
"user-agent",
0,
{"user-agent", Pleroma.Application.user_agent()}
)
else
headers
end
end).()
headers
|> downcase_headers()
|> Enum.filter(fn {k, _} -> k in @keep_req_headers end)
|> (fn headers ->
headers = headers ++ Keyword.get(opts, :req_headers, [])
if Keyword.get(opts, :keep_user_agent, false) do
List.keystore(
headers,
"user-agent",
0,
{"user-agent", Pleroma.Application.user_agent()}
)
else
headers
end
end).()
end
defp build_resp_headers(headers, opts) do
......@@ -268,7 +269,7 @@ defmodule Pleroma.ReverseProxy do
|> (fn headers -> headers ++ Keyword.get(opts, :resp_headers, []) end).()
end
defp build_resp_cache_headers(headers, opts) do
defp build_resp_cache_headers(headers, _opts) do
has_cache? = Enum.any?(headers, fn {k, _} -> k in @resp_cache_headers end)
if has_cache? do
......
......@@ -128,19 +128,18 @@ defmodule Pleroma.Upload do
opts
end
opts =
if Pleroma.Config.get([:instance, :dedupe_media]) == true &&
!Enum.member?(opts.filters, Pleroma.Upload.Filter.Dedupe) do
Logger.warn("""
Pleroma: configuration `:instance, :dedupe_media` is deprecated, please instead set:
if Pleroma.Config.get([:instance, :dedupe_media]) == true &&
!Enum.member?(opts.filters, Pleroma.Upload.Filter.Dedupe) do
Logger.warn("""
Pleroma: configuration `:instance, :dedupe_media` is deprecated, please instead set:
:pleroma, Pleroma.Upload, [filters: [Pleroma.Upload.Filter.Dedupe]]
""")
:pleroma, Pleroma.Upload, [filters: [Pleroma.Upload.Filter.Dedupe]]
""")
Map.put(opts, :filters, opts.filters ++ [Pleroma.Upload.Filter.Dedupe])
else
opts
end
Map.put(opts, :filters, opts.filters ++ [Pleroma.Upload.Filter.Dedupe])
else
opts
end
end
defp prepare_upload(%Plug.Upload{} = file, opts) do
......@@ -216,7 +215,5 @@ defmodule Pleroma.Upload do
|> Path.join()
end
defp url_from_spec({:url, url}) do
url
end
defp url_from_spec(_base_url, {:url, url}), do: url
end
defmodule Pleroma.Upload.Filter.AnonymizeFilename do
@moduledoc "Replaces the original filename with a randomly generated string."
@moduledoc """
Replaces the original filename with a pre-defined text or randomly generated string.
Should be used after `Pleroma.Upload.Filter.Dedupe`.
"""
@behaviour Pleroma.Upload.Filter
def filter(upload) do
extension = List.last(String.split(upload.name, "."))
string = Base.url_encode64(:crypto.strong_rand_bytes(10), padding: false)
{:ok, %Pleroma.Upload{upload | name: string <> "." <> extension}}
name = Pleroma.Config.get([__MODULE__, :text], random(extension))
{:ok, %Pleroma.Upload{upload | name: name}}
end
defp random(extension) do
string =
10
|> :crypto.strong_rand_bytes()
|> Base.url_encode64(padding: false)
string <> "." <> extension
end
end
defmodule Pleroma.Upload.Filter.Dedupe do
@behaviour Pleroma.Upload.Filter
alias Pleroma.Upload
def filter(upload = %Pleroma.Upload{name: name, tempfile: path}) do
def filter(upload = %Upload{name: name}) do
extension = String.split(name, ".") |> List.last()
shasum = :crypto.hash(:sha256, File.read!(upload.tempfile)) |> Base.encode16(case: :lower)
filename = shasum <> "." <> extension
{:ok, %Pleroma.Upload{upload | id: shasum, path: filename}}
{:ok, %Upload{upload | id: shasum, path: filename}}
end
end
defmodule Pleroma.Upload.Filter.Mogrify do
@behaviour Pleroma.Uploader.Filter
@behaviour Pleroma.Upload.Filter
@type conversion :: action :: String.t() | {action :: String.t(), opts :: String.t()}
@type conversions :: conversion() | [conversion()]
......
defmodule Pleroma.Uploaders.Local do
@behaviour Pleroma.Uploaders.Uploader
alias Pleroma.Web
def get_file(_) do
{:ok, {:static_dir, upload_path()}}
end
......
......@@ -12,8 +12,8 @@ defmodule Pleroma.Uploaders.MDII do
end
def put_file(upload) do
cgi = Pleroma.Config.get([Pleroma.Uploaders.MDII, :cgi])
files = Pleroma.Config.get([Pleroma.Uploaders.MDII, :files])
cgi = Config.get([Pleroma.Uploaders.MDII, :cgi])
files = Config.get([Pleroma.Uploaders.MDII, :files])
{:ok, file_data} = File.read(upload.tempfile)
......
......@@ -9,7 +9,6 @@ defmodule Pleroma.Uploaders.Swift.Client do
end
def upload_file(filename, body, content_type) do
object_url = Pleroma.Config.get!([Pleroma.Uploaders.Swift, :object_url])
token = Pleroma.Uploaders.Swift.Keystone.get_token()
case put("#{filename}", body, "X-Auth-Token": token, "Content-Type": content_type) do
......
......@@ -2,7 +2,6 @@ defmodule Pleroma.User do
use Ecto.Schema
import Ecto.{Changeset, Query}
alias Ecto.Multi
alias Pleroma.{Repo, User, Object, Web, Activity, Notification}
alias Comeonin.Pbkdf2
alias Pleroma.Formatter
......@@ -10,6 +9,8 @@ defmodule Pleroma.User do
alias Pleroma.Web.{OStatus, Websub, OAuth}
alias Pleroma.Web.ActivityPub.{Utils, ActivityPub}
@type t :: %__MODULE__{}
schema "users" do
field(:bio, :string)
field(:email, :string)
......@@ -211,14 +212,14 @@ defmodule Pleroma.User do
end
def maybe_direct_follow(%User{} = follower, %User{} = followed) do
if !User.ap_enabled?(followed) do
if not User.ap_enabled?(followed) do
follow(follower, followed)
else
{:ok, follower}
end
end
def maybe_follow(%User{} = follower, %User{info: info} = followed) do
def maybe_follow(%User{} = follower, %User{info: _info} = followed) do
if not following?(follower, followed) do
follow(follower, followed)
else
......@@ -280,6 +281,7 @@ defmodule Pleroma.User do
end
end
@spec following?(User.t(), User.t()) :: boolean
def following?(%User{} = follower, %User{} = followed) do
Enum.member?(follower.following, followed.follower_address)
end
......@@ -734,7 +736,8 @@ defmodule Pleroma.User do
source_data: %{"publicKey" => %{"publicKeyPem" => public_key_pem}}
}) do
key =
:public_key.pem_decode(public_key_pem)
public_key_pem
|> :public_key.pem_decode()
|> hd()
|> :public_key.pem_entry_decode()
......@@ -772,13 +775,10 @@ defmodule Pleroma.User do
def ap_enabled?(%User{info: info}), do: info.ap_enabled
def ap_enabled?(_), do: false
def get_or_fetch(uri_or_nickname) do
if String.starts_with?(uri_or_nickname, "http") do
get_or_fetch_by_ap_id(uri_or_nickname)
else
get_or_fetch_by_nickname(uri_or_nickname)
end
end
@doc "Gets or fetch a user by uri or nickname."
@spec get_or_fetch(String.t()) :: User.t()
def get_or_fetch("http" <> _host = uri), do: get_or_fetch_by_ap_id(uri)
def get_or_fetch(nickname), do: get_or_fetch_by_nickname(nickname)
# wait a period of time and return newest version of the User structs
# this is because we have synchronous follow APIs and need to simulate them
......@@ -804,7 +804,11 @@ defmodule Pleroma.User do
end
end
def parse_bio(bio, user \\ %User{info: %{source_data: %{}}}) do
def parse_bio(bio, user \\ %User{info: %{source_data: %{}}})
def parse_bio(nil, _user), do: ""
def parse_bio(bio, _user) when bio == "", do: bio
def parse_bio(bio, user) do
mentions = Formatter.parse_mentions(bio)
tags = Formatter.parse_tags(bio)
......@@ -815,7 +819,9 @@ defmodule Pleroma.User do
{String.trim(name, ":"), url}
end)
CommonUtils.format_input(bio, mentions, tags, "text/plain") |> Formatter.emojify(emoji)
bio
|> CommonUtils.format_input(mentions, tags, "text/plain")
|> Formatter.emojify(emoji)
end
def tag(user_identifiers, tags) when is_list(user_identifiers) do
......@@ -824,20 +830,21 @@ defmodule Pleroma.User do
end)
end
def tag(nickname, tags) when is_binary(nickname),
do: tag(User.get_by_nickname(nickname), tags)
def tag(%User{} = user, tags),
do: update_tags(user, Enum.uniq(user.tags ++ normalize_tags(tags)))
def untag(user_identifiers, tags) when is_list(user_identifiers) do
Repo.transaction(fn ->
for user_identifier <- user_identifiers, do: untag(user_identifier, tags)
end)
end
def tag(nickname, tags) when is_binary(nickname), do: tag(User.get_by_nickname(nickname), tags)
def untag(nickname, tags) when is_binary(nickname),
do: untag(User.get_by_nickname(nickname), tags)
def tag(%User{} = user, tags),
do: update_tags(user, Enum.uniq(user.tags ++ normalize_tags(tags)))
def untag(%User{} = user, tags), do: update_tags(user, user.tags -- normalize_tags(tags))
defp update_tags(%User{} = user, new_tags) do
......
......@@ -3,7 +3,8 @@ defmodule Pleroma.UserInviteToken do
import Ecto.Changeset
alias Pleroma.{User, UserInviteToken, Repo}
alias Pleroma.UserInviteToken
alias Pleroma.Repo
schema "user_invite_tokens" do
field(:token, :string)
......
......@@ -799,7 +799,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
# guard
def entire_thread_visible_for_user?(nil, user), do: false
def entire_thread_visible_for_user?(nil, _user), do: false
# child
def entire_thread_visible_for_user?(
......
......@@ -141,7 +141,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
json(conn, "error")
end
def relay(conn, params) do
def relay(conn, _params) do
with %User{} = user <- Relay.get_actor(),
{:ok, user} <- Pleroma.Web.WebFinger.ensure_keys_present(user) do
conn
......
......@@ -5,7 +5,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrepended do
@reply_prefix Regex.compile!("^re:[[:space:]]*", [:caseless])
def filter_by_summary(
%{"summary" => parent_summary} = parent,
%{"summary" => parent_summary} = _parent,
%{"summary" => child_summary} = child
)
when not is_nil(child_summary) and byte_size(child_summary) > 0 and
......@@ -19,7 +19,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrepended do
end
end
def filter_by_summary(parent, child), do: child
def filter_by_summary(_parent, child), do: child
def filter(%{"type" => activity_type} = object) when activity_type == "Create" do
child = object["object"]
......
......@@ -37,9 +37,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
@doc """
Checks that an imported AP object's actor matches the domain it came from.
"""
def contain_origin(id, %{"actor" => nil}), do: :error
def contain_origin(_id, %{"actor" => nil}), do: :error
def contain_origin(id, %{"actor" => actor} = params) do
def contain_origin(id, %{"actor" => _actor} = params) do
id_uri = URI.parse(id)
actor_uri = URI.parse(get_actor(params))
......@@ -50,9 +50,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
end
def contain_origin_from_id(id, %{"id" => nil}), do: :error
def contain_origin_from_id(_id, %{"id" => nil}), do: :error
def contain_origin_from_id(id, %{"id" => other_id} = params) do
def contain_origin_from_id(id, %{"id" => other_id} = _params) do
id_uri = URI.parse(id)
other_uri = URI.parse(other_id)
......@@ -266,6 +266,32 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def fix_content_map(object), do: object
defp mastodon_follow_hack(%{"id" => id, "actor" => follower_id}, followed) do
with true <- id =~ "follows",
%User{local: true} = follower <- User.get_cached_by_ap_id(follower_id),
%Activity{} = activity <- Utils.fetch_latest_follow(follower, followed) do
{:ok, activity}
else
_ -> {:error, nil}
end
end
defp mastodon_follow_hack(_, _), do: {:error, nil}
defp get_follow_activity(follow_object, followed) do
with object_id when not is_nil(object_id) <- Utils.get_ap_id(follow_object),
{_, %Activity{} = activity} <- {:activity, Activity.get_by_ap_id(object_id)} do
{:ok, activity}
else
# Can't find the activity. This might a Mastodon 2.3 "Accept"
{:activity, nil} ->
mastodon_follow_hack(follow_object, followed)
_ ->
{:error, nil}
end
end
# disallow objects with bogus IDs
def handle_incoming(%{"id" => nil}), do: :error
def handle_incoming(%{"id" => ""}), do: :error
......@@ -331,34 +357,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
end
defp mastodon_follow_hack(%{"id" => id, "actor" => follower_id}, followed) do
with true <- id =~ "follows",
%User{local: true} = follower <- User.get_cached_by_ap_id(follower_id),
%Activity{} = activity <- Utils.fetch_latest_follow(follower, followed) do
{:ok, activity}
else
_ -> {:error, nil}
end
end
defp mastodon_follow_hack(_), do: {:error, nil}
defp get_follow_activity(follow_object, followed) do
with object_id when not is_nil(object_id) <- Utils.get_ap_id(follow_object),
{_, %Activity{} = activity} <- {:activity, Activity.get_by_ap_id(object_id)} do
{:ok, activity}
else
# Can't find the activity. This might a Mastodon 2.3 "Accept"
{:activity, nil} ->
mastodon_follow_hack(follow_object, followed)
_ ->
{:error, nil}
end
end
def handle_incoming(
%{"type" => "Accept", "object" => follow_object, "actor" => actor, "id" => id} = data
%{"type" => "Accept", "object" => follow_object, "actor" => _actor, "id" => _id} = data
) do
with actor <- get_actor(data),
%User{} = followed <- User.get_or_fetch_by_ap_id(actor),
......@@ -374,7 +374,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
local: false
}) do
if not User.following?(follower, followed) do
{:ok, follower} = User.follow(follower, followed)
{:ok, _follower} = User.follow(follower, followed)
end
{:ok, activity}
......@@ -384,7 +384,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
def handle_incoming(
%{"type" => "Reject", "object" => follow_object, "actor" => actor, "id" => id} = data
%{"type" => "Reject", "object" => follow_object, "actor" => _actor, "id" => _id} = data
) do
with actor <- get_actor(data),
%User{} = followed <- User.get_or_fetch_by_ap_id(actor),
......@@ -408,7 +408,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
def handle_incoming(
%{"type" => "Like", "object" => object_id, "actor" => actor, "id" => id} = data
%{"type" => "Like", "object" => object_id, "actor" => _actor, "id" => id} = data
) do
with actor <- get_actor(data),
%User{} = actor <- User.get_or_fetch_by_ap_id(actor),
......@@ -421,7 +421,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
def handle_incoming(
%{"type" => "Announce", "object" => object_id, "actor" => actor, "id" => id} = data
%{"type" => "Announce", "object" => object_id, "actor" => _actor, "id" => id} = data
) do
with actor <- get_actor(data),
%User{} = actor <- User.get_or_fetch_by_ap_id(actor),
......@@ -492,7 +492,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
%{
"type" => "Undo",
"object" => %{"type" => "Announce", "object" => object_id},
"actor" => actor,
"actor" => _actor,
"id" => id
} = data
) do
......@@ -520,7 +520,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
User.unfollow(follower, followed)
{:ok, activity}
else
e -> :error
_e -> :error
end
end
......@@ -539,12 +539,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
User.unblock(blocker, blocked)
{:ok, activity}
else
e -> :error
_e -> :error
end
end
def handle_incoming(
%{"type" => "Block", "object" => blocked, "actor" => blocker, "id" => id} = data
%{"type" => "Block", "object" => blocked, "actor" => blocker, "id" => id} = _data
) do
with true <- Pleroma.Config.get([:activitypub, :accept_blocks]),
%User{local: true} = blocked = User.get_cached_by_ap_id(blocked),
......@@ -554,7 +554,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
User.block(blocker, blocked)
{:ok, activity}
else
e -> :error
_e -> :error
end
end
......@@ -562,7 +562,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
%{
"type" => "Undo",
"object" => %{"type" => "Like", "object" => object_id},
"actor" => actor,
"actor" => _actor,
"id" => id
} = data
) do
......
......@@ -292,7 +292,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
"""
def make_follow_data(
%User{ap_id: follower_id},
%User{ap_id: followed_id} = followed,
%User{ap_id: followed_id} = _followed,
activity_id
) do
data = %{
......
......@@ -63,13 +63,19 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
info_cng = User.Info.admin_api_update(user.info, info)
cng =
Ecto.Changeset.change(user)
user
|> Ecto.Changeset.change()
|> Ecto.Changeset.put_embed(:info, info_cng)
{:ok, user} = User.update_and_set_cache(cng)
{:ok, _user} = User.update_and_set_cache(cng)
json(conn, info)
end
def right_add(conn, _) do
conn
|> json(info)
|> put_status(404)
|> json(%{error: "No such permission_group"})
end
def right_get(conn, %{"nickname" => nickname}) do
......@@ -82,12 +88,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
})
end
def right_add(conn, _) do
conn
|> put_status(404)
|> json(%{error: "No such permission_group"})
end
def right_delete(
%{assigns: %{user: %User{:nickname => admin_nickname}}} = conn,
%{
......@@ -113,10 +113,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
Ecto.Changeset.change(user)
|> Ecto.Changeset.put_embed(:info, info_cng)
{:ok, user} = User.update_and_set_cache(cng)
{:ok, _user} = User.update_and_set_cache(cng)
conn
|> json(info)
json(conn, info)
end
end
......@@ -127,32 +126,28 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
end
def relay_follow(conn, %{"relay_url" => target}) do
{status, message} = Relay.follow(target)
if status == :ok do
conn
|> json(target)
with {:ok, _message} <- Relay.follow(target) do
json(conn, target)
else
conn
|> put_status(500)
|> json(target)
_ ->
conn
|> put_status(500)
|> json(target)
end
end
def relay_unfollow(conn, %{"relay_url" => target}) do
{status, message} = Relay.unfollow(target)
if status == :ok do
conn
|> json(target)
with {:ok, _message} <- Relay.unfollow(target) do
json(conn, target)
else
conn
|> put_status(500)
|> json(target)
_ ->
conn
|> put_status(500)
|> json(target)
end
end
@shortdoc "Get a account registeration invite token (base64 string)"
@doc "Get a account registeration invite token (base64 string)"
def get_invite_token(conn, _params) do
{:ok, token} = Pleroma.UserInviteToken.create_token()
......@@ -160,7 +155,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|> json(token.token)
end
@shortdoc "Get a password reset token (base64 string) for given nickname"
@doc "Get a password reset token (base64 string) for given nickname"
def get_password_reset(conn, %{"nickname" => nickname}) do
(%User{local: true} = user) = User.get_by_nickname(nickname)
{:ok, token} = Pleroma.PasswordResetToken.create_token(user)
......
defmodule Pleroma.Web.CommonAPI.Utils do
alias Pleroma.{Repo, Object, Formatter, Activity}
alias Calendar.Strftime
alias Comeonin.Pbkdf2
alias Pleroma.{Activity, Formatter, Object, Repo}
alias Pleroma.User
alias Pleroma.Web
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.Endpoint
alias Pleroma.Web.MediaProxy
alias Pleroma.User
alias Calendar.Strftime
alias Comeonin.Pbkdf2
# This is a hack for twidere.
def get_by_id_or_ap_id(id) do
......@@ -122,7 +123,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|> Formatter.finalize()
end
def format_input(text, mentions, tags, "text/html") do
def format_input(text, mentions, _tags, "text/html") do
text
|> Formatter.html_escape("text/html")
|> String.replace(~r/\r?\n/, "<br>")
......@@ -148,7 +149,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|> Enum.sort_by(fn {tag, _} -> -String.length(tag) end)
Enum.reduce(tags, text, fn {full, tag}, text ->
url = "<a href='#{Pleroma.Web.base_url()}/tag/#{tag}' rel='tag'>##{tag}</a>"
url = "<a href='#{Web.base_url()}/tag/#{tag}' rel='tag'>##{tag}</a>"
String.replace(text, full, url)
end)
end
......@@ -236,7 +237,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
end
end
def emoji_from_profile(%{info: info} = user) do
def emoji_from_profile(%{info: _info} = user) do
(Formatter.get_emoji(user.bio) ++ Formatter.get_emoji(user.name))
|> Enum.map(fn {shortcode, url} ->
%{
......
......@@ -13,7 +13,6 @@ defmodule Pleroma.Web.Federator do
@websub Application.get_env(:pleroma, :websub)
@ostatus Application.get_env(:pleroma, :ostatus)
@httpoison Application.get_env(:pleroma, :httpoison)
@max_jobs 20
def init(args) do
......@@ -134,7 +133,7 @@ defmodule Pleroma.Web.Federator do
def handle(
:publish_single_websub,
%{xml: xml, topic: topic, callback: callback, secret: secret} = params
%{xml: _xml, topic: _topic, callback: _callback, secret: _secret} = params
) do
case Websub.publish_one(params) do
{:ok, _} ->
......@@ -151,7 +150,7 @@ defmodule Pleroma.Web.Federator do
end
if Mix.env() == :test do
def enqueue(type, payload, priority \\ 1) do
def enqueue(type, payload, _priority \\ 1) do
if Pleroma.Config.get([:instance, :federating]) do
handle(type, payload)
end
......
defmodule Pleroma.Web.Federator.RetryQueue do
use GenServer
alias Pleroma.Web.{WebFinger, Websub}
alias Pleroma.Web.ActivityPub.ActivityPub
require Logger
@websub Application.get_env(:pleroma, :websub)
@ostatus Application.get_env(:pleroma, :websub)
@httpoison Application.get_env(:pleroma, :websub)
@instance Application.get_env(:pleroma, :websub)
# initial timeout, 5 min
@initial_timeout 30_000
@max_retries 5
......@@ -46,7 +41,7 @@ defmodule Pleroma.Web.Federator.RetryQueue do
Process.send_after(
__MODULE__,
{:send, data, transport, retries},
growth_function(retries)
timeout
)
{:noreply, state}
......@@ -62,7 +57,7 @@ defmodule Pleroma.Web.Federator.RetryQueue do
{:ok, _} ->
{:noreply, %{state | delivered: delivery_count + 1}}
{:error, reason} ->
{:error, _reason} ->
enqueue(data, transport, retries)
{:noreply, state}
end
......
......@@ -437,10 +437,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
# Instead of returning a 400 when no "id" params is present, Mastodon returns an empty array.
def relationships(%{assigns: %{user: user}} = conn, _) do
conn
|> json([])
end
def relationships(%{assigns: %{user: _user}} = conn, _), do: json(conn, [])
def update_media(%{assigns: %{user: user}} = conn, data) do
with %Object{} = object <- Repo.get(Object, data["id"]),
......@@ -850,7 +847,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
def list_timeline(%{assigns: %{user: user}} = conn, %{"list_id" => id} = params) do
with %Pleroma.List{title: title, following: following} <- Pleroma.List.get(id, user) do
with %Pleroma.List{title: _title, following: following} <- Pleroma.List.get(id, user) do
params =
params
|> Map.put("type", "Create")
......@@ -983,13 +980,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
with changeset <- User.update_changeset(user),
changeset <- Ecto.Changeset.put_embed(changeset, :info, info_cng),
{:ok, user} <- User.update_and_set_cache(changeset) do
conn
|> json(%{})
{:ok, _user} <- User.update_and_set_cache(changeset) do
json(conn, %{})
else
e ->
conn
|> json(%{error: inspect(e)})
json(conn, %{error: inspect(e)})
end
end
......
......@@ -5,12 +5,13 @@ defmodule Pleroma.Web.MastodonAPI.MastodonSocket do
alias Pleroma.{User, Repo}
transport(
:streaming,
:websocket,
Phoenix.Transports.WebSocket.Raw,
# We never receive data.
timeout: :infinity
)
@spec connect(params :: map(), Phoenix.Socket.t()) :: {:ok, Phoenix.Socket.t()} | :error
def connect(%{"access_token" => token} = params, socket) do
with %Token{user_id: user_id} <- Repo.get_by(Token, token: token),
%User{} = user <- Repo.get(User, user_id),
......@@ -52,16 +53,16 @@ defmodule Pleroma.Web.MastodonAPI.MastodonSocket do
_ -> stream
end
with socket =
socket
|> assign(:topic, topic) do
Pleroma.Web.Streamer.add_socket(topic, socket)
{:ok, socket}
else
_e -> :error
end
socket =
socket
|> assign(:topic, topic)
Pleroma.Web.Streamer.add_socket(topic, socket)
{:ok, socket}
end