aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/mix/pleroma.ex (renamed from lib/mix/tasks/pleroma/common.ex)8
-rw-r--r--lib/mix/tasks/pleroma/benchmark.ex (renamed from lib/mix/tasks/benchmark.ex)6
-rw-r--r--lib/mix/tasks/pleroma/config.ex9
-rw-r--r--lib/mix/tasks/pleroma/database.ex10
-rw-r--r--lib/mix/tasks/pleroma/ecto/ecto.ex11
-rw-r--r--lib/mix/tasks/pleroma/ecto/migrate.ex2
-rw-r--r--lib/mix/tasks/pleroma/ecto/rollback.ex2
-rw-r--r--lib/mix/tasks/pleroma/instance.ex80
-rw-r--r--lib/mix/tasks/pleroma/relay.ex10
-rw-r--r--lib/mix/tasks/pleroma/robots_txt.eex2
-rw-r--r--lib/mix/tasks/pleroma/sample_config.eex79
-rw-r--r--lib/mix/tasks/pleroma/sample_psql.eex7
-rw-r--r--lib/mix/tasks/pleroma/uploads.ex16
-rw-r--r--lib/mix/tasks/pleroma/user.ex100
-rw-r--r--lib/pleroma/notification.ex10
-rw-r--r--lib/pleroma/release_tasks.ex3
-rw-r--r--lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex48
-rw-r--r--lib/pleroma/web/oauth/oauth_controller.ex46
-rw-r--r--lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex33
19 files changed, 244 insertions, 238 deletions
diff --git a/lib/mix/tasks/pleroma/common.ex b/lib/mix/pleroma.ex
index 7d50605af..1b758ea33 100644
--- a/lib/mix/tasks/pleroma/common.ex
+++ b/lib/mix/pleroma.ex
@@ -2,19 +2,23 @@
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
-defmodule Mix.Tasks.Pleroma.Common do
+defmodule Mix.Pleroma do
@doc "Common functions to be reused in mix tasks"
def start_pleroma do
Application.put_env(:phoenix, :serve_endpoints, false, persistent: true)
{:ok, _} = Application.ensure_all_started(:pleroma)
end
+ def load_pleroma do
+ Application.load(:pleroma)
+ end
+
def get_option(options, opt, prompt, defval \\ nil, defname \\ nil) do
Keyword.get(options, opt) || shell_prompt(prompt, defval, defname)
end
def shell_prompt(prompt, defval \\ nil, defname \\ nil) do
- prompt_message = "#{prompt} [#{defname || defval}]"
+ prompt_message = "#{prompt} [#{defname || defval}] "
input =
if mix_shell?(),
diff --git a/lib/mix/tasks/benchmark.ex b/lib/mix/tasks/pleroma/benchmark.ex
index e4b1a638a..d43db7b35 100644
--- a/lib/mix/tasks/benchmark.ex
+++ b/lib/mix/tasks/pleroma/benchmark.ex
@@ -1,9 +1,9 @@
defmodule Mix.Tasks.Pleroma.Benchmark do
+ import Mix.Pleroma
use Mix.Task
- alias Mix.Tasks.Pleroma.Common
def run(["search"]) do
- Common.start_pleroma()
+ start_pleroma()
Benchee.run(%{
"search" => fn ->
@@ -13,7 +13,7 @@ defmodule Mix.Tasks.Pleroma.Benchmark do
end
def run(["tag"]) do
- Common.start_pleroma()
+ start_pleroma()
Benchee.run(%{
"tag" => fn ->
diff --git a/lib/mix/tasks/pleroma/config.ex b/lib/mix/tasks/pleroma/config.ex
index 1fe03088d..cc5425362 100644
--- a/lib/mix/tasks/pleroma/config.ex
+++ b/lib/mix/tasks/pleroma/config.ex
@@ -1,6 +1,6 @@
defmodule Mix.Tasks.Pleroma.Config do
use Mix.Task
- alias Mix.Tasks.Pleroma.Common
+ import Mix.Pleroma
alias Pleroma.Repo
alias Pleroma.Web.AdminAPI.Config
@shortdoc "Manages the location of the config"
@@ -17,7 +17,7 @@ defmodule Mix.Tasks.Pleroma.Config do
"""
def run(["migrate_to_db"]) do
- Common.start_pleroma()
+ start_pleroma()
if Pleroma.Config.get([:instance, :dynamic_configuration]) do
Application.get_all_env(:pleroma)
@@ -37,12 +37,13 @@ defmodule Mix.Tasks.Pleroma.Config do
end
def run(["migrate_from_db", env]) do
- Common.start_pleroma()
+ start_pleroma()
if Pleroma.Config.get([:instance, :dynamic_configuration]) do
- config_path = "config/#{env}.migrated.secret.exs"
+ config_path = "config/#{env}.exported_from_db.secret.exs"
{:ok, file} = File.open(config_path, [:write])
+ IO.write(file, "use Mix.Config\r\n")
Repo.all(Config)
|> Enum.each(fn config ->
diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex
index 4d480ac3f..e91fb31d1 100644
--- a/lib/mix/tasks/pleroma/database.ex
+++ b/lib/mix/tasks/pleroma/database.ex
@@ -3,12 +3,12 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Mix.Tasks.Pleroma.Database do
- alias Mix.Tasks.Pleroma.Common
alias Pleroma.Conversation
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
require Logger
+ import Mix.Pleroma
use Mix.Task
@shortdoc "A collection of database related tasks"
@@ -45,7 +45,7 @@ defmodule Mix.Tasks.Pleroma.Database do
]
)
- Common.start_pleroma()
+ start_pleroma()
Logger.info("Removing embedded objects")
Repo.query!(
@@ -66,12 +66,12 @@ defmodule Mix.Tasks.Pleroma.Database do
end
def run(["bump_all_conversations"]) do
- Common.start_pleroma()
+ start_pleroma()
Conversation.bump_for_all_activities()
end
def run(["update_users_following_followers_counts"]) do
- Common.start_pleroma()
+ start_pleroma()
users = Repo.all(User)
Enum.each(users, &User.remove_duplicated_following/1)
@@ -89,7 +89,7 @@ defmodule Mix.Tasks.Pleroma.Database do
]
)
- Common.start_pleroma()
+ start_pleroma()
deadline = Pleroma.Config.get([:instance, :remote_post_retention_days])
diff --git a/lib/mix/tasks/pleroma/ecto/ecto.ex b/lib/mix/tasks/pleroma/ecto/ecto.ex
index af09cb289..324f57fdd 100644
--- a/lib/mix/tasks/pleroma/ecto/ecto.ex
+++ b/lib/mix/tasks/pleroma/ecto/ecto.ex
@@ -9,6 +9,15 @@ defmodule Mix.Tasks.Pleroma.Ecto do
def ensure_migrations_path(repo, opts) do
path = opts[:migrations_path] || Path.join(source_repo_priv(repo), "migrations")
+ path =
+ case Path.type(path) do
+ :relative ->
+ Path.join(Application.app_dir(:pleroma), path)
+
+ :absolute ->
+ path
+ end
+
if not File.dir?(path) do
raise_missing_migrations(Path.relative_to_cwd(path), repo)
end
@@ -22,7 +31,7 @@ defmodule Mix.Tasks.Pleroma.Ecto do
def source_repo_priv(repo) do
config = repo.config()
priv = config[:priv] || "priv/#{repo |> Module.split() |> List.last() |> Macro.underscore()}"
- Path.join(File.cwd!(), priv)
+ Path.join(Application.app_dir(:pleroma), priv)
end
defp raise_missing_migrations(path, repo) do
diff --git a/lib/mix/tasks/pleroma/ecto/migrate.ex b/lib/mix/tasks/pleroma/ecto/migrate.ex
index 22eafe76f..855c977f6 100644
--- a/lib/mix/tasks/pleroma/ecto/migrate.ex
+++ b/lib/mix/tasks/pleroma/ecto/migrate.ex
@@ -4,6 +4,7 @@
defmodule Mix.Tasks.Pleroma.Ecto.Migrate do
use Mix.Task
+ import Mix.Pleroma
require Logger
@shortdoc "Wrapper on `ecto.migrate` task."
@@ -37,6 +38,7 @@ defmodule Mix.Tasks.Pleroma.Ecto.Migrate do
@impl true
def run(args \\ []) do
+ load_pleroma()
{opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases)
opts =
diff --git a/lib/mix/tasks/pleroma/ecto/rollback.ex b/lib/mix/tasks/pleroma/ecto/rollback.ex
index 0033ceba4..2ffb0901c 100644
--- a/lib/mix/tasks/pleroma/ecto/rollback.ex
+++ b/lib/mix/tasks/pleroma/ecto/rollback.ex
@@ -4,6 +4,7 @@
defmodule Mix.Tasks.Pleroma.Ecto.Rollback do
use Mix.Task
+ import Mix.Pleroma
require Logger
@shortdoc "Wrapper on `ecto.rollback` task"
@@ -36,6 +37,7 @@ defmodule Mix.Tasks.Pleroma.Ecto.Rollback do
@impl true
def run(args \\ []) do
+ load_pleroma()
{opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases)
opts =
diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex
index 44e49cb69..c6738dbcc 100644
--- a/lib/mix/tasks/pleroma/instance.ex
+++ b/lib/mix/tasks/pleroma/instance.ex
@@ -4,7 +4,7 @@
defmodule Mix.Tasks.Pleroma.Instance do
use Mix.Task
- alias Mix.Tasks.Pleroma.Common
+ import Mix.Pleroma
@shortdoc "Manages Pleroma instance"
@moduledoc """
@@ -31,6 +31,8 @@ defmodule Mix.Tasks.Pleroma.Instance do
- `--dbpass DBPASS` - the password to use for the database connection
- `--indexable Y/N` - Allow/disallow indexing site by search engines
- `--db-configurable Y/N` - Allow/disallow configuring instance from admin part
+ - `--uploads-dir` - the directory uploads go in when using a local uploader
+ - `--static-dir` - the directory custom public files should be read from (custom emojis, frontend bundle overrides, robots.txt, etc.)
"""
def run(["gen" | rest]) do
@@ -50,7 +52,9 @@ defmodule Mix.Tasks.Pleroma.Instance do
dbuser: :string,
dbpass: :string,
indexable: :string,
- db_configurable: :string
+ db_configurable: :string,
+ uploads_dir: :string,
+ static_dir: :string
],
aliases: [
o: :output,
@@ -70,7 +74,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
if proceed? do
[domain, port | _] =
String.split(
- Common.get_option(
+ get_option(
options,
:domain,
"What domain will your instance use? (e.g pleroma.soykaf.com)"
@@ -79,16 +83,16 @@ defmodule Mix.Tasks.Pleroma.Instance do
) ++ [443]
name =
- Common.get_option(
+ get_option(
options,
:instance_name,
"What is the name of your instance? (e.g. Pleroma/Soykaf)"
)
- email = Common.get_option(options, :admin_email, "What is your admin email address?")
+ email = get_option(options, :admin_email, "What is your admin email address?")
notify_email =
- Common.get_option(
+ get_option(
options,
:notify_email,
"What email address do you want to use for sending email notifications?",
@@ -96,7 +100,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
)
indexable =
- Common.get_option(
+ get_option(
options,
:indexable,
"Do you want search engines to index your site? (y/n)",
@@ -104,21 +108,19 @@ defmodule Mix.Tasks.Pleroma.Instance do
) === "y"
db_configurable? =
- Common.get_option(
+ get_option(
options,
:db_configurable,
- "Do you want to be able to configure instance from admin part? (y/n)",
+ "Do you want to store the configuration in the database (allows controlling it from admin-fe)? (y/n)",
"y"
) === "y"
- dbhost =
- Common.get_option(options, :dbhost, "What is the hostname of your database?", "localhost")
+ dbhost = get_option(options, :dbhost, "What is the hostname of your database?", "localhost")
- dbname =
- Common.get_option(options, :dbname, "What is the name of your database?", "pleroma_dev")
+ dbname = get_option(options, :dbname, "What is the name of your database?", "pleroma_dev")
dbuser =
- Common.get_option(
+ get_option(
options,
:dbuser,
"What is the user used to connect to your database?",
@@ -126,7 +128,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
)
dbpass =
- Common.get_option(
+ get_option(
options,
:dbpass,
"What is the password used to connect to your database?",
@@ -134,13 +136,30 @@ defmodule Mix.Tasks.Pleroma.Instance do
"autogenerated"
)
+ uploads_dir =
+ get_option(
+ options,
+ :upload_dir,
+ "What directory should media uploads go in (when using the local uploader)?",
+ Pleroma.Config.get([Pleroma.Uploaders.Local, :uploads])
+ )
+
+ static_dir =
+ get_option(
+ options,
+ :static_dir,
+ "What directory should custom public files be read from (custom emojis, frontend bundle overrides, robots.txt, etc.)?",
+ Pleroma.Config.get([:instance, :static_dir])
+ )
+
secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
signing_salt = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8)
{web_push_public_key, web_push_private_key} = :crypto.generate_key(:ecdh, :prime256v1)
+ template_dir = Application.app_dir(:pleroma, "priv") <> "/templates"
result_config =
EEx.eval_file(
- "sample_config.eex" |> Path.expand(__DIR__),
+ template_dir <> "/sample_config.eex",
domain: domain,
port: port,
email: email,
@@ -150,47 +169,48 @@ defmodule Mix.Tasks.Pleroma.Instance do
dbname: dbname,
dbuser: dbuser,
dbpass: dbpass,
- version: Pleroma.Mixfile.project() |> Keyword.get(:version),
secret: secret,
signing_salt: signing_salt,
web_push_public_key: Base.url_encode64(web_push_public_key, padding: false),
web_push_private_key: Base.url_encode64(web_push_private_key, padding: false),
- db_configurable?: db_configurable?
+ db_configurable?: db_configurable?,
+ static_dir: static_dir,
+ uploads_dir: uploads_dir
)
result_psql =
EEx.eval_file(
- "sample_psql.eex" |> Path.expand(__DIR__),
+ template_dir <> "/sample_psql.eex",
dbname: dbname,
dbuser: dbuser,
dbpass: dbpass
)
- Common.shell_info(
+ shell_info(
"Writing config to #{config_path}. You should rename it to config/prod.secret.exs or config/dev.secret.exs."
)
File.write(config_path, result_config)
- Common.shell_info("Writing #{psql_path}.")
+ shell_info("Writing #{psql_path}.")
File.write(psql_path, result_psql)
- write_robots_txt(indexable)
+ write_robots_txt(indexable, template_dir)
- Common.shell_info(
+ shell_info(
"\n" <>
"""
To get started:
1. Verify the contents of the generated files.
- 2. Run `sudo -u postgres psql -f #{Common.escape_sh_path(psql_path)}`.
+ 2. Run `sudo -u postgres psql -f #{escape_sh_path(psql_path)}`.
""" <>
if config_path in ["config/dev.secret.exs", "config/prod.secret.exs"] do
""
else
- "3. Run `mv #{Common.escape_sh_path(config_path)} 'config/prod.secret.exs'`."
+ "3. Run `mv #{escape_sh_path(config_path)} 'config/prod.secret.exs'`."
end
)
else
- Common.shell_error(
+ shell_error(
"The task would have overwritten the following files:\n" <>
(Enum.map(paths, &"- #{&1}\n") |> Enum.join("")) <>
"Rerun with `--force` to overwrite them."
@@ -198,10 +218,10 @@ defmodule Mix.Tasks.Pleroma.Instance do
end
end
- defp write_robots_txt(indexable) do
+ defp write_robots_txt(indexable, template_dir) do
robots_txt =
EEx.eval_file(
- Path.expand("robots_txt.eex", __DIR__),
+ template_dir <> "/robots_txt.eex",
indexable: indexable
)
@@ -215,10 +235,10 @@ defmodule Mix.Tasks.Pleroma.Instance do
if File.exists?(robots_txt_path) do
File.cp!(robots_txt_path, "#{robots_txt_path}.bak")
- Common.shell_info("Backing up existing robots.txt to #{robots_txt_path}.bak")
+ shell_info("Backing up existing robots.txt to #{robots_txt_path}.bak")
end
File.write(robots_txt_path, robots_txt)
- Common.shell_info("Writing #{robots_txt_path}.")
+ shell_info("Writing #{robots_txt_path}.")
end
end
diff --git a/lib/mix/tasks/pleroma/relay.ex b/lib/mix/tasks/pleroma/relay.ex
index 213ae24d2..83ed0ed02 100644
--- a/lib/mix/tasks/pleroma/relay.ex
+++ b/lib/mix/tasks/pleroma/relay.ex
@@ -4,7 +4,7 @@
defmodule Mix.Tasks.Pleroma.Relay do
use Mix.Task
- alias Mix.Tasks.Pleroma.Common
+ import Mix.Pleroma
alias Pleroma.Web.ActivityPub.Relay
@shortdoc "Manages remote relays"
@@ -24,24 +24,24 @@ defmodule Mix.Tasks.Pleroma.Relay do
Example: ``mix pleroma.relay unfollow https://example.org/relay``
"""
def run(["follow", target]) do
- Common.start_pleroma()
+ start_pleroma()
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
- {:error, e} -> Common.shell_error("Error while following #{target}: #{inspect(e)}")
+ {:error, e} -> shell_error("Error while following #{target}: #{inspect(e)}")
end
end
def run(["unfollow", target]) do
- Common.start_pleroma()
+ start_pleroma()
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
- {:error, e} -> Common.shell_error("Error while following #{target}: #{inspect(e)}")
+ {:error, e} -> shell_error("Error while following #{target}: #{inspect(e)}")
end
end
end
diff --git a/lib/mix/tasks/pleroma/robots_txt.eex b/lib/mix/tasks/pleroma/robots_txt.eex
deleted file mode 100644
index 1af3c47ee..000000000
--- a/lib/mix/tasks/pleroma/robots_txt.eex
+++ /dev/null
@@ -1,2 +0,0 @@
-User-Agent: *
-Disallow: <%= if indexable, do: "", else: "/" %>
diff --git a/lib/mix/tasks/pleroma/sample_config.eex b/lib/mix/tasks/pleroma/sample_config.eex
deleted file mode 100644
index 73d9217be..000000000
--- a/lib/mix/tasks/pleroma/sample_config.eex
+++ /dev/null
@@ -1,79 +0,0 @@
-# Pleroma instance configuration
-
-# NOTE: This file should not be committed to a repo or otherwise made public
-# without removing sensitive information.
-
-use Mix.Config
-
-config :pleroma, Pleroma.Web.Endpoint,
- url: [host: "<%= domain %>", scheme: "https", port: <%= port %>],
- secret_key_base: "<%= secret %>",
- signing_salt: "<%= signing_salt %>"
-
-config :pleroma, :instance,
- name: "<%= name %>",
- email: "<%= email %>",
- notify_email: "<%= notify_email %>",
- limit: 5000,
- registrations_open: true,
- dedupe_media: false,
- dynamic_configuration: <%= db_configurable? %>
-
-config :pleroma, :media_proxy,
- enabled: false,
- redirect_on_failure: true
- #base_url: "https://cache.pleroma.social"
-
-config :pleroma, Pleroma.Repo,
- adapter: Ecto.Adapters.Postgres,
- username: "<%= dbuser %>",
- password: "<%= dbpass %>",
- database: "<%= dbname %>",
- hostname: "<%= dbhost %>",
- pool_size: 10
-
-# Configure web push notifications
-config :web_push_encryption, :vapid_details,
- subject: "mailto:<%= email %>",
- public_key: "<%= web_push_public_key %>",
- private_key: "<%= web_push_private_key %>"
-
-# Enable Strict-Transport-Security once SSL is working:
-# config :pleroma, :http_security,
-# sts: true
-
-# Configure S3 support if desired.
-# The public S3 endpoint is different depending on region and provider,
-# consult your S3 provider's documentation for details on what to use.
-#
-# config :pleroma, Pleroma.Uploaders.S3,
-# bucket: "some-bucket",
-# public_endpoint: "https://s3.amazonaws.com"
-#
-# Configure S3 credentials:
-# config :ex_aws, :s3,
-# access_key_id: "xxxxxxxxxxxxx",
-# secret_access_key: "yyyyyyyyyyyy",
-# region: "us-east-1",
-# scheme: "https://"
-#
-# For using third-party S3 clones like wasabi, also do:
-# config :ex_aws, :s3,
-# host: "s3.wasabisys.com"
-
-
-# Configure Openstack Swift support if desired.
-#
-# Many openstack deployments are different, so config is left very open with
-# no assumptions made on which provider you're using. This should allow very
-# wide support without needing separate handlers for OVH, Rackspace, etc.
-#
-# config :pleroma, Pleroma.Uploaders.Swift,
-# container: "some-container",
-# username: "api-username-yyyy",
-# password: "api-key-xxxx",
-# tenant_id: "<openstack-project/tenant-id>",
-# auth_url: "https://keystone-endpoint.provider.com",
-# storage_url: "https://swift-endpoint.prodider.com/v1/AUTH_<tenant>/<container>",
-# object_url: "https://cdn-endpoint.provider.com/<container>"
-#
diff --git a/lib/mix/tasks/pleroma/sample_psql.eex b/lib/mix/tasks/pleroma/sample_psql.eex
deleted file mode 100644
index f0ac05e57..000000000
--- a/lib/mix/tasks/pleroma/sample_psql.eex
+++ /dev/null
@@ -1,7 +0,0 @@
-CREATE USER <%= dbuser %> WITH ENCRYPTED PASSWORD '<%= dbpass %>';
-CREATE DATABASE <%= dbname %> OWNER <%= dbuser %>;
-\c <%= dbname %>;
---Extensions made by ecto.migrate that need superuser access
-CREATE EXTENSION IF NOT EXISTS citext;
-CREATE EXTENSION IF NOT EXISTS pg_trgm;
-CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
diff --git a/lib/mix/tasks/pleroma/uploads.ex b/lib/mix/tasks/pleroma/uploads.ex
index 8855b5538..be45383ee 100644
--- a/lib/mix/tasks/pleroma/uploads.ex
+++ b/lib/mix/tasks/pleroma/uploads.ex
@@ -4,7 +4,7 @@
defmodule Mix.Tasks.Pleroma.Uploads do
use Mix.Task
- alias Mix.Tasks.Pleroma.Common
+ import Mix.Pleroma
alias Pleroma.Upload
alias Pleroma.Uploaders.Local
require Logger
@@ -24,7 +24,7 @@ defmodule Mix.Tasks.Pleroma.Uploads do
"""
def run(["migrate_local", target_uploader | args]) do
delete? = Enum.member?(args, "--delete")
- Common.start_pleroma()
+ start_pleroma()
local_path = Pleroma.Config.get!([Local, :uploads])
uploader = Module.concat(Pleroma.Uploaders, target_uploader)
@@ -38,10 +38,10 @@ defmodule Mix.Tasks.Pleroma.Uploads do
Pleroma.Config.put([Upload, :uploader], uploader)
end
- Common.shell_info("Migrating files from local #{local_path} to #{to_string(uploader)}")
+ shell_info("Migrating files from local #{local_path} to #{to_string(uploader)}")
if delete? do
- Common.shell_info(
+ shell_info(
"Attention: uploaded files will be deleted, hope you have backups! (--delete ; cancel with ^C)"
)
@@ -78,7 +78,7 @@ defmodule Mix.Tasks.Pleroma.Uploads do
|> Enum.filter(& &1)
total_count = length(uploads)
- Common.shell_info("Found #{total_count} uploads")
+ shell_info("Found #{total_count} uploads")
uploads
|> Task.async_stream(
@@ -90,7 +90,7 @@ defmodule Mix.Tasks.Pleroma.Uploads do
:ok
error ->
- Common.shell_error("failed to upload #{inspect(upload.path)}: #{inspect(error)}")
+ shell_error("failed to upload #{inspect(upload.path)}: #{inspect(error)}")
end
end,
timeout: 150_000
@@ -99,10 +99,10 @@ defmodule Mix.Tasks.Pleroma.Uploads do
# credo:disable-for-next-line Credo.Check.Warning.UnusedEnumOperation
|> Enum.reduce(0, fn done, count ->
count = count + length(done)
- Common.shell_info("Uploaded #{count}/#{total_count} files")
+ shell_info("Uploaded #{count}/#{total_count} files")
count
end)
- Common.shell_info("Done!")
+ shell_info("Done!")
end
end
diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex
index 0efa745e4..ab158f57e 100644
--- a/lib/mix/tasks/pleroma/user.ex
+++ b/lib/mix/tasks/pleroma/user.ex
@@ -5,7 +5,7 @@
defmodule Mix.Tasks.Pleroma.User do
use Mix.Task
import Ecto.Changeset
- alias Mix.Tasks.Pleroma.Common
+ import Mix.Pleroma
alias Pleroma.User
alias Pleroma.UserInviteToken
alias Pleroma.Web.OAuth
@@ -120,7 +120,7 @@ defmodule Mix.Tasks.Pleroma.User do
admin? = Keyword.get(options, :admin, false)
assume_yes? = Keyword.get(options, :assume_yes, false)
- Common.shell_info("""
+ shell_info("""
A user will be created with the following information:
- nickname: #{nickname}
- email: #{email}
@@ -133,10 +133,10 @@ defmodule Mix.Tasks.Pleroma.User do
- admin: #{if(admin?, do: "true", else: "false")}
""")
- proceed? = assume_yes? or Common.shell_yes?("Continue?")
+ proceed? = assume_yes? or shell_yes?("Continue?")
if proceed? do
- Common.start_pleroma()
+ start_pleroma()
params = %{
nickname: nickname,
@@ -150,7 +150,7 @@ defmodule Mix.Tasks.Pleroma.User do
changeset = User.register_changeset(%User{}, params, need_confirmation: false)
{:ok, _user} = User.register(changeset)
- Common.shell_info("User #{nickname} created")
+ shell_info("User #{nickname} created")
if moderator? do
run(["set", nickname, "--moderator"])
@@ -164,43 +164,43 @@ defmodule Mix.Tasks.Pleroma.User do
run(["reset_password", nickname])
end
else
- Common.shell_info("User will not be created.")
+ shell_info("User will not be created.")
end
end
def run(["rm", nickname]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
User.perform(:delete, user)
- Common.shell_info("User #{nickname} deleted.")
+ shell_info("User #{nickname} deleted.")
else
_ ->
- Common.shell_error("No local user #{nickname}")
+ shell_error("No local user #{nickname}")
end
end
def run(["toggle_activated", nickname]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{} = user <- User.get_cached_by_nickname(nickname) do
{:ok, user} = User.deactivate(user, !user.info.deactivated)
- Common.shell_info(
+ shell_info(
"Activation status of #{nickname}: #{if(user.info.deactivated, do: "de", else: "")}activated"
)
else
_ ->
- Common.shell_error("No user #{nickname}")
+ shell_error("No user #{nickname}")
end
end
def run(["reset_password", nickname]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{local: true} = user <- User.get_cached_by_nickname(nickname),
{:ok, token} <- Pleroma.PasswordResetToken.create_token(user) do
- Common.shell_info("Generated password reset token for #{user.nickname}")
+ shell_info("Generated password reset token for #{user.nickname}")
IO.puts(
"URL: #{
@@ -213,15 +213,15 @@ defmodule Mix.Tasks.Pleroma.User do
)
else
_ ->
- Common.shell_error("No local user #{nickname}")
+ shell_error("No local user #{nickname}")
end
end
def run(["unsubscribe", nickname]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{} = user <- User.get_cached_by_nickname(nickname) do
- Common.shell_info("Deactivating #{user.nickname}")
+ shell_info("Deactivating #{user.nickname}")
User.deactivate(user)
{:ok, friends} = User.get_friends(user)
@@ -229,7 +229,7 @@ defmodule Mix.Tasks.Pleroma.User do
Enum.each(friends, fn friend ->
user = User.get_cached_by_id(user.id)
- Common.shell_info("Unsubscribing #{friend.nickname} from #{user.nickname}")
+ shell_info("Unsubscribing #{friend.nickname} from #{user.nickname}")
User.unfollow(user, friend)
end)
@@ -238,16 +238,16 @@ defmodule Mix.Tasks.Pleroma.User do
user = User.get_cached_by_id(user.id)
if Enum.empty?(user.following) do
- Common.shell_info("Successfully unsubscribed all followers from #{user.nickname}")
+ shell_info("Successfully unsubscribed all followers from #{user.nickname}")
end
else
_ ->
- Common.shell_error("No user #{nickname}")
+ shell_error("No user #{nickname}")
end
end
def run(["set", nickname | rest]) do
- Common.start_pleroma()
+ start_pleroma()
{options, [], []} =
OptionParser.parse(
@@ -279,33 +279,33 @@ defmodule Mix.Tasks.Pleroma.User do
end
else
_ ->
- Common.shell_error("No local user #{nickname}")
+ shell_error("No local user #{nickname}")
end
end
def run(["tag", nickname | tags]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{} = user <- User.get_cached_by_nickname(nickname) do
user = user |> User.tag(tags)
- Common.shell_info("Tags of #{user.nickname}: #{inspect(tags)}")
+ shell_info("Tags of #{user.nickname}: #{inspect(tags)}")
else
_ ->
- Common.shell_error("Could not change user tags for #{nickname}")
+ shell_error("Could not change user tags for #{nickname}")
end
end
def run(["untag", nickname | tags]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{} = user <- User.get_cached_by_nickname(nickname) do
user = user |> User.untag(tags)
- Common.shell_info("Tags of #{user.nickname}: #{inspect(tags)}")
+ shell_info("Tags of #{user.nickname}: #{inspect(tags)}")
else
_ ->
- Common.shell_error("Could not change user tags for #{nickname}")
+ shell_error("Could not change user tags for #{nickname}")
end
end
@@ -326,14 +326,12 @@ defmodule Mix.Tasks.Pleroma.User do
end)
|> Enum.into(%{})
- Common.start_pleroma()
+ start_pleroma()
with {:ok, val} <- options[:expires_at],
options = Map.put(options, :expires_at, val),
{:ok, invite} <- UserInviteToken.create_invite(options) do
- Common.shell_info(
- "Generated user invite token " <> String.replace(invite.invite_type, "_", " ")
- )
+ shell_info("Generated user invite token " <> String.replace(invite.invite_type, "_", " "))
url =
Pleroma.Web.Router.Helpers.redirect_url(
@@ -345,14 +343,14 @@ defmodule Mix.Tasks.Pleroma.User do
IO.puts(url)
else
error ->
- Common.shell_error("Could not create invite token: #{inspect(error)}")
+ shell_error("Could not create invite token: #{inspect(error)}")
end
end
def run(["invites"]) do
- Common.start_pleroma()
+ start_pleroma()
- Common.shell_info("Invites list:")
+ shell_info("Invites list:")
UserInviteToken.list_invites()
|> Enum.each(fn invite ->
@@ -366,7 +364,7 @@ defmodule Mix.Tasks.Pleroma.User do
" | Max use: #{max_use} Left use: #{max_use - invite.uses}"
end
- Common.shell_info(
+ shell_info(
"ID: #{invite.id} | Token: #{invite.token} | Token type: #{invite.invite_type} | Used: #{
invite.used
}#{expire_info}#{using_info}"
@@ -375,54 +373,54 @@ defmodule Mix.Tasks.Pleroma.User do
end
def run(["revoke_invite", token]) do
- Common.start_pleroma()
+ start_pleroma()
with {:ok, invite} <- UserInviteToken.find_by_token(token),
{:ok, _} <- UserInviteToken.update_invite(invite, %{used: true}) do
- Common.shell_info("Invite for token #{token} was revoked.")
+ shell_info("Invite for token #{token} was revoked.")
else
- _ -> Common.shell_error("No invite found with token #{token}")
+ _ -> shell_error("No invite found with token #{token}")
end
end
def run(["delete_activities", nickname]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
{:ok, _} = User.delete_user_activities(user)
- Common.shell_info("User #{nickname} statuses deleted.")
+ shell_info("User #{nickname} statuses deleted.")
else
_ ->
- Common.shell_error("No local user #{nickname}")
+ shell_error("No local user #{nickname}")
end
end
def run(["toggle_confirmed", nickname]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{} = user <- User.get_cached_by_nickname(nickname) do
{:ok, user} = User.toggle_confirmation(user)
message = if user.info.confirmation_pending, do: "needs", else: "doesn't need"
- Common.shell_info("#{nickname} #{message} confirmation.")
+ shell_info("#{nickname} #{message} confirmation.")
else
_ ->
- Common.shell_error("No local user #{nickname}")
+ shell_error("No local user #{nickname}")
end
end
def run(["sign_out", nickname]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
OAuth.Token.delete_user_tokens(user)
OAuth.Authorization.delete_user_authorizations(user)
- Common.shell_info("#{nickname} signed out from all apps.")
+ shell_info("#{nickname} signed out from all apps.")
else
_ ->
- Common.shell_error("No local user #{nickname}")
+ shell_error("No local user #{nickname}")
end
end
@@ -435,7 +433,7 @@ defmodule Mix.Tasks.Pleroma.User do
{:ok, user} = User.update_and_set_cache(user_cng)
- Common.shell_info("Moderator status of #{user.nickname}: #{user.info.is_moderator}")
+ shell_info("Moderator status of #{user.nickname}: #{user.info.is_moderator}")
user
end
@@ -448,7 +446,7 @@ defmodule Mix.Tasks.Pleroma.User do
{:ok, user} = User.update_and_set_cache(user_cng)
- Common.shell_info("Admin status of #{user.nickname}: #{user.info.is_admin}")
+ shell_info("Admin status of #{user.nickname}: #{user.info.is_admin}")
user
end
@@ -461,7 +459,7 @@ defmodule Mix.Tasks.Pleroma.User do
{:ok, user} = User.update_and_set_cache(user_cng)
- Common.shell_info("Locked status of #{user.nickname}: #{user.info.locked}")
+ shell_info("Locked status of #{user.nickname}: #{user.info.locked}")
user
end
end
diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex
index e25692006..a414afbbf 100644
--- a/lib/pleroma/notification.ex
+++ b/lib/pleroma/notification.ex
@@ -127,8 +127,7 @@ defmodule Pleroma.Notification do
end
end
- def create_notifications(%Activity{data: %{"to" => _, "type" => type}} = activity)
- when type in ["Create", "Like", "Announce", "Follow"] do
+ def create_notifications(%Activity{data: %{"to" => _, "type" => "Create"}} = activity) do
object = Object.normalize(activity)
unless object && object.data["type"] == "Answer" do
@@ -140,6 +139,13 @@ defmodule Pleroma.Notification do
end
end
+ def create_notifications(%Activity{data: %{"to" => _, "type" => type}} = activity)
+ when type in ["Like", "Announce", "Follow"] do
+ users = get_notified_from_activity(activity)
+ notifications = Enum.map(users, fn user -> create_notification(activity, user) end)
+ {:ok, notifications}
+ end
+
def create_notifications(_), do: {:ok, []}
# TODO move to sql, too.
diff --git a/lib/pleroma/release_tasks.ex b/lib/pleroma/release_tasks.ex
index eb6eff61c..8afabf463 100644
--- a/lib/pleroma/release_tasks.ex
+++ b/lib/pleroma/release_tasks.ex
@@ -17,6 +17,7 @@ defmodule Pleroma.ReleaseTasks do
end
defp mix_task(task, args) do
+ Application.load(:pleroma)
{:ok, modules} = :application.get_key(:pleroma, :modules)
module =
@@ -43,6 +44,8 @@ defmodule Pleroma.ReleaseTasks do
end
def create do
+ Application.load(:pleroma)
+
case @repo.__adapter__.storage_up(@repo.config) do
:ok ->
IO.puts("The database for #{inspect(@repo)} has been created")
diff --git a/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
new file mode 100644
index 000000000..2da3eac2f
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
@@ -0,0 +1,48 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
+ alias Pleroma.User
+
+ require Logger
+
+ # has the user successfully posted before?
+ defp old_user?(%User{} = u) do
+ u.info.note_count > 0 || u.info.follower_count > 0
+ end
+
+ # does the post contain links?
+ defp contains_links?(%{"content" => content} = _object) do
+ content
+ |> Floki.filter_out("a.mention,a.hashtag,a[rel~=\"tag\"],a.zrl")
+ |> Floki.attribute("a", "href")
+ |> length() > 0
+ end
+
+ defp contains_links?(_), do: false
+
+ def filter(%{"type" => "Create", "actor" => actor, "object" => object} = message) do
+ with {:ok, %User{} = u} <- User.get_or_fetch_by_ap_id(actor),
+ {:contains_links, true} <- {:contains_links, contains_links?(object)},
+ {:old_user, true} <- {:old_user, old_user?(u)} do
+ {:ok, message}
+ else
+ {:contains_links, false} ->
+ {:ok, message}
+
+ {:old_user, false} ->
+ {:reject, nil}
+
+ {:error, _} ->
+ {:reject, nil}
+
+ e ->
+ Logger.warn("[MRF anti-link-spam] WTF: unhandled error #{inspect(e)}")
+ {:reject, nil}
+ end
+ end
+
+ # in all other cases, pass through
+ def filter(message), do: {:ok, message}
+end
diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex
index 35a7c582e..3f8e3b074 100644
--- a/lib/pleroma/web/oauth/oauth_controller.ex
+++ b/lib/pleroma/web/oauth/oauth_controller.ex
@@ -64,26 +64,34 @@ defmodule Pleroma.Web.OAuth.OAuthController do
defp handle_existing_authorization(
%Plug.Conn{assigns: %{token: %Token{} = token}} = conn,
- params
+ %{"redirect_uri" => @oob_token_redirect_uri}
) do
- token = Repo.preload(token, :app)
+ render(conn, "oob_token_exists.html", %{token: token})
+ end
+
+ defp handle_existing_authorization(
+ %Plug.Conn{assigns: %{token: %Token{} = token}} = conn,
+ %{} = params
+ ) do
+ app = Repo.preload(token, :app).app
redirect_uri =
if is_binary(params["redirect_uri"]) do
params["redirect_uri"]
else
- default_redirect_uri(token.app)
+ default_redirect_uri(app)
end
- redirect_uri = redirect_uri(conn, redirect_uri)
-
- if redirect_uri == @oob_token_redirect_uri do
- render(conn, "oob_token_exists.html", %{token: token})
- else
+ if redirect_uri in String.split(app.redirect_uris) do
+ redirect_uri = redirect_uri(conn, redirect_uri)
url_params = %{access_token: token.token}
url_params = UriHelper.append_param_if_present(url_params, :state, params["state"])
url = UriHelper.append_uri_params(redirect_uri, url_params)
redirect(conn, external: url)
+ else
+ conn
+ |> put_flash(:error, "Unlisted redirect_uri.")
+ |> redirect(external: redirect_uri(conn, redirect_uri))
end
end
@@ -101,17 +109,27 @@ defmodule Pleroma.Web.OAuth.OAuthController do
end
def after_create_authorization(%Plug.Conn{} = conn, %Authorization{} = auth, %{
+ "authorization" => %{"redirect_uri" => @oob_token_redirect_uri}
+ }) do
+ render(conn, "oob_authorization_created.html", %{auth: auth})
+ end
+
+ def after_create_authorization(%Plug.Conn{} = conn, %Authorization{} = auth, %{
"authorization" => %{"redirect_uri" => redirect_uri} = auth_attrs
}) do
- redirect_uri = redirect_uri(conn, redirect_uri)
+ app = Repo.preload(auth, :app).app
- if redirect_uri == @oob_token_redirect_uri do
- render(conn, "oob_authorization_created.html", %{auth: auth})
- else
+ # An extra safety measure before we redirect (also done in `do_create_authorization/2`)
+ if redirect_uri in String.split(app.redirect_uris) do
+ redirect_uri = redirect_uri(conn, redirect_uri)
url_params = %{code: auth.token}
url_params = UriHelper.append_param_if_present(url_params, :state, auth_attrs["state"])
url = UriHelper.append_uri_params(redirect_uri, url_params)
redirect(conn, external: url)
+ else
+ conn
+ |> put_flash(:error, "Unlisted redirect_uri.")
+ |> redirect(external: redirect_uri(conn, redirect_uri))
end
end
@@ -324,7 +342,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
})
conn
- |> put_session(:registration_id, registration.id)
+ |> put_session_registration_id(registration.id)
|> registration_details(%{"authorization" => registration_params})
end
else
@@ -445,7 +463,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
|> Scopes.validates(app.scopes)
end
- defp default_redirect_uri(%App{} = app) do
+ def default_redirect_uri(%App{} = app) do
app.redirect_uris
|> String.split()
|> Enum.at(0)
diff --git a/lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex b/lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex
index 82f1cce29..4a7c5eae0 100644
--- a/lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex
+++ b/lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex
@@ -1,19 +1,15 @@
defmodule Pleroma.Web.RichMedia.Parsers.MetaTagsParser do
def parse(html, data, prefix, error_message, key_name, value_name \\ "content") do
- meta_data =
- html
- |> get_elements(key_name, prefix)
- |> Enum.reduce(data, fn el, acc ->
- attributes = normalize_attributes(el, prefix, key_name, value_name)
+ with elements = [_ | _] <- get_elements(html, key_name, prefix),
+ meta_data =
+ Enum.reduce(elements, data, fn el, acc ->
+ attributes = normalize_attributes(el, prefix, key_name, value_name)
- Map.merge(acc, attributes)
- end)
- |> maybe_put_title(html)
-
- if Enum.empty?(meta_data) do
- {:error, error_message}
- else
+ Map.merge(acc, attributes)
+ end) do
{:ok, meta_data}
+ else
+ _e -> {:error, error_message}
end
end
@@ -31,17 +27,4 @@ defmodule Pleroma.Web.RichMedia.Parsers.MetaTagsParser do
%{String.to_atom(data[key_name]) => data[value_name]}
end
-
- defp maybe_put_title(%{title: _} = meta, _), do: meta
-
- defp maybe_put_title(meta, html) do
- case get_page_title(html) do
- "" -> meta
- title -> Map.put_new(meta, :title, title)
- end
- end
-
- defp get_page_title(html) do
- Floki.find(html, "title") |> Floki.text()
- end
end