Merge remote-tracking branch 'origin/develop' into shigusegubu
* origin/develop: (87 commits) Add a gopher url port config option modify the migrations to use naive_datetime_usec Fix filter migration Fix migration timestamp type Ecto 3.0.5 migration Update frontend Format Use ILIKE to search users transmogrifier: upgrade: when upgrading OStatus users to AP, ensure we always use the fake collection user: properly cope with actors which do not declare a followers collection transmogrifier: when determining followers collection URI, we may need to fetch the actor test: add test for list sanitization tests: add test for as:Public issues activitypub: transmogrifier: do not allow missing lists to be interpreted as nil activitypub: transmogrifier: ensure as:Public activities are delivered to followers fix UploadTest to use new image_tmp.jpg used imageOptim to reduce size of image files Document additional pleroma changes to /api/v1/accounts/:id Check if the user has indeed not been federated with Added support for exclude_types, limit, and min_id in Mastodon notifications. ...
This commit is contained in:
commit
9bb34a12eb
392 changed files with 2149 additions and 715 deletions
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
defmodule Mix.Tasks.Pleroma.Relay do
|
||||
use Mix.Task
|
||||
alias Pleroma.Web.ActivityPub.Relay
|
||||
alias Mix.Tasks.Pleroma.Common
|
||||
alias Pleroma.Web.ActivityPub.Relay
|
||||
|
||||
@shortdoc "Manages remote relays"
|
||||
@moduledoc """
|
||||
|
|
|
|||
32
lib/mix/tasks/pleroma/robotstxt.ex
Normal file
32
lib/mix/tasks/pleroma/robotstxt.ex
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Mix.Tasks.Pleroma.RobotsTxt do
|
||||
use Mix.Task
|
||||
|
||||
@shortdoc "Generate robots.txt"
|
||||
@moduledoc """
|
||||
Generates robots.txt
|
||||
|
||||
## Overwrite robots.txt to disallow all
|
||||
|
||||
mix pleroma.robots_txt disallow_all
|
||||
|
||||
This will write a robots.txt that will hide all paths on your instance
|
||||
from search engines and other robots that obey robots.txt
|
||||
|
||||
"""
|
||||
def run(["disallow_all"]) do
|
||||
static_dir = Pleroma.Config.get([:instance, :static_dir], "instance/static/")
|
||||
|
||||
if !File.exists?(static_dir) do
|
||||
File.mkdir_p!(static_dir)
|
||||
end
|
||||
|
||||
robots_txt_path = Path.join(static_dir, "robots.txt")
|
||||
robots_txt_content = "User-Agent: *\nDisallow: /\n"
|
||||
|
||||
File.write!(robots_txt_path, robots_txt_content, [:write])
|
||||
end
|
||||
end
|
||||
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
defmodule Mix.Tasks.Pleroma.Uploads do
|
||||
use Mix.Task
|
||||
alias Mix.Tasks.Pleroma.Common
|
||||
alias Pleroma.Upload
|
||||
alias Pleroma.Uploaders.Local
|
||||
alias Mix.Tasks.Pleroma.Common
|
||||
require Logger
|
||||
|
||||
@log_every 50
|
||||
|
|
@ -20,7 +20,6 @@ defmodule Mix.Tasks.Pleroma.Uploads do
|
|||
Options:
|
||||
- `--delete` - delete local uploads after migrating them to the target uploader
|
||||
|
||||
|
||||
A list of available uploaders can be seen in config.exs
|
||||
"""
|
||||
def run(["migrate_local", target_uploader | args]) do
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
defmodule Mix.Tasks.Pleroma.User do
|
||||
use Mix.Task
|
||||
import Ecto.Changeset
|
||||
alias Mix.Tasks.Pleroma.Common
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Mix.Tasks.Pleroma.Common
|
||||
|
||||
@shortdoc "Manages Pleroma users"
|
||||
@moduledoc """
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ defmodule Pleroma.PasswordResetToken do
|
|||
|
||||
import Ecto.Changeset
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.PasswordResetToken
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
||||
schema "password_reset_tokens" do
|
||||
belongs_to(:user, User, type: Pleroma.FlakeId)
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
defmodule Pleroma.Activity do
|
||||
use Ecto.Schema
|
||||
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Repo
|
||||
|
||||
import Ecto.Query
|
||||
|
||||
|
|
@ -22,6 +22,10 @@ defmodule Pleroma.Activity do
|
|||
"Like" => "favourite"
|
||||
}
|
||||
|
||||
@mastodon_to_ap_notification_types for {k, v} <- @mastodon_notification_types,
|
||||
into: %{},
|
||||
do: {v, k}
|
||||
|
||||
schema "activities" do
|
||||
field(:data, :map)
|
||||
field(:local, :boolean, default: true)
|
||||
|
|
@ -109,7 +113,8 @@ defmodule Pleroma.Activity do
|
|||
|
||||
def delete_by_ap_id(id) when is_binary(id) do
|
||||
by_object_ap_id(id)
|
||||
|> Repo.delete_all(returning: true)
|
||||
|> select([u], u)
|
||||
|> Repo.delete_all()
|
||||
|> elem(1)
|
||||
|> Enum.find(fn
|
||||
%{data: %{"type" => "Create", "object" => %{"id" => ap_id}}} -> ap_id == id
|
||||
|
|
@ -126,6 +131,10 @@ defmodule Pleroma.Activity do
|
|||
|
||||
def mastodon_notification_type(%Activity{}), do: nil
|
||||
|
||||
def from_mastodon_notification_type(type) do
|
||||
Map.get(@mastodon_to_ap_notification_types, type)
|
||||
end
|
||||
|
||||
def all_by_actor_and_id(actor, status_ids \\ [])
|
||||
def all_by_actor_and_id(_actor, []), do: []
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ defmodule Pleroma.Application do
|
|||
@repository Mix.Project.config()[:source_url]
|
||||
def name, do: @name
|
||||
def version, do: @version
|
||||
def named_version(), do: @name <> " " <> @version
|
||||
def named_version, do: @name <> " " <> @version
|
||||
def repository, do: @repository
|
||||
|
||||
def user_agent() do
|
||||
def user_agent do
|
||||
info = "#{Pleroma.Web.base_url()} <#{Pleroma.Config.get([:instance, :email], "")}>"
|
||||
named_version() <> "; " <> info
|
||||
end
|
||||
|
|
@ -48,7 +48,7 @@ defmodule Pleroma.Application do
|
|||
[
|
||||
:user_cache,
|
||||
[
|
||||
default_ttl: 25000,
|
||||
default_ttl: 25_000,
|
||||
ttl_interval: 1000,
|
||||
limit: 2500
|
||||
]
|
||||
|
|
@ -60,7 +60,7 @@ defmodule Pleroma.Application do
|
|||
[
|
||||
:object_cache,
|
||||
[
|
||||
default_ttl: 25000,
|
||||
default_ttl: 25_000,
|
||||
ttl_interval: 1000,
|
||||
limit: 2500
|
||||
]
|
||||
|
|
@ -127,7 +127,7 @@ defmodule Pleroma.Application do
|
|||
Supervisor.start_link(children, opts)
|
||||
end
|
||||
|
||||
def enabled_hackney_pools() do
|
||||
def enabled_hackney_pools do
|
||||
[:media] ++
|
||||
if Application.get_env(:tesla, :adapter) == Tesla.Adapter.Hackney do
|
||||
[:federation]
|
||||
|
|
@ -142,14 +142,14 @@ defmodule Pleroma.Application do
|
|||
end
|
||||
|
||||
if Mix.env() == :test do
|
||||
defp streamer_child(), do: []
|
||||
defp chat_child(), do: []
|
||||
defp streamer_child, do: []
|
||||
defp chat_child, do: []
|
||||
else
|
||||
defp streamer_child() do
|
||||
defp streamer_child do
|
||||
[worker(Pleroma.Web.Streamer, [])]
|
||||
end
|
||||
|
||||
defp chat_child() do
|
||||
defp chat_child do
|
||||
if Pleroma.Config.get([:chat, :enabled]) do
|
||||
[worker(Pleroma.Web.ChatChannel.ChatChannelState, [])]
|
||||
else
|
||||
|
|
@ -158,7 +158,7 @@ defmodule Pleroma.Application do
|
|||
end
|
||||
end
|
||||
|
||||
defp hackney_pool_children() do
|
||||
defp hackney_pool_children do
|
||||
for pool <- enabled_hackney_pools() do
|
||||
options = Pleroma.Config.get([:hackney_pools, pool])
|
||||
:hackney_pool.child_spec(pool, options)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ defmodule Pleroma.Captcha do
|
|||
use GenServer
|
||||
|
||||
@doc false
|
||||
def start_link() do
|
||||
def start_link do
|
||||
GenServer.start_link(__MODULE__, [], name: __MODULE__)
|
||||
end
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ defmodule Pleroma.Captcha do
|
|||
@doc """
|
||||
Ask the configured captcha service for a new captcha
|
||||
"""
|
||||
def new() do
|
||||
def new do
|
||||
GenServer.call(__MODULE__, :new)
|
||||
end
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ defmodule Pleroma.Captcha do
|
|||
secret = KeyGenerator.generate(secret_key_base, token <> "_encrypt")
|
||||
sign_secret = KeyGenerator.generate(secret_key_base, token <> "_sign")
|
||||
|
||||
# If the time found is less than (current_time - seconds_valid), then the time has already passed.
|
||||
# If the time found is less than (current_time-seconds_valid) then the time has already passed
|
||||
# Later we check that the time found is more than the presumed invalidatation time, that means
|
||||
# that the data is still valid and the captcha can be checked
|
||||
seconds_valid = Pleroma.Config.get!([Pleroma.Captcha, :seconds_valid])
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ defmodule Pleroma.Captcha.Kocaptcha do
|
|||
@behaviour Service
|
||||
|
||||
@impl Service
|
||||
def new() do
|
||||
def new do
|
||||
endpoint = Pleroma.Config.get!([__MODULE__, :endpoint])
|
||||
|
||||
case Tesla.get(endpoint <> "/new") do
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@ defmodule Pleroma.Clippy do
|
|||
# No software is complete until they have a Clippy implementation.
|
||||
# A ballmer peak _may_ be required to change this module.
|
||||
|
||||
def tip() do
|
||||
def tip do
|
||||
tips()
|
||||
|> Enum.random()
|
||||
|> puts()
|
||||
end
|
||||
|
||||
def tips() do
|
||||
def tips do
|
||||
host = Pleroma.Config.get([Pleroma.Web.Endpoint, :url, :host])
|
||||
|
||||
[
|
||||
|
|
@ -92,8 +92,8 @@ defmodule Pleroma.Clippy do
|
|||
|
||||
# surrond one/five line clippy with blank lines around to not fuck up the layout
|
||||
#
|
||||
# yes this fix sucks but it's good enough, have you ever seen a release of windows wihtout some butched
|
||||
# features anyway?
|
||||
# yes this fix sucks but it's good enough, have you ever seen a release of windows
|
||||
# without some butched features anyway?
|
||||
lines =
|
||||
if length(lines) == 1 or length(lines) == 5 do
|
||||
[""] ++ lines ++ [""]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
defmodule Pleroma.Config.DeprecationWarnings do
|
||||
require Logger
|
||||
|
||||
def check_frontend_config_mechanism() do
|
||||
def check_frontend_config_mechanism do
|
||||
if Pleroma.Config.get(:fe) do
|
||||
Logger.warn("""
|
||||
!!!DEPRECATION WARNING!!!
|
||||
|
|
|
|||
|
|
@ -17,13 +17,13 @@ defmodule Pleroma.Emoji do
|
|||
@ets_options [:ordered_set, :protected, :named_table, {:read_concurrency, true}]
|
||||
|
||||
@doc false
|
||||
def start_link() do
|
||||
def start_link do
|
||||
GenServer.start_link(__MODULE__, [], name: __MODULE__)
|
||||
end
|
||||
|
||||
@doc "Reloads the emojis from disk."
|
||||
@spec reload() :: :ok
|
||||
def reload() do
|
||||
def reload do
|
||||
GenServer.call(__MODULE__, :reload)
|
||||
end
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ defmodule Pleroma.Emoji do
|
|||
|
||||
@doc "Returns all the emojos!!"
|
||||
@spec get_all() :: [{String.t(), String.t()}, ...]
|
||||
def get_all() do
|
||||
def get_all do
|
||||
:ets.tab2list(@ets)
|
||||
end
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ defmodule Pleroma.Emoji do
|
|||
{:ok, state}
|
||||
end
|
||||
|
||||
defp load() do
|
||||
defp load do
|
||||
emojis =
|
||||
(load_finmoji(Keyword.get(Application.get_env(:pleroma, :instance), :finmoji_enabled)) ++
|
||||
load_from_file("config/emoji.txt") ++
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ defmodule Pleroma.Filter do
|
|||
import Ecto.Changeset
|
||||
import Ecto.Query
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
||||
schema "filters" do
|
||||
belongs_to(:user, User, type: Pleroma.FlakeId)
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ defmodule Pleroma.FlakeId do
|
|||
{:ok, FlakeId.from_string(value)}
|
||||
end
|
||||
|
||||
def autogenerate(), do: get()
|
||||
def autogenerate, do: get()
|
||||
|
||||
# -- GenServer API
|
||||
def start_link do
|
||||
|
|
@ -165,7 +165,7 @@ defmodule Pleroma.FlakeId do
|
|||
1_000_000_000 * mega_seconds + seconds * 1000 + :erlang.trunc(micro_seconds / 1000)
|
||||
end
|
||||
|
||||
defp worker_id() do
|
||||
defp worker_id do
|
||||
<<worker::integer-size(48)>> = :crypto.strong_rand_bytes(6)
|
||||
worker
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ defmodule Pleroma.Formatter do
|
|||
|
||||
@markdown_characters_regex ~r/(`|\*|_|{|}|[|]|\(|\)|#|\+|-|\.|!)/
|
||||
@link_regex ~r{((?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~%:/?#[\]@!\$&'\(\)\*\+,;=.]+)|[0-9a-z+\-\.]+:[0-9a-z$-_.+!*'(),]+}ui
|
||||
# credo:disable-for-previous-line Credo.Check.Readability.MaxLineLength
|
||||
|
||||
@auto_linker_config hashtag: true,
|
||||
hashtag_handler: &Pleroma.Formatter.hashtag_handler/4,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ defmodule Pleroma.Gopher.Server do
|
|||
use GenServer
|
||||
require Logger
|
||||
|
||||
def start_link() do
|
||||
def start_link do
|
||||
config = Pleroma.Config.get(:gopher, [])
|
||||
ip = Keyword.get(config, :ip, {0, 0, 0, 0})
|
||||
port = Keyword.get(config, :port, 1234)
|
||||
|
|
@ -36,12 +36,12 @@ defmodule Pleroma.Gopher.Server do
|
|||
end
|
||||
|
||||
defmodule Pleroma.Gopher.Server.ProtocolHandler do
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.HTML
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
|
||||
def start_link(ref, socket, transport, opts) do
|
||||
pid = spawn_link(__MODULE__, :init, [ref, socket, transport, opts])
|
||||
|
|
@ -66,7 +66,8 @@ defmodule Pleroma.Gopher.Server.ProtocolHandler do
|
|||
def link(name, selector, type \\ 1) do
|
||||
address = Pleroma.Web.Endpoint.host()
|
||||
port = Pleroma.Config.get([:gopher, :port], 1234)
|
||||
"#{type}#{name}\t#{selector}\t#{address}\t#{port}\r\n"
|
||||
dstport = Pleroma.Config.get([:gopher, :dstport], port)
|
||||
"#{type}#{name}\t#{selector}\t#{address}\t#{dstport}\r\n"
|
||||
end
|
||||
|
||||
def render_activities(activities) do
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ defmodule Pleroma.HTML do
|
|||
defp get_scrubbers(scrubbers) when is_list(scrubbers), do: scrubbers
|
||||
defp get_scrubbers(_), do: [Pleroma.HTML.Scrubber.Default]
|
||||
|
||||
def get_scrubbers() do
|
||||
def get_scrubbers do
|
||||
Pleroma.Config.get([:markup, :scrub_policy])
|
||||
|> get_scrubbers
|
||||
end
|
||||
|
|
@ -95,6 +95,13 @@ defmodule Pleroma.HTML.Scrubber.TwitterText do
|
|||
Meta.allow_tag_with_uri_attributes("a", ["href", "data-user", "data-tag"], @valid_schemes)
|
||||
Meta.allow_tag_with_these_attributes("a", ["name", "title", "class"])
|
||||
|
||||
Meta.allow_tag_with_this_attribute_values("a", "rel", [
|
||||
"tag",
|
||||
"nofollow",
|
||||
"noopener",
|
||||
"noreferrer"
|
||||
])
|
||||
|
||||
# paragraphs and linebreaks
|
||||
Meta.allow_tag_with_these_attributes("br", [])
|
||||
Meta.allow_tag_with_these_attributes("p", [])
|
||||
|
|
@ -137,6 +144,13 @@ defmodule Pleroma.HTML.Scrubber.Default do
|
|||
Meta.allow_tag_with_uri_attributes("a", ["href", "data-user", "data-tag"], @valid_schemes)
|
||||
Meta.allow_tag_with_these_attributes("a", ["name", "title", "class"])
|
||||
|
||||
Meta.allow_tag_with_this_attribute_values("a", "rel", [
|
||||
"tag",
|
||||
"nofollow",
|
||||
"noopener",
|
||||
"noreferrer"
|
||||
])
|
||||
|
||||
Meta.allow_tag_with_these_attributes("abbr", ["title"])
|
||||
|
||||
Meta.allow_tag_with_these_attributes("b", [])
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ defmodule Pleroma.Instances.Instance do
|
|||
@moduledoc "Instance."
|
||||
|
||||
alias Pleroma.Instances
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Instances.Instance
|
||||
alias Pleroma.Repo
|
||||
|
||||
use Ecto.Schema
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ defmodule Pleroma.Instances.Instance do
|
|||
|
||||
schema "instances" do
|
||||
field(:host, :string)
|
||||
field(:unreachable_since, :naive_datetime)
|
||||
field(:unreachable_since, :naive_datetime_usec)
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,14 +5,16 @@
|
|||
defmodule Pleroma.Notification do
|
||||
use Ecto.Schema
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Pagination
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
|
||||
import Ecto.Query
|
||||
import Ecto.Changeset
|
||||
|
||||
schema "notifications" do
|
||||
field(:seen, :boolean, default: false)
|
||||
|
|
@ -22,36 +24,22 @@ defmodule Pleroma.Notification do
|
|||
timestamps()
|
||||
end
|
||||
|
||||
# TODO: Make generic and unify (see activity_pub.ex)
|
||||
defp restrict_max(query, %{"max_id" => max_id}) do
|
||||
from(activity in query, where: activity.id < ^max_id)
|
||||
def changeset(%Notification{} = notification, attrs) do
|
||||
notification
|
||||
|> cast(attrs, [:seen])
|
||||
end
|
||||
|
||||
defp restrict_max(query, _), do: query
|
||||
|
||||
defp restrict_since(query, %{"since_id" => since_id}) do
|
||||
from(activity in query, where: activity.id > ^since_id)
|
||||
def for_user_query(user) do
|
||||
Notification
|
||||
|> where(user_id: ^user.id)
|
||||
|> join(:inner, [n], activity in assoc(n, :activity))
|
||||
|> preload(:activity)
|
||||
end
|
||||
|
||||
defp restrict_since(query, _), do: query
|
||||
|
||||
def for_user(user, opts \\ %{}) do
|
||||
query =
|
||||
from(
|
||||
n in Notification,
|
||||
where: n.user_id == ^user.id,
|
||||
order_by: [desc: n.id],
|
||||
join: activity in assoc(n, :activity),
|
||||
preload: [activity: activity],
|
||||
limit: 20
|
||||
)
|
||||
|
||||
query =
|
||||
query
|
||||
|> restrict_since(opts)
|
||||
|> restrict_max(opts)
|
||||
|
||||
Repo.all(query)
|
||||
user
|
||||
|> for_user_query()
|
||||
|> Pagination.fetch_paginated(opts)
|
||||
end
|
||||
|
||||
def set_read_up_to(%{id: user_id} = _user, id) do
|
||||
|
|
@ -68,6 +56,14 @@ defmodule Pleroma.Notification do
|
|||
Repo.update_all(query, [])
|
||||
end
|
||||
|
||||
def read_one(%User{} = user, notification_id) do
|
||||
with {:ok, %Notification{} = notification} <- get(user, notification_id) do
|
||||
notification
|
||||
|> changeset(%{seen: true})
|
||||
|> Repo.update()
|
||||
end
|
||||
end
|
||||
|
||||
def get(%{id: user_id} = _user, id) do
|
||||
query =
|
||||
from(
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@
|
|||
defmodule Pleroma.Object do
|
||||
use Ecto.Schema
|
||||
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.ObjectTombstone
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
||||
import Ecto.Query
|
||||
import Ecto.Changeset
|
||||
|
|
|
|||
78
lib/pleroma/pagination.ex
Normal file
78
lib/pleroma/pagination.ex
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
defmodule Pleroma.Pagination do
|
||||
@moduledoc """
|
||||
Implements Mastodon-compatible pagination.
|
||||
"""
|
||||
|
||||
import Ecto.Query
|
||||
import Ecto.Changeset
|
||||
|
||||
alias Pleroma.Repo
|
||||
|
||||
@default_limit 20
|
||||
|
||||
def fetch_paginated(query, params) do
|
||||
options = cast_params(params)
|
||||
|
||||
query
|
||||
|> paginate(options)
|
||||
|> Repo.all()
|
||||
|> enforce_order(options)
|
||||
end
|
||||
|
||||
def paginate(query, options) do
|
||||
query
|
||||
|> restrict(:min_id, options)
|
||||
|> restrict(:since_id, options)
|
||||
|> restrict(:max_id, options)
|
||||
|> restrict(:order, options)
|
||||
|> restrict(:limit, options)
|
||||
end
|
||||
|
||||
defp cast_params(params) do
|
||||
param_types = %{
|
||||
min_id: :string,
|
||||
since_id: :string,
|
||||
max_id: :string,
|
||||
limit: :integer
|
||||
}
|
||||
|
||||
changeset = cast({%{}, param_types}, params, Map.keys(param_types))
|
||||
changeset.changes
|
||||
end
|
||||
|
||||
defp restrict(query, :min_id, %{min_id: min_id}) do
|
||||
where(query, [q], q.id > ^min_id)
|
||||
end
|
||||
|
||||
defp restrict(query, :since_id, %{since_id: since_id}) do
|
||||
where(query, [q], q.id > ^since_id)
|
||||
end
|
||||
|
||||
defp restrict(query, :max_id, %{max_id: max_id}) do
|
||||
where(query, [q], q.id < ^max_id)
|
||||
end
|
||||
|
||||
defp restrict(query, :order, %{min_id: _}) do
|
||||
order_by(query, [u], fragment("? asc nulls last", u.id))
|
||||
end
|
||||
|
||||
defp restrict(query, :order, _options) do
|
||||
order_by(query, [u], fragment("? desc nulls last", u.id))
|
||||
end
|
||||
|
||||
defp restrict(query, :limit, options) do
|
||||
limit = Map.get(options, :limit, @default_limit)
|
||||
|
||||
query
|
||||
|> limit(^limit)
|
||||
end
|
||||
|
||||
defp restrict(query, _, _), do: query
|
||||
|
||||
defp enforce_order(result, %{min_id: _}) do
|
||||
result
|
||||
|> Enum.reverse()
|
||||
end
|
||||
|
||||
defp enforce_order(result, _), do: result
|
||||
end
|
||||
|
|
@ -3,8 +3,8 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
|
||||
alias Pleroma.Web.HTTPSignatures
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.HTTPSignatures
|
||||
import Plug.Conn
|
||||
require Logger
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ defmodule Pleroma.Plugs.InstanceStatic do
|
|||
end
|
||||
end
|
||||
|
||||
@only ~w(index.html static emoji packs sounds images instance favicon.png sw.js sw-pleroma.js)
|
||||
@only ~w(index.html robots.txt static emoji packs sounds images instance favicon.png sw.js
|
||||
sw-pleroma.js)
|
||||
|
||||
def init(opts) do
|
||||
opts
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ defmodule Pleroma.Plugs.OAuthPlug do
|
|||
import Plug.Conn
|
||||
import Ecto.Query
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
|
||||
@realm_reg Regex.compile!("Bearer\:?\s+(.*)$", "i")
|
||||
|
|
@ -38,6 +38,7 @@ defmodule Pleroma.Plugs.OAuthPlug do
|
|||
preload: [user: user]
|
||||
)
|
||||
|
||||
# credo:disable-for-next-line Credo.Check.Readability.MaxLineLength
|
||||
with %Token{user: %{info: %{deactivated: false} = _} = user} = token_record <- Repo.one(query) do
|
||||
{:ok, user, token_record}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,6 +24,18 @@ defmodule Pleroma.Plugs.UploadedMedia do
|
|||
end
|
||||
|
||||
def call(%{request_path: <<"/", @path, "/", file::binary>>} = conn, opts) do
|
||||
conn =
|
||||
case fetch_query_params(conn) do
|
||||
%{query_params: %{"name" => name}} = conn ->
|
||||
name = String.replace(name, "\"", "\\\"")
|
||||
|
||||
conn
|
||||
|> put_resp_header("content-disposition", "filename=\"#{name}\"")
|
||||
|
||||
conn ->
|
||||
conn
|
||||
end
|
||||
|
||||
config = Pleroma.Config.get([Pleroma.Upload])
|
||||
|
||||
with uploader <- Keyword.fetch!(config, :uploader),
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.UserFetcherPlug do
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
||||
import Plug.Conn
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Repo do
|
||||
use Ecto.Repo, otp_app: :pleroma
|
||||
use Ecto.Repo,
|
||||
otp_app: :pleroma,
|
||||
adapter: Ecto.Adapters.Postgres,
|
||||
migration_timestamps: [type: :naive_datetime_usec]
|
||||
|
||||
@doc """
|
||||
Dynamically loads the repository url from the
|
||||
|
|
|
|||
|
|
@ -3,10 +3,12 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.ReverseProxy do
|
||||
@keep_req_headers ~w(accept user-agent accept-encoding cache-control if-modified-since if-unmodified-since if-none-match if-range range)
|
||||
@keep_req_headers ~w(accept user-agent accept-encoding cache-control if-modified-since) ++
|
||||
~w(if-unmodified-since if-none-match if-range range)
|
||||
@resp_cache_headers ~w(etag date last-modified cache-control)
|
||||
@keep_resp_headers @resp_cache_headers ++
|
||||
~w(content-type content-disposition content-encoding content-range accept-ranges vary)
|
||||
~w(content-type content-disposition content-encoding content-range) ++
|
||||
~w(accept-ranges vary)
|
||||
@default_cache_control_header "public, max-age=1209600"
|
||||
@valid_resp_codes [200, 206, 304]
|
||||
@max_read_duration :timer.seconds(30)
|
||||
|
|
@ -282,8 +284,8 @@ defmodule Pleroma.ReverseProxy do
|
|||
headers
|
||||
|
||||
has_cache? ->
|
||||
# There's caching header present but no cache-control -- we need to explicitely override it to public
|
||||
# as Plug defaults to "max-age=0, private, must-revalidate"
|
||||
# There's caching header present but no cache-control -- we need to explicitely override it
|
||||
# to public as Plug defaults to "max-age=0, private, must-revalidate"
|
||||
List.keystore(headers, "cache-control", 0, {"cache-control", "public"})
|
||||
|
||||
true ->
|
||||
|
|
@ -309,7 +311,25 @@ defmodule Pleroma.ReverseProxy do
|
|||
end
|
||||
|
||||
if attachment? do
|
||||
disposition = "attachment; filename=" <> Keyword.get(opts, :attachment_name, "attachment")
|
||||
name =
|
||||
try do
|
||||
{{"content-disposition", content_disposition_string}, _} =
|
||||
List.keytake(headers, "content-disposition", 0)
|
||||
|
||||
[name | _] =
|
||||
Regex.run(
|
||||
~r/filename="((?:[^"\\]|\\.)*)"/u,
|
||||
content_disposition_string || "",
|
||||
capture: :all_but_first
|
||||
)
|
||||
|
||||
name
|
||||
rescue
|
||||
MatchError -> Keyword.get(opts, :attachment_name, "attachment")
|
||||
end
|
||||
|
||||
disposition = "attachment; filename=\"#{name}\""
|
||||
|
||||
List.keystore(headers, "content-disposition", 0, {"content-disposition", disposition})
|
||||
else
|
||||
headers
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
defmodule Pleroma.Stats do
|
||||
import Ecto.Query
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
||||
def start_link do
|
||||
agent = Agent.start_link(fn -> {[], %{}} end, name: __MODULE__)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,11 @@
|
|||
|
||||
defmodule Pleroma.ThreadMute do
|
||||
use Ecto.Schema
|
||||
alias Pleroma.{Repo, User, ThreadMute}
|
||||
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.ThreadMute
|
||||
alias Pleroma.User
|
||||
|
||||
require Ecto.Query
|
||||
|
||||
schema "thread_mutes" do
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ defmodule Pleroma.Upload do
|
|||
%{
|
||||
"type" => "Link",
|
||||
"mediaType" => upload.content_type,
|
||||
"href" => url_from_spec(opts.base_url, url_spec)
|
||||
"href" => url_from_spec(upload, opts.base_url, url_spec)
|
||||
}
|
||||
],
|
||||
"name" => Map.get(opts, :description) || upload.name
|
||||
|
|
@ -219,14 +219,18 @@ defmodule Pleroma.Upload do
|
|||
tmp_path
|
||||
end
|
||||
|
||||
defp url_from_spec(base_url, {:file, path}) do
|
||||
defp url_from_spec(%__MODULE__{name: name}, base_url, {:file, path}) do
|
||||
path =
|
||||
path
|
||||
|> URI.encode(&char_unescaped?/1)
|
||||
URI.encode(path, &char_unescaped?/1) <>
|
||||
if Pleroma.Config.get([__MODULE__, :link_name], false) do
|
||||
"?name=#{URI.encode(name, &char_unescaped?/1)}"
|
||||
else
|
||||
""
|
||||
end
|
||||
|
||||
[base_url, "media", path]
|
||||
|> Path.join()
|
||||
end
|
||||
|
||||
defp url_from_spec(_base_url, {:url, url}), do: url
|
||||
defp url_from_spec(_upload, _base_url, {:url, url}), do: url
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ defmodule Pleroma.Uploaders.S3 do
|
|||
@behaviour Pleroma.Uploaders.Uploader
|
||||
require Logger
|
||||
|
||||
# The file name is re-encoded with S3's constraints here to comply with previous links with less strict filenames
|
||||
# The file name is re-encoded with S3's constraints here to comply with previous
|
||||
# links with less strict filenames
|
||||
def get_file(file) do
|
||||
config = Pleroma.Config.get([__MODULE__])
|
||||
bucket = Keyword.fetch!(config, :bucket)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ defmodule Pleroma.Uploaders.Swift.Keystone do
|
|||
|> Poison.decode!()
|
||||
end
|
||||
|
||||
def get_token() do
|
||||
def get_token do
|
||||
settings = Pleroma.Config.get(Pleroma.Uploaders.Swift)
|
||||
username = Keyword.fetch!(settings, :username)
|
||||
password = Keyword.fetch!(settings, :password)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ defmodule Pleroma.Uploaders.Uploader do
|
|||
* `{:error, String.t}` error information if the file failed to be saved to the backend.
|
||||
* `:wait_callback` will wait for an http post request at `/api/pleroma/upload_callback/:upload_path` and call the uploader's `http_callback/3` method.
|
||||
|
||||
|
||||
"""
|
||||
@type file_spec :: {:file | :url, String.t()}
|
||||
@callback put_file(Pleroma.Upload.t()) ::
|
||||
|
|
|
|||
|
|
@ -8,21 +8,21 @@ defmodule Pleroma.User do
|
|||
import Ecto.Changeset
|
||||
import Ecto.Query
|
||||
|
||||
alias Comeonin.Pbkdf2
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Formatter
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Notification
|
||||
alias Comeonin.Pbkdf2
|
||||
alias Pleroma.Formatter
|
||||
alias Pleroma.Web.CommonAPI.Utils, as: CommonUtils
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.Websub
|
||||
alias Pleroma.Web.OAuth
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.CommonAPI.Utils, as: CommonUtils
|
||||
alias Pleroma.Web.OAuth
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.RelMe
|
||||
alias Pleroma.Web.Websub
|
||||
|
||||
require Logger
|
||||
|
||||
|
|
@ -30,6 +30,7 @@ defmodule Pleroma.User do
|
|||
|
||||
@primary_key {:id, Pleroma.FlakeId, autogenerate: true}
|
||||
|
||||
# credo:disable-for-next-line Credo.Check.Readability.MaxLineLength
|
||||
@email_regex ~r/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
|
||||
|
||||
@strict_local_nickname_regex ~r/^[a-zA-Z\d]+$/
|
||||
|
|
@ -51,7 +52,7 @@ defmodule Pleroma.User do
|
|||
field(:search_rank, :float, virtual: true)
|
||||
field(:tags, {:array, :string}, default: [])
|
||||
field(:bookmarks, {:array, :string}, default: [])
|
||||
field(:last_refreshed_at, :naive_datetime)
|
||||
field(:last_refreshed_at, :naive_datetime_usec)
|
||||
has_many(:notifications, Notification)
|
||||
embeds_one(:info, Pleroma.User.Info)
|
||||
|
||||
|
|
@ -103,9 +104,8 @@ defmodule Pleroma.User do
|
|||
"#{Web.base_url()}/users/#{nickname}"
|
||||
end
|
||||
|
||||
def ap_followers(%User{} = user) do
|
||||
"#{ap_id(user)}/followers"
|
||||
end
|
||||
def ap_followers(%User{follower_address: fa}) when is_binary(fa), do: fa
|
||||
def ap_followers(%User{} = user), do: "#{ap_id(user)}/followers"
|
||||
|
||||
def user_info(%User{} = user) do
|
||||
oneself = if user.local, do: 1, else: 0
|
||||
|
|
@ -285,7 +285,7 @@ defmodule Pleroma.User do
|
|||
def needs_update?(%User{local: false, last_refreshed_at: nil}), do: true
|
||||
|
||||
def needs_update?(%User{local: false} = user) do
|
||||
NaiveDateTime.diff(NaiveDateTime.utc_now(), user.last_refreshed_at) >= 86400
|
||||
NaiveDateTime.diff(NaiveDateTime.utc_now(), user.last_refreshed_at) >= 86_400
|
||||
end
|
||||
|
||||
def needs_update?(_), do: true
|
||||
|
|
@ -334,10 +334,11 @@ defmodule Pleroma.User do
|
|||
^followed_addresses
|
||||
)
|
||||
]
|
||||
]
|
||||
],
|
||||
select: u
|
||||
)
|
||||
|
||||
{1, [follower]} = Repo.update_all(q, [], returning: true)
|
||||
{1, [follower]} = Repo.update_all(q, [])
|
||||
|
||||
Enum.each(followeds, fn followed ->
|
||||
update_follower_count(followed)
|
||||
|
|
@ -367,10 +368,11 @@ defmodule Pleroma.User do
|
|||
q =
|
||||
from(u in User,
|
||||
where: u.id == ^follower.id,
|
||||
update: [push: [following: ^ap_followers]]
|
||||
update: [push: [following: ^ap_followers]],
|
||||
select: u
|
||||
)
|
||||
|
||||
{1, [follower]} = Repo.update_all(q, [], returning: true)
|
||||
{1, [follower]} = Repo.update_all(q, [])
|
||||
|
||||
{:ok, _} = update_follower_count(followed)
|
||||
|
||||
|
|
@ -385,10 +387,11 @@ defmodule Pleroma.User do
|
|||
q =
|
||||
from(u in User,
|
||||
where: u.id == ^follower.id,
|
||||
update: [pull: [following: ^ap_followers]]
|
||||
update: [pull: [following: ^ap_followers]],
|
||||
select: u
|
||||
)
|
||||
|
||||
{1, [follower]} = Repo.update_all(q, [], returning: true)
|
||||
{1, [follower]} = Repo.update_all(q, [])
|
||||
|
||||
{:ok, followed} = update_follower_count(followed)
|
||||
|
||||
|
|
@ -435,7 +438,8 @@ defmodule Pleroma.User do
|
|||
Repo.get_by(User, ap_id: ap_id)
|
||||
end
|
||||
|
||||
# This is mostly an SPC migration fix. This guesses the user nickname (by taking the last part of the ap_id and the domain) and tries to get that user
|
||||
# This is mostly an SPC migration fix. This guesses the user nickname by taking the last part
|
||||
# of the ap_id and the domain and tries to get that user
|
||||
def get_by_guessed_nickname(ap_id) do
|
||||
domain = URI.parse(ap_id).host
|
||||
name = List.last(String.split(ap_id, "/"))
|
||||
|
|
@ -635,7 +639,7 @@ defmodule Pleroma.User do
|
|||
users =
|
||||
user
|
||||
|> User.get_follow_requests_query()
|
||||
|> join(:inner, [a], u in User, a.actor == u.ap_id)
|
||||
|> join(:inner, [a], u in User, on: a.actor == u.ap_id)
|
||||
|> where([a, u], not fragment("? @> ?", u.following, ^[user.follower_address]))
|
||||
|> group_by([a, u], u.id)
|
||||
|> select([a, u], u)
|
||||
|
|
@ -657,7 +661,8 @@ defmodule Pleroma.User do
|
|||
)
|
||||
]
|
||||
)
|
||||
|> Repo.update_all([], returning: true)
|
||||
|> select([u], u)
|
||||
|> Repo.update_all([])
|
||||
|> case do
|
||||
{1, [user]} -> set_cache(user)
|
||||
_ -> {:error, user}
|
||||
|
|
@ -677,7 +682,8 @@ defmodule Pleroma.User do
|
|||
)
|
||||
]
|
||||
)
|
||||
|> Repo.update_all([], returning: true)
|
||||
|> select([u], u)
|
||||
|> Repo.update_all([])
|
||||
|> case do
|
||||
{1, [user]} -> set_cache(user)
|
||||
_ -> {:error, user}
|
||||
|
|
@ -723,7 +729,8 @@ defmodule Pleroma.User do
|
|||
)
|
||||
]
|
||||
)
|
||||
|> Repo.update_all([], returning: true)
|
||||
|> select([u], u)
|
||||
|> Repo.update_all([])
|
||||
|> case do
|
||||
{1, [user]} -> set_cache(user)
|
||||
_ -> {:error, user}
|
||||
|
|
@ -771,7 +778,7 @@ defmodule Pleroma.User do
|
|||
}) :: {:ok, [Pleroma.User.t()], number()}
|
||||
def search_for_admin(%{query: nil, local: local, page: page, page_size: page_size}) do
|
||||
query =
|
||||
from(u in User, order_by: u.id)
|
||||
from(u in User, order_by: u.nickname)
|
||||
|> maybe_local_user_query(local)
|
||||
|
||||
paginated_query =
|
||||
|
|
@ -787,34 +794,27 @@ defmodule Pleroma.User do
|
|||
|
||||
@spec search_for_admin(%{
|
||||
query: binary(),
|
||||
admin: Pleroma.User.t(),
|
||||
local: boolean(),
|
||||
page: number(),
|
||||
page_size: number()
|
||||
}) :: {:ok, [Pleroma.User.t()], number()}
|
||||
def search_for_admin(%{
|
||||
query: term,
|
||||
admin: admin,
|
||||
local: local,
|
||||
page: page,
|
||||
page_size: page_size
|
||||
}) do
|
||||
term = String.trim_leading(term, "@")
|
||||
maybe_local_query = User |> maybe_local_user_query(local)
|
||||
|
||||
local_paginated_query =
|
||||
User
|
||||
|> maybe_local_user_query(local)
|
||||
search_query = from(u in maybe_local_query, where: ilike(u.nickname, ^"%#{term}%"))
|
||||
count = search_query |> Repo.aggregate(:count, :id)
|
||||
|
||||
results =
|
||||
search_query
|
||||
|> paginate(page, page_size)
|
||||
|> Repo.all()
|
||||
|
||||
search_query = fts_search_subquery(term, local_paginated_query)
|
||||
|
||||
count =
|
||||
term
|
||||
|> fts_search_subquery()
|
||||
|> maybe_local_user_query(local)
|
||||
|> Repo.aggregate(:count, :id)
|
||||
|
||||
{:ok, do_search(search_query, admin), count}
|
||||
{:ok, results, count}
|
||||
end
|
||||
|
||||
def search(query, resolve \\ false, for_user \\ nil) do
|
||||
|
|
@ -1157,9 +1157,12 @@ defmodule Pleroma.User do
|
|||
if !is_nil(user) and !User.needs_update?(user) do
|
||||
user
|
||||
else
|
||||
# Whether to fetch initial posts for the user (if it's a new user & the fetching is enabled)
|
||||
should_fetch_initial = is_nil(user) and Pleroma.Config.get([:fetch_initial_posts, :enabled])
|
||||
|
||||
user = fetch_by_ap_id(ap_id)
|
||||
|
||||
if Pleroma.Config.get([:fetch_initial_posts, :enabled]) do
|
||||
if should_fetch_initial do
|
||||
with %User{} = user do
|
||||
{:ok, _} = Task.start(__MODULE__, :fetch_initial_posts, [user])
|
||||
end
|
||||
|
|
@ -1340,7 +1343,7 @@ defmodule Pleroma.User do
|
|||
|> Enum.map(&String.downcase(&1))
|
||||
end
|
||||
|
||||
defp local_nickname_regex() do
|
||||
defp local_nickname_regex do
|
||||
if Pleroma.Config.get([:instance, :extended_nickname_format]) do
|
||||
@extended_local_nickname_regex
|
||||
else
|
||||
|
|
@ -1383,4 +1386,8 @@ defmodule Pleroma.User do
|
|||
offset: ^((page - 1) * page_size)
|
||||
)
|
||||
end
|
||||
|
||||
def showing_reblogs?(%User{} = user, %User{} = target) do
|
||||
target.ap_id not in user.info.muted_reblogs
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ defmodule Pleroma.User.Info do
|
|||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
alias Pleroma.User.Info
|
||||
|
||||
embedded_schema do
|
||||
field(:banner, :map, default: %{})
|
||||
field(:background, :map, default: %{})
|
||||
|
|
@ -19,6 +21,7 @@ defmodule Pleroma.User.Info do
|
|||
field(:blocks, {:array, :string}, default: [])
|
||||
field(:domain_blocks, {:array, :string}, default: [])
|
||||
field(:mutes, {:array, :string}, default: [])
|
||||
field(:muted_reblogs, {:array, :string}, default: [])
|
||||
field(:deactivated, :boolean, default: false)
|
||||
field(:no_rich_text, :boolean, default: false)
|
||||
field(:ap_enabled, :boolean, default: false)
|
||||
|
|
@ -250,4 +253,23 @@ defmodule Pleroma.User.Info do
|
|||
|
||||
cast(info, params, [:pinned_activities])
|
||||
end
|
||||
|
||||
def roles(%Info{is_moderator: is_moderator, is_admin: is_admin}) do
|
||||
%{
|
||||
admin: is_admin,
|
||||
moderator: is_moderator
|
||||
}
|
||||
end
|
||||
|
||||
def add_reblog_mute(info, ap_id) do
|
||||
params = %{muted_reblogs: info.muted_reblogs ++ [ap_id]}
|
||||
|
||||
cast(info, params, [:muted_reblogs])
|
||||
end
|
||||
|
||||
def remove_reblog_mute(info, ap_id) do
|
||||
params = %{muted_reblogs: List.delete(info.muted_reblogs, ap_id)}
|
||||
|
||||
cast(info, params, [:muted_reblogs])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ defmodule Pleroma.User.WelcomeMessage do
|
|||
end
|
||||
end
|
||||
|
||||
defp welcome_user() do
|
||||
defp welcome_user do
|
||||
with nickname when is_binary(nickname) <-
|
||||
Pleroma.Config.get([:instance, :welcome_user_nickname]),
|
||||
%User{local: true} = user <- User.get_cached_by_nickname(nickname) do
|
||||
|
|
@ -24,7 +24,7 @@ defmodule Pleroma.User.WelcomeMessage do
|
|||
end
|
||||
end
|
||||
|
||||
defp welcome_message() do
|
||||
defp welcome_message do
|
||||
Pleroma.Config.get([:instance, :welcome_message])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ defmodule Pleroma.UserInviteToken do
|
|||
|
||||
import Ecto.Changeset
|
||||
|
||||
alias Pleroma.UserInviteToken
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.UserInviteToken
|
||||
|
||||
schema "user_invite_tokens" do
|
||||
field(:token, :string)
|
||||
|
|
|
|||
|
|
@ -4,17 +4,17 @@
|
|||
|
||||
defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Instances
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Upload
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Instances
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.ActivityPub.MRF
|
||||
alias Pleroma.Web.WebFinger
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.Federator
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.WebFinger
|
||||
|
||||
import Ecto.Query
|
||||
import Pleroma.Web.ActivityPub.Utils
|
||||
|
|
@ -170,7 +170,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
additional
|
||||
),
|
||||
{:ok, activity} <- insert(create_data, local),
|
||||
# Changing note count prior to enqueuing federation task in order to avoid race conditions on updating user.info
|
||||
# Changing note count prior to enqueuing federation task in order to avoid
|
||||
# race conditions on updating user.info
|
||||
{:ok, _actor} <- increase_note_count_if_public(actor, activity),
|
||||
:ok <- maybe_federate(activity) do
|
||||
{:ok, activity}
|
||||
|
|
@ -309,7 +310,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
|
||||
def delete(%Object{data: %{"id" => id, "actor" => actor}} = object, local \\ true) do
|
||||
user = User.get_cached_by_ap_id(actor)
|
||||
to = object.data["to"] || [] ++ object.data["cc"] || []
|
||||
to = (object.data["to"] || []) ++ (object.data["cc"] || [])
|
||||
|
||||
with {:ok, object, activity} <- Object.delete(object),
|
||||
data <- %{
|
||||
|
|
@ -320,7 +321,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
"deleted_activity_id" => activity && activity.id
|
||||
},
|
||||
{:ok, activity} <- insert(data, local),
|
||||
# Changing note count prior to enqueuing federation task in order to avoid race conditions on updating user.info
|
||||
# Changing note count prior to enqueuing federation task in order to avoid
|
||||
# race conditions on updating user.info
|
||||
{:ok, _actor} <- decrease_note_count_if_public(user, object),
|
||||
:ok <- maybe_federate(activity) do
|
||||
{:ok, activity}
|
||||
|
|
@ -368,20 +370,38 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
content: content
|
||||
} = params
|
||||
) do
|
||||
additional = params[:additional] || %{}
|
||||
|
||||
# only accept false as false value
|
||||
local = !(params[:local] == false)
|
||||
forward = !(params[:forward] == false)
|
||||
|
||||
%{
|
||||
additional = params[:additional] || %{}
|
||||
|
||||
params = %{
|
||||
actor: actor,
|
||||
context: context,
|
||||
account: account,
|
||||
statuses: statuses,
|
||||
content: content
|
||||
}
|
||||
|> make_flag_data(additional)
|
||||
|> insert(local)
|
||||
|
||||
additional =
|
||||
if forward do
|
||||
Map.merge(additional, %{"to" => [], "cc" => [account.ap_id]})
|
||||
else
|
||||
Map.merge(additional, %{"to" => [], "cc" => []})
|
||||
end
|
||||
|
||||
with flag_data <- make_flag_data(params, additional),
|
||||
{:ok, activity} <- insert(flag_data, local),
|
||||
:ok <- maybe_federate(activity) do
|
||||
Enum.each(User.all_superusers(), fn superuser ->
|
||||
superuser
|
||||
|> Pleroma.AdminEmail.report(actor, account, statuses, content)
|
||||
|> Pleroma.Mailer.deliver_async()
|
||||
end)
|
||||
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_activities_for_context(context, opts \\ %{}) do
|
||||
|
|
@ -502,7 +522,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
when is_list(tag_reject) and tag_reject != [] do
|
||||
from(
|
||||
activity in query,
|
||||
where: fragment("(not (? #> '{\"object\",\"tag\"}') \\?| ?)", activity.data, ^tag_reject)
|
||||
where: fragment(~s(\(not \(? #> '{"object","tag"}'\) \\?| ?\)), activity.data, ^tag_reject)
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -512,7 +532,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
when is_list(tag_all) and tag_all != [] do
|
||||
from(
|
||||
activity in query,
|
||||
where: fragment("(? #> '{\"object\",\"tag\"}') \\?& ?", activity.data, ^tag_all)
|
||||
where: fragment(~s(\(? #> '{"object","tag"}'\) \\?& ?), activity.data, ^tag_all)
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -521,14 +541,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
defp restrict_tag(query, %{"tag" => tag}) when is_list(tag) do
|
||||
from(
|
||||
activity in query,
|
||||
where: fragment("(? #> '{\"object\",\"tag\"}') \\?| ?", activity.data, ^tag)
|
||||
where: fragment(~s(\(? #> '{"object","tag"}'\) \\?| ?), activity.data, ^tag)
|
||||
)
|
||||
end
|
||||
|
||||
defp restrict_tag(query, %{"tag" => tag}) when is_binary(tag) do
|
||||
from(
|
||||
activity in query,
|
||||
where: fragment("? <@ (? #> '{\"object\",\"tag\"}')", ^tag, activity.data)
|
||||
where: fragment(~s(? <@ (? #> '{"object","tag"}'\)), ^tag, activity.data)
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -601,7 +621,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
defp restrict_favorited_by(query, %{"favorited_by" => ap_id}) do
|
||||
from(
|
||||
activity in query,
|
||||
where: fragment("? <@ (? #> '{\"object\",\"likes\"}')", ^ap_id, activity.data)
|
||||
where: fragment(~s(? <@ (? #> '{"object","likes"}'\)), ^ap_id, activity.data)
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -610,7 +630,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
defp restrict_media(query, %{"only_media" => val}) when val == "true" or val == "1" do
|
||||
from(
|
||||
activity in query,
|
||||
where: fragment("not (? #> '{\"object\",\"attachment\"}' = ?)", activity.data, ^[])
|
||||
where: fragment(~s(not (? #> '{"object","attachment"}' = ?\)), activity.data, ^[])
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -677,6 +697,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
|
||||
defp restrict_pinned(query, _), do: query
|
||||
|
||||
defp restrict_muted_reblogs(query, %{"muting_user" => %User{info: info}}) do
|
||||
muted_reblogs = info.muted_reblogs || []
|
||||
|
||||
from(
|
||||
activity in query,
|
||||
where: fragment("not ?->>'type' = 'Announce'", activity.data),
|
||||
where: fragment("not ? = ANY(?)", activity.actor, ^muted_reblogs)
|
||||
)
|
||||
end
|
||||
|
||||
defp restrict_muted_reblogs(query, _), do: query
|
||||
|
||||
def fetch_activities_query(recipients, opts \\ %{}) do
|
||||
base_query =
|
||||
from(
|
||||
|
|
@ -704,6 +736,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
|> restrict_replies(opts)
|
||||
|> restrict_reblogs(opts)
|
||||
|> restrict_pinned(opts)
|
||||
|> restrict_muted_reblogs(opts)
|
||||
end
|
||||
|
||||
def fetch_activities(recipients, opts \\ %{}) do
|
||||
|
|
|
|||
|
|
@ -6,15 +6,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|
|||
use Pleroma.Web, :controller
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.ObjectView
|
||||
alias Pleroma.Web.ActivityPub.UserView
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.ActivityPub.ObjectView
|
||||
alias Pleroma.Web.ActivityPub.Relay
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.ActivityPub.UserView
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.Federator
|
||||
|
||||
require Logger
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ defmodule Pleroma.Web.ActivityPub.MRF do
|
|||
end)
|
||||
end
|
||||
|
||||
def get_policies() do
|
||||
def get_policies do
|
||||
Application.get_env(:pleroma, :instance, [])
|
||||
|> Keyword.get(:rewrite_policy, [])
|
||||
|> get_policies()
|
||||
|
|
|
|||
|
|
@ -45,13 +45,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
|||
|
||||
defp check_replace(%{"object" => %{"content" => content, "summary" => summary}} = message) do
|
||||
{content, summary} =
|
||||
Enum.reduce(Pleroma.Config.get([:mrf_keyword, :replace]), {content, summary}, fn {pattern,
|
||||
replacement},
|
||||
{content_acc,
|
||||
summary_acc} ->
|
||||
{String.replace(content_acc, pattern, replacement),
|
||||
String.replace(summary_acc, pattern, replacement)}
|
||||
end)
|
||||
Enum.reduce(
|
||||
Pleroma.Config.get([:mrf_keyword, :replace]),
|
||||
{content, summary},
|
||||
fn {pattern, replacement}, {content_acc, summary_acc} ->
|
||||
{String.replace(content_acc, pattern, replacement),
|
||||
String.replace(summary_acc, pattern, replacement)}
|
||||
end
|
||||
)
|
||||
|
||||
{:ok,
|
||||
message
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.Relay do
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
require Logger
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
A module to handle coding from internal to wire ActivityPub and back.
|
||||
"""
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
|
|
@ -86,11 +86,15 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
end
|
||||
|
||||
def fix_addressing_list(map, field) do
|
||||
if is_binary(map[field]) do
|
||||
map
|
||||
|> Map.put(field, [map[field]])
|
||||
else
|
||||
map
|
||||
cond do
|
||||
is_binary(map[field]) ->
|
||||
Map.put(map, field, [map[field]])
|
||||
|
||||
is_nil(map[field]) ->
|
||||
Map.put(map, field, [])
|
||||
|
||||
true ->
|
||||
map
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -128,13 +132,42 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
|> fix_explicit_addressing(explicit_mentions)
|
||||
end
|
||||
|
||||
# if as:Public is addressed, then make sure the followers collection is also addressed
|
||||
# so that the activities will be delivered to local users.
|
||||
def fix_implicit_addressing(%{"to" => to, "cc" => cc} = object, followers_collection) do
|
||||
recipients = to ++ cc
|
||||
|
||||
if followers_collection not in recipients do
|
||||
cond do
|
||||
"https://www.w3.org/ns/activitystreams#Public" in cc ->
|
||||
to = to ++ [followers_collection]
|
||||
Map.put(object, "to", to)
|
||||
|
||||
"https://www.w3.org/ns/activitystreams#Public" in to ->
|
||||
cc = cc ++ [followers_collection]
|
||||
Map.put(object, "cc", cc)
|
||||
|
||||
true ->
|
||||
object
|
||||
end
|
||||
else
|
||||
object
|
||||
end
|
||||
end
|
||||
|
||||
def fix_implicit_addressing(object, _), do: object
|
||||
|
||||
def fix_addressing(object) do
|
||||
%User{} = user = User.get_or_fetch_by_ap_id(object["actor"])
|
||||
followers_collection = User.ap_followers(user)
|
||||
|
||||
object
|
||||
|> fix_addressing_list("to")
|
||||
|> fix_addressing_list("cc")
|
||||
|> fix_addressing_list("bto")
|
||||
|> fix_addressing_list("bcc")
|
||||
|> fix_explicit_addressing
|
||||
|> fix_implicit_addressing(followers_collection)
|
||||
end
|
||||
|
||||
def fix_actor(%{"attributedTo" => actor} = object) do
|
||||
|
|
@ -355,6 +388,40 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
end
|
||||
end
|
||||
|
||||
# Flag objects are placed ahead of the ID check because Mastodon 2.8 and earlier send them
|
||||
# with nil ID.
|
||||
def handle_incoming(%{"type" => "Flag", "object" => objects, "actor" => actor} = data) do
|
||||
with context <- data["context"] || Utils.generate_context_id(),
|
||||
content <- data["content"] || "",
|
||||
%User{} = actor <- User.get_cached_by_ap_id(actor),
|
||||
|
||||
# Reduce the object list to find the reported user.
|
||||
%User{} = account <-
|
||||
Enum.reduce_while(objects, nil, fn ap_id, _ ->
|
||||
with %User{} = user <- User.get_cached_by_ap_id(ap_id) do
|
||||
{:halt, user}
|
||||
else
|
||||
_ -> {:cont, nil}
|
||||
end
|
||||
end),
|
||||
|
||||
# Remove the reported user from the object list.
|
||||
statuses <- Enum.filter(objects, fn ap_id -> ap_id != account.ap_id end) do
|
||||
params = %{
|
||||
actor: actor,
|
||||
context: context,
|
||||
account: account,
|
||||
statuses: statuses,
|
||||
content: content,
|
||||
additional: %{
|
||||
"cc" => [account.ap_id]
|
||||
}
|
||||
}
|
||||
|
||||
ActivityPub.flag(params)
|
||||
end
|
||||
end
|
||||
|
||||
# disallow objects with bogus IDs
|
||||
def handle_incoming(%{"id" => nil}), do: :error
|
||||
def handle_incoming(%{"id" => ""}), do: :error
|
||||
|
|
@ -650,10 +717,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
if object = Object.normalize(id), do: {:ok, object}, else: nil
|
||||
end
|
||||
|
||||
def set_reply_to_uri(%{"inReplyTo" => inReplyTo} = object) when is_binary(inReplyTo) do
|
||||
with false <- String.starts_with?(inReplyTo, "http"),
|
||||
{:ok, %{data: replied_to_object}} <- get_obj_helper(inReplyTo) do
|
||||
Map.put(object, "inReplyTo", replied_to_object["external_url"] || inReplyTo)
|
||||
def set_reply_to_uri(%{"inReplyTo" => in_reply_to} = object) when is_binary(in_reply_to) do
|
||||
with false <- String.starts_with?(in_reply_to, "http"),
|
||||
{:ok, %{data: replied_to_object}} <- get_obj_helper(in_reply_to) do
|
||||
Map.put(object, "inReplyTo", replied_to_object["external_url"] || in_reply_to)
|
||||
else
|
||||
_e -> object
|
||||
end
|
||||
|
|
@ -830,10 +897,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
end
|
||||
|
||||
def add_attributed_to(object) do
|
||||
attributedTo = object["attributedTo"] || object["actor"]
|
||||
attributed_to = object["attributedTo"] || object["actor"]
|
||||
|
||||
object
|
||||
|> Map.put("attributedTo", attributedTo)
|
||||
|> Map.put("attributedTo", attributed_to)
|
||||
end
|
||||
|
||||
def add_likes(%{"id" => id, "like_count" => likes} = object) do
|
||||
|
|
@ -888,7 +955,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
defp strip_internal_tags(object), do: object
|
||||
|
||||
defp user_upgrade_task(user) do
|
||||
old_follower_address = User.ap_followers(user)
|
||||
# we pass a fake user so that the followers collection is stripped away
|
||||
old_follower_address = User.ap_followers(%User{nickname: user.nickname})
|
||||
|
||||
q =
|
||||
from(
|
||||
|
|
|
|||
|
|
@ -3,17 +3,17 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.Utils do
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Web
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Web.Router.Helpers
|
||||
alias Pleroma.Web.Endpoint
|
||||
alias Ecto.Changeset
|
||||
alias Ecto.UUID
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.Endpoint
|
||||
alias Pleroma.Web.Router.Helpers
|
||||
|
||||
import Ecto.Query
|
||||
|
||||
|
|
@ -621,7 +621,13 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||
#### Flag-related helpers
|
||||
|
||||
def make_flag_data(params, additional) do
|
||||
status_ap_ids = Enum.map(params.statuses || [], & &1.data["id"])
|
||||
status_ap_ids =
|
||||
Enum.map(params.statuses || [], fn
|
||||
%Activity{} = act -> act.data["id"]
|
||||
act when is_map(act) -> act["id"]
|
||||
act when is_binary(act) -> act
|
||||
end)
|
||||
|
||||
object = [params.account.ap_id] ++ status_ap_ids
|
||||
|
||||
%{
|
||||
|
|
|
|||
|
|
@ -5,15 +5,15 @@
|
|||
defmodule Pleroma.Web.ActivityPub.UserView do
|
||||
use Pleroma.Web, :view
|
||||
|
||||
alias Pleroma.Web.WebFinger
|
||||
alias Pleroma.Web.Salmon
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.Router.Helpers
|
||||
alias Pleroma.Web.Endpoint
|
||||
alias Pleroma.Web.Router.Helpers
|
||||
alias Pleroma.Web.Salmon
|
||||
alias Pleroma.Web.WebFinger
|
||||
|
||||
import Ecto.Query
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
|||
use Pleroma.Web, :controller
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Relay
|
||||
alias Pleroma.Web.MastodonAPI.Admin.AccountView
|
||||
alias Pleroma.Web.AdminAPI.AccountView
|
||||
|
||||
import Pleroma.Web.ControllerHelper, only: [json_response: 3]
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@
|
|||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.Admin.AccountView do
|
||||
defmodule Pleroma.Web.AdminAPI.AccountView do
|
||||
use Pleroma.Web, :view
|
||||
|
||||
alias Pleroma.Web.MastodonAPI.Admin.AccountView
|
||||
alias Pleroma.User.Info
|
||||
alias Pleroma.Web.AdminAPI.AccountView
|
||||
|
||||
def render("index.json", %{users: users, count: count, page_size: page_size}) do
|
||||
%{
|
||||
|
|
@ -19,7 +20,10 @@ defmodule Pleroma.Web.MastodonAPI.Admin.AccountView do
|
|||
%{
|
||||
"id" => user.id,
|
||||
"nickname" => user.nickname,
|
||||
"deactivated" => user.info.deactivated
|
||||
"deactivated" => user.info.deactivated,
|
||||
"local" => user.local,
|
||||
"roles" => Info.roles(user.info),
|
||||
"tags" => user.tags || []
|
||||
}
|
||||
end
|
||||
end
|
||||
143
lib/pleroma/web/auth/ldap_authenticator.ex
Normal file
143
lib/pleroma/web/auth/ldap_authenticator.ex
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Auth.LDAPAuthenticator do
|
||||
alias Pleroma.User
|
||||
|
||||
require Logger
|
||||
|
||||
@behaviour Pleroma.Web.Auth.Authenticator
|
||||
|
||||
@connection_timeout 10_000
|
||||
@search_timeout 10_000
|
||||
|
||||
def get_user(%Plug.Conn{} = conn) do
|
||||
if Pleroma.Config.get([:ldap, :enabled]) do
|
||||
{name, password} =
|
||||
case conn.params do
|
||||
%{"authorization" => %{"name" => name, "password" => password}} ->
|
||||
{name, password}
|
||||
|
||||
%{"grant_type" => "password", "username" => name, "password" => password} ->
|
||||
{name, password}
|
||||
end
|
||||
|
||||
case ldap_user(name, password) do
|
||||
%User{} = user ->
|
||||
{:ok, user}
|
||||
|
||||
{:error, {:ldap_connection_error, _}} ->
|
||||
# When LDAP is unavailable, try default authenticator
|
||||
Pleroma.Web.Auth.PleromaAuthenticator.get_user(conn)
|
||||
|
||||
error ->
|
||||
error
|
||||
end
|
||||
else
|
||||
# Fall back to default authenticator
|
||||
Pleroma.Web.Auth.PleromaAuthenticator.get_user(conn)
|
||||
end
|
||||
end
|
||||
|
||||
def handle_error(%Plug.Conn{} = _conn, error) do
|
||||
error
|
||||
end
|
||||
|
||||
def auth_template, do: nil
|
||||
|
||||
defp ldap_user(name, password) do
|
||||
ldap = Pleroma.Config.get(:ldap, [])
|
||||
host = Keyword.get(ldap, :host, "localhost")
|
||||
port = Keyword.get(ldap, :port, 389)
|
||||
ssl = Keyword.get(ldap, :ssl, false)
|
||||
sslopts = Keyword.get(ldap, :sslopts, [])
|
||||
|
||||
options =
|
||||
[{:port, port}, {:ssl, ssl}, {:timeout, @connection_timeout}] ++
|
||||
if sslopts != [], do: [{:sslopts, sslopts}], else: []
|
||||
|
||||
case :eldap.open([to_charlist(host)], options) do
|
||||
{:ok, connection} ->
|
||||
try do
|
||||
if Keyword.get(ldap, :tls, false) do
|
||||
:application.ensure_all_started(:ssl)
|
||||
|
||||
case :eldap.start_tls(
|
||||
connection,
|
||||
Keyword.get(ldap, :tlsopts, []),
|
||||
@connection_timeout
|
||||
) do
|
||||
:ok ->
|
||||
:ok
|
||||
|
||||
error ->
|
||||
Logger.error("Could not start TLS: #{inspect(error)}")
|
||||
end
|
||||
end
|
||||
|
||||
bind_user(connection, ldap, name, password)
|
||||
after
|
||||
:eldap.close(connection)
|
||||
end
|
||||
|
||||
{:error, error} ->
|
||||
Logger.error("Could not open LDAP connection: #{inspect(error)}")
|
||||
{:error, {:ldap_connection_error, error}}
|
||||
end
|
||||
end
|
||||
|
||||
defp bind_user(connection, ldap, name, password) do
|
||||
uid = Keyword.get(ldap, :uid, "cn")
|
||||
base = Keyword.get(ldap, :base)
|
||||
|
||||
case :eldap.simple_bind(connection, "#{uid}=#{name},#{base}", password) do
|
||||
:ok ->
|
||||
case User.get_by_nickname_or_email(name) do
|
||||
%User{} = user ->
|
||||
user
|
||||
|
||||
_ ->
|
||||
register_user(connection, base, uid, name, password)
|
||||
end
|
||||
|
||||
error ->
|
||||
error
|
||||
end
|
||||
end
|
||||
|
||||
defp register_user(connection, base, uid, name, password) do
|
||||
case :eldap.search(connection, [
|
||||
{:base, to_charlist(base)},
|
||||
{:filter, :eldap.equalityMatch(to_charlist(uid), to_charlist(name))},
|
||||
{:scope, :eldap.wholeSubtree()},
|
||||
{:attributes, ['mail', 'email']},
|
||||
{:timeout, @search_timeout}
|
||||
]) do
|
||||
{:ok, {:eldap_search_result, [{:eldap_entry, _, attributes}], _}} ->
|
||||
with {_, [mail]} <- List.keyfind(attributes, 'mail', 0) do
|
||||
params = %{
|
||||
email: :erlang.list_to_binary(mail),
|
||||
name: name,
|
||||
nickname: name,
|
||||
password: password,
|
||||
password_confirmation: password
|
||||
}
|
||||
|
||||
changeset = User.register_changeset(%User{}, params)
|
||||
|
||||
case User.register(changeset) do
|
||||
{:ok, user} -> user
|
||||
error -> error
|
||||
end
|
||||
else
|
||||
_ ->
|
||||
Logger.error("Could not find LDAP attribute mail: #{inspect(attributes)}")
|
||||
{:error, :ldap_registration_missing_attributes}
|
||||
end
|
||||
|
||||
error ->
|
||||
error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -3,13 +3,20 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Auth.PleromaAuthenticator do
|
||||
alias Pleroma.User
|
||||
alias Comeonin.Pbkdf2
|
||||
alias Pleroma.User
|
||||
|
||||
@behaviour Pleroma.Web.Auth.Authenticator
|
||||
|
||||
def get_user(%Plug.Conn{} = conn) do
|
||||
%{"authorization" => %{"name" => name, "password" => password}} = conn.params
|
||||
{name, password} =
|
||||
case conn.params do
|
||||
%{"authorization" => %{"name" => name, "password" => password}} ->
|
||||
{name, password}
|
||||
|
||||
%{"grant_type" => "password", "username" => name, "password" => password} ->
|
||||
{name, password}
|
||||
end
|
||||
|
||||
with {_, %User{} = user} <- {:user, User.get_by_nickname_or_email(name)},
|
||||
{_, true} <- {:checkpw, Pbkdf2.checkpw(password, user.password_hash)} do
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ defmodule Pleroma.Web.UserSocket do
|
|||
# performing token verification on connect.
|
||||
def connect(%{"token" => token}, socket) do
|
||||
with true <- Pleroma.Config.get([:chat, :enabled]),
|
||||
{:ok, user_id} <- Phoenix.Token.verify(socket, "user socket", token, max_age: 84600),
|
||||
{:ok, user_id} <- Phoenix.Token.verify(socket, "user socket", token, max_age: 84_600),
|
||||
%User{} = user <- Pleroma.Repo.get(User, user_id) do
|
||||
{:ok, assign(socket, :user_name, user.nickname)}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
defmodule Pleroma.Web.ChatChannel do
|
||||
use Phoenix.Channel
|
||||
alias Pleroma.Web.ChatChannel.ChatChannelState
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ChatChannel.ChatChannelState
|
||||
|
||||
def join("chat:public", _message, socket) do
|
||||
send(self(), :after_join)
|
||||
|
|
@ -48,7 +48,7 @@ defmodule Pleroma.Web.ChatChannel.ChatChannelState do
|
|||
end)
|
||||
end
|
||||
|
||||
def messages() do
|
||||
def messages do
|
||||
Agent.get(__MODULE__, fn state -> state[:messages] |> Enum.reverse() end)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.CommonAPI do
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Formatter
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.ThreadMute
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Formatter
|
||||
|
||||
import Pleroma.Web.CommonAPI.Utils
|
||||
|
||||
|
|
@ -27,6 +27,42 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
end
|
||||
end
|
||||
|
||||
def unfollow(follower, unfollowed) do
|
||||
with {:ok, follower, _follow_activity} <- User.unfollow(follower, unfollowed),
|
||||
{:ok, _activity} <- ActivityPub.unfollow(follower, unfollowed) do
|
||||
{:ok, follower}
|
||||
end
|
||||
end
|
||||
|
||||
def accept_follow_request(follower, followed) do
|
||||
with {:ok, follower} <- User.maybe_follow(follower, followed),
|
||||
%Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed),
|
||||
{:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "accept"),
|
||||
{:ok, _activity} <-
|
||||
ActivityPub.accept(%{
|
||||
to: [follower.ap_id],
|
||||
actor: followed,
|
||||
object: follow_activity.data["id"],
|
||||
type: "Accept"
|
||||
}) do
|
||||
{:ok, follower}
|
||||
end
|
||||
end
|
||||
|
||||
def reject_follow_request(follower, followed) do
|
||||
with %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed),
|
||||
{:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "reject"),
|
||||
{:ok, _activity} <-
|
||||
ActivityPub.reject(%{
|
||||
to: [follower.ap_id],
|
||||
actor: followed,
|
||||
object: follow_activity.data["id"],
|
||||
type: "Reject"
|
||||
}) do
|
||||
{:ok, follower}
|
||||
end
|
||||
end
|
||||
|
||||
def delete(activity_id, user) do
|
||||
with %Activity{data: %{"object" => %{"id" => object_id}}} <- Repo.get(Activity, activity_id),
|
||||
%Object{} = object <- Object.normalize(object_id),
|
||||
|
|
@ -88,8 +124,8 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
nil ->
|
||||
"public"
|
||||
|
||||
inReplyTo ->
|
||||
Pleroma.Web.MastodonAPI.StatusView.get_visibility(inReplyTo.data["object"])
|
||||
in_reply_to ->
|
||||
Pleroma.Web.MastodonAPI.StatusView.get_visibility(in_reply_to.data["object"])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -101,15 +137,15 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
|
||||
with status <- String.trim(status),
|
||||
attachments <- attachments_from_ids(data),
|
||||
inReplyTo <- get_replied_to_activity(data["in_reply_to_status_id"]),
|
||||
in_reply_to <- get_replied_to_activity(data["in_reply_to_status_id"]),
|
||||
{content_html, mentions, tags} <-
|
||||
make_content_html(
|
||||
status,
|
||||
attachments,
|
||||
data
|
||||
),
|
||||
{to, cc} <- to_for_user_and_mentions(user, mentions, inReplyTo, visibility),
|
||||
context <- make_context(inReplyTo),
|
||||
{to, cc} <- to_for_user_and_mentions(user, mentions, in_reply_to, visibility),
|
||||
context <- make_context(in_reply_to),
|
||||
cw <- data["spoiler_text"],
|
||||
full_payload <- String.trim(status <> (data["spoiler_text"] || "")),
|
||||
length when length in 1..limit <- String.length(full_payload),
|
||||
|
|
@ -120,7 +156,7 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
context,
|
||||
content_html,
|
||||
attachments,
|
||||
inReplyTo,
|
||||
in_reply_to,
|
||||
tags,
|
||||
cw,
|
||||
cc
|
||||
|
|
@ -248,14 +284,9 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
actor: user,
|
||||
account: account,
|
||||
statuses: statuses,
|
||||
content: content_html
|
||||
content: content_html,
|
||||
forward: data["forward"] || false
|
||||
}) do
|
||||
Enum.each(User.all_superusers(), fn superuser ->
|
||||
superuser
|
||||
|> Pleroma.AdminEmail.report(user, account, statuses, content_html)
|
||||
|> Pleroma.Mailer.deliver_async()
|
||||
end)
|
||||
|
||||
{:ok, activity}
|
||||
else
|
||||
{:error, err} -> {:error, err}
|
||||
|
|
@ -263,4 +294,24 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
{:account, nil} -> {:error, "Account not found"}
|
||||
end
|
||||
end
|
||||
|
||||
def hide_reblogs(user, muted) do
|
||||
ap_id = muted.ap_id
|
||||
|
||||
if ap_id not in user.info.muted_reblogs do
|
||||
info_changeset = User.Info.add_reblog_mute(user.info, ap_id)
|
||||
changeset = Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset)
|
||||
User.update_and_set_cache(changeset)
|
||||
end
|
||||
end
|
||||
|
||||
def show_reblogs(user, muted) do
|
||||
ap_id = muted.ap_id
|
||||
|
||||
if ap_id in user.info.muted_reblogs do
|
||||
info_changeset = User.Info.remove_reblog_mute(user.info, ap_id)
|
||||
changeset = Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset)
|
||||
User.update_and_set_cache(changeset)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
|||
alias Calendar.Strftime
|
||||
alias Comeonin.Pbkdf2
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Formatter
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.Endpoint
|
||||
alias Pleroma.Web.MediaProxy
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
|
||||
# This is a hack for twidere.
|
||||
def get_by_id_or_ap_id(id) do
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ defmodule Pleroma.Web.ControllerHelper do
|
|||
use Pleroma.Web, :controller
|
||||
|
||||
def oauth_scopes(params, default) do
|
||||
# Note: `scopes` is used by Mastodon — supporting it but sticking to OAuth's standard `scope` wherever we control it
|
||||
# Note: `scopes` is used by Mastodon — supporting it but sticking to
|
||||
# OAuth's standard `scope` wherever we control it
|
||||
Pleroma.Web.OAuth.parse_scopes(params["scope"] || params["scopes"], default)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ defmodule Pleroma.Web.Endpoint do
|
|||
at: "/",
|
||||
from: "priv_sid/static",
|
||||
only:
|
||||
~w(index.html static finmoji emoji packs sounds images instance sw.js sw-pleroma.js favicon.png schemas doc)
|
||||
~w(index.html robots.txt static finmoji emoji packs sounds images instance sw.js sw-pleroma.js favicon.png schemas doc)
|
||||
# credo:disable-for-previous-line Credo.Check.Readability.MaxLineLength
|
||||
)
|
||||
|
||||
# Code reloading can be explicitly enabled under the
|
||||
|
|
|
|||
|
|
@ -4,27 +4,27 @@
|
|||
|
||||
defmodule Pleroma.Web.Federator do
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Jobs
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.WebFinger
|
||||
alias Pleroma.Web.Websub
|
||||
alias Pleroma.Web.Salmon
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.ActivityPub.Relay
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.Federator.RetryQueue
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Jobs
|
||||
alias Pleroma.Web.Salmon
|
||||
alias Pleroma.Web.WebFinger
|
||||
alias Pleroma.Web.Websub
|
||||
|
||||
require Logger
|
||||
|
||||
@websub Application.get_env(:pleroma, :websub)
|
||||
@ostatus Application.get_env(:pleroma, :ostatus)
|
||||
|
||||
def init() do
|
||||
def init do
|
||||
# 1 minute
|
||||
Process.sleep(1000 * 60 * 1)
|
||||
Process.sleep(1000 * 60)
|
||||
refresh_subscriptions()
|
||||
end
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ defmodule Pleroma.Web.Federator do
|
|||
Jobs.enqueue(:federator_outgoing, __MODULE__, [:request_subscription, sub])
|
||||
end
|
||||
|
||||
def refresh_subscriptions() do
|
||||
def refresh_subscriptions do
|
||||
Jobs.enqueue(:federator_outgoing, __MODULE__, [:refresh_subscriptions])
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ defmodule Pleroma.Web.Federator.RetryQueue do
|
|||
{:ok, %{args | queue_table: queue_table, running_jobs: :sets.new()}}
|
||||
end
|
||||
|
||||
def start_link() do
|
||||
def start_link do
|
||||
enabled =
|
||||
if Mix.env() == :test, do: true, else: Pleroma.Config.get([__MODULE__, :enabled], false)
|
||||
|
||||
|
|
@ -39,11 +39,11 @@ defmodule Pleroma.Web.Federator.RetryQueue do
|
|||
GenServer.cast(__MODULE__, {:maybe_enqueue, data, transport, retries + 1})
|
||||
end
|
||||
|
||||
def get_stats() do
|
||||
def get_stats do
|
||||
GenServer.call(__MODULE__, :get_stats)
|
||||
end
|
||||
|
||||
def reset_stats() do
|
||||
def reset_stats do
|
||||
GenServer.call(__MODULE__, :reset_stats)
|
||||
end
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ defmodule Pleroma.Web.Federator.RetryQueue do
|
|||
end
|
||||
end
|
||||
|
||||
def get_retry_timer_interval() do
|
||||
def get_retry_timer_interval do
|
||||
Pleroma.Config.get([:retry_queue, :interval], 1000)
|
||||
end
|
||||
|
||||
|
|
@ -231,7 +231,7 @@ defmodule Pleroma.Web.Federator.RetryQueue do
|
|||
end
|
||||
end
|
||||
|
||||
defp maybe_kickoff_timer() do
|
||||
defp maybe_kickoff_timer do
|
||||
GenServer.cast(__MODULE__, :kickoff_timer)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,61 +2,49 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
|
|||
import Ecto.Query
|
||||
import Ecto.Changeset
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Pagination
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Repo
|
||||
|
||||
@default_limit 20
|
||||
|
||||
def get_followers(user, params \\ %{}) do
|
||||
user
|
||||
|> User.get_followers_query()
|
||||
|> paginate(params)
|
||||
|> Repo.all()
|
||||
|> Pagination.fetch_paginated(params)
|
||||
end
|
||||
|
||||
def get_friends(user, params \\ %{}) do
|
||||
user
|
||||
|> User.get_friends_query()
|
||||
|> paginate(params)
|
||||
|> Repo.all()
|
||||
|> Pagination.fetch_paginated(params)
|
||||
end
|
||||
|
||||
def paginate(query, params \\ %{}) do
|
||||
def get_notifications(user, params \\ %{}) do
|
||||
options = cast_params(params)
|
||||
|
||||
query
|
||||
|> restrict(:max_id, options)
|
||||
|> restrict(:since_id, options)
|
||||
|> restrict(:limit, options)
|
||||
|> order_by([u], fragment("? desc nulls last", u.id))
|
||||
user
|
||||
|> Notification.for_user_query()
|
||||
|> restrict(:exclude_types, options)
|
||||
|> Pagination.fetch_paginated(params)
|
||||
end
|
||||
|
||||
def cast_params(params) do
|
||||
defp cast_params(params) do
|
||||
param_types = %{
|
||||
max_id: :string,
|
||||
since_id: :string,
|
||||
limit: :integer
|
||||
exclude_types: {:array, :string}
|
||||
}
|
||||
|
||||
changeset = cast({%{}, param_types}, params, Map.keys(param_types))
|
||||
changeset.changes
|
||||
end
|
||||
|
||||
defp restrict(query, :max_id, %{max_id: max_id}) do
|
||||
query
|
||||
|> where([q], q.id < ^max_id)
|
||||
end
|
||||
|
||||
defp restrict(query, :since_id, %{since_id: since_id}) do
|
||||
query
|
||||
|> where([q], q.id > ^since_id)
|
||||
end
|
||||
|
||||
defp restrict(query, :limit, options) do
|
||||
limit = Map.get(options, :limit, @default_limit)
|
||||
defp restrict(query, :exclude_types, %{exclude_types: mastodon_types = [_ | _]}) do
|
||||
ap_types =
|
||||
mastodon_types
|
||||
|> Enum.map(&Activity.from_mastodon_notification_type/1)
|
||||
|> Enum.filter(& &1)
|
||||
|
||||
query
|
||||
|> limit(^limit)
|
||||
|> where([q, a], not fragment("? @> ARRAY[?->>'type']::varchar[]", ^ap_types, a.data))
|
||||
end
|
||||
|
||||
defp restrict(query, _, _), do: query
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Filter
|
||||
|
|
@ -13,19 +14,18 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
alias Pleroma.Stats
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.MediaProxy
|
||||
|
||||
alias Pleroma.Web.MastodonAPI.AccountView
|
||||
alias Pleroma.Web.MastodonAPI.FilterView
|
||||
alias Pleroma.Web.MastodonAPI.ListView
|
||||
alias Pleroma.Web.MastodonAPI.MastodonView
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
alias Pleroma.Web.MastodonAPI.ReportView
|
||||
alias Pleroma.Web.MastodonAPI.MastodonAPI
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.MastodonAPI.MastodonView
|
||||
alias Pleroma.Web.MastodonAPI.NotificationView
|
||||
alias Pleroma.Web.MastodonAPI.ReportView
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
alias Pleroma.Web.MediaProxy
|
||||
alias Pleroma.Web.OAuth.App
|
||||
alias Pleroma.Web.OAuth.Authorization
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
|
|
@ -502,21 +502,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
end
|
||||
|
||||
def notifications(%{assigns: %{user: user}} = conn, params) do
|
||||
notifications = Notification.for_user(user, params)
|
||||
|
||||
result =
|
||||
notifications
|
||||
|> Enum.map(fn x -> render_notification(user, x) end)
|
||||
|> Enum.filter(& &1)
|
||||
notifications = MastodonAPI.get_notifications(user, params)
|
||||
|
||||
conn
|
||||
|> add_link_headers(:notifications, notifications)
|
||||
|> json(result)
|
||||
|> put_view(NotificationView)
|
||||
|> render("index.json", %{notifications: notifications, for: user})
|
||||
end
|
||||
|
||||
def get_notification(%{assigns: %{user: user}} = conn, %{"id" => id} = _params) do
|
||||
with {:ok, notification} <- Notification.get(user, id) do
|
||||
json(conn, render_notification(user, notification))
|
||||
conn
|
||||
|> put_view(NotificationView)
|
||||
|> render("show.json", %{notification: notification, for: user})
|
||||
else
|
||||
{:error, reason} ->
|
||||
conn
|
||||
|
|
@ -697,16 +695,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
|
||||
def authorize_follow_request(%{assigns: %{user: followed}} = conn, %{"id" => id}) do
|
||||
with %User{} = follower <- Repo.get(User, id),
|
||||
{:ok, follower} <- User.maybe_follow(follower, followed),
|
||||
%Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed),
|
||||
{:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "accept"),
|
||||
{:ok, _activity} <-
|
||||
ActivityPub.accept(%{
|
||||
to: [follower.ap_id],
|
||||
actor: followed,
|
||||
object: follow_activity.data["id"],
|
||||
type: "Accept"
|
||||
}) do
|
||||
{:ok, follower} <- CommonAPI.accept_follow_request(follower, followed) do
|
||||
conn
|
||||
|> put_view(AccountView)
|
||||
|> render("relationship.json", %{user: followed, target: follower})
|
||||
|
|
@ -720,15 +709,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
|
||||
def reject_follow_request(%{assigns: %{user: followed}} = conn, %{"id" => id}) do
|
||||
with %User{} = follower <- Repo.get(User, id),
|
||||
%Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed),
|
||||
{:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "reject"),
|
||||
{:ok, _activity} <-
|
||||
ActivityPub.reject(%{
|
||||
to: [follower.ap_id],
|
||||
actor: followed,
|
||||
object: follow_activity.data["id"],
|
||||
type: "Reject"
|
||||
}) do
|
||||
{:ok, follower} <- CommonAPI.reject_follow_request(follower, followed) do
|
||||
conn
|
||||
|> put_view(AccountView)
|
||||
|> render("relationship.json", %{user: followed, target: follower})
|
||||
|
|
@ -742,11 +723,25 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
|
||||
def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
|
||||
with %User{} = followed <- Repo.get(User, id),
|
||||
false <- User.following?(follower, followed),
|
||||
{:ok, follower, followed, _} <- CommonAPI.follow(follower, followed) do
|
||||
conn
|
||||
|> put_view(AccountView)
|
||||
|> render("relationship.json", %{user: follower, target: followed})
|
||||
else
|
||||
true ->
|
||||
followed = User.get_cached_by_id(id)
|
||||
|
||||
{:ok, follower} =
|
||||
case conn.params["reblogs"] do
|
||||
true -> CommonAPI.show_reblogs(follower, followed)
|
||||
false -> CommonAPI.hide_reblogs(follower, followed)
|
||||
end
|
||||
|
||||
conn
|
||||
|> put_view(AccountView)
|
||||
|> render("relationship.json", %{user: follower, target: followed})
|
||||
|
||||
{:error, message} ->
|
||||
conn
|
||||
|> put_resp_content_type("application/json")
|
||||
|
|
@ -770,8 +765,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
|
||||
def unfollow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
|
||||
with %User{} = followed <- Repo.get(User, id),
|
||||
{:ok, _activity} <- ActivityPub.unfollow(follower, followed),
|
||||
{:ok, follower, _} <- User.unfollow(follower, followed) do
|
||||
{:ok, follower} <- CommonAPI.unfollow(follower, followed) do
|
||||
conn
|
||||
|> put_view(AccountView)
|
||||
|> render("relationship.json", %{user: follower, target: followed})
|
||||
|
|
@ -1129,7 +1123,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
compose: %{
|
||||
me: "#{user.id}",
|
||||
default_privacy: user.info.default_scope,
|
||||
default_sensitive: false
|
||||
default_sensitive: false,
|
||||
allow_content_types: Config.get([:instance, :allowed_post_formats])
|
||||
},
|
||||
media_attachments: %{
|
||||
accept_content_types: [
|
||||
|
|
@ -1274,7 +1269,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
end
|
||||
end
|
||||
|
||||
defp get_or_make_app() do
|
||||
defp get_or_make_app do
|
||||
find_attrs = %{client_name: @local_mastodon_name, redirect_uris: "."}
|
||||
scopes = ["read", "write", "follow", "push"]
|
||||
|
||||
|
|
@ -1327,45 +1322,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
json(conn, %{})
|
||||
end
|
||||
|
||||
def render_notification(user, %{id: id, activity: activity, inserted_at: created_at} = _params) do
|
||||
actor = User.get_cached_by_ap_id(activity.data["actor"])
|
||||
parent_activity = Activity.get_create_by_object_ap_id(activity.data["object"])
|
||||
mastodon_type = Activity.mastodon_notification_type(activity)
|
||||
|
||||
response = %{
|
||||
id: to_string(id),
|
||||
type: mastodon_type,
|
||||
created_at: CommonAPI.Utils.to_masto_date(created_at),
|
||||
account: AccountView.render("account.json", %{user: actor, for: user})
|
||||
}
|
||||
|
||||
case mastodon_type do
|
||||
"mention" ->
|
||||
response
|
||||
|> Map.merge(%{
|
||||
status: StatusView.render("status.json", %{activity: activity, for: user})
|
||||
})
|
||||
|
||||
"favourite" ->
|
||||
response
|
||||
|> Map.merge(%{
|
||||
status: StatusView.render("status.json", %{activity: parent_activity, for: user})
|
||||
})
|
||||
|
||||
"reblog" ->
|
||||
response
|
||||
|> Map.merge(%{
|
||||
status: StatusView.render("status.json", %{activity: parent_activity, for: user})
|
||||
})
|
||||
|
||||
"follow" ->
|
||||
response
|
||||
|
||||
_ ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def get_filters(%{assigns: %{user: user}} = conn, _) do
|
||||
filters = Filter.get_filters(user)
|
||||
res = FilterView.render("filters.json", filters: filters)
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
muting_notifications: false,
|
||||
requested: requested,
|
||||
domain_blocking: false,
|
||||
showing_reblogs: false,
|
||||
showing_reblogs: User.showing_reblogs?(user, target),
|
||||
endorsed: false
|
||||
}
|
||||
end
|
||||
|
|
|
|||
64
lib/pleroma/web/mastodon_api/views/notification_view.ex
Normal file
64
lib/pleroma/web/mastodon_api/views/notification_view.ex
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.NotificationView do
|
||||
use Pleroma.Web, :view
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.MastodonAPI.AccountView
|
||||
alias Pleroma.Web.MastodonAPI.NotificationView
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
|
||||
def render("index.json", %{notifications: notifications, for: user}) do
|
||||
render_many(notifications, NotificationView, "show.json", %{for: user})
|
||||
end
|
||||
|
||||
def render("show.json", %{
|
||||
notification: %Notification{activity: activity} = notification,
|
||||
for: user
|
||||
}) do
|
||||
actor = User.get_cached_by_ap_id(activity.data["actor"])
|
||||
parent_activity = Activity.get_create_by_object_ap_id(activity.data["object"])
|
||||
mastodon_type = Activity.mastodon_notification_type(activity)
|
||||
|
||||
response = %{
|
||||
id: to_string(notification.id),
|
||||
type: mastodon_type,
|
||||
created_at: CommonAPI.Utils.to_masto_date(notification.inserted_at),
|
||||
account: AccountView.render("account.json", %{user: actor, for: user}),
|
||||
pleroma: %{
|
||||
is_seen: notification.seen
|
||||
}
|
||||
}
|
||||
|
||||
case mastodon_type do
|
||||
"mention" ->
|
||||
response
|
||||
|> Map.merge(%{
|
||||
status: StatusView.render("status.json", %{activity: activity, for: user})
|
||||
})
|
||||
|
||||
"favourite" ->
|
||||
response
|
||||
|> Map.merge(%{
|
||||
status: StatusView.render("status.json", %{activity: parent_activity, for: user})
|
||||
})
|
||||
|
||||
"reblog" ->
|
||||
response
|
||||
|> Map.merge(%{
|
||||
status: StatusView.render("status.json", %{activity: parent_activity, for: user})
|
||||
})
|
||||
|
||||
"follow" ->
|
||||
response
|
||||
|
||||
_ ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -257,7 +257,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
preview_url: href,
|
||||
text_url: href,
|
||||
type: type,
|
||||
description: attachment["name"]
|
||||
description: attachment["name"],
|
||||
pleroma: %{mime_type: media_type}
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
|
||||
require Logger
|
||||
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
|
||||
@behaviour :cowboy_websocket
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ defmodule Pleroma.Web.MediaProxy do
|
|||
else
|
||||
secret = Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base]
|
||||
|
||||
# Must preserve `%2F` for compatibility with S3 (https://git.pleroma.social/pleroma/pleroma/issues/580)
|
||||
# Must preserve `%2F` for compatibility with S3
|
||||
# https://git.pleroma.social/pleroma/pleroma/issues/580
|
||||
replacement = get_replacement(url, ":2F:")
|
||||
|
||||
# The URL is url-decoded and encoded again to ensure it is correctly encoded and not twice.
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ defmodule Pleroma.Web.Metadata.Providers.OpenGraph do
|
|||
|
||||
# TODO: Add additional properties to objects when we have the data available.
|
||||
# Also, Whatsapp only wants JPEG or PNGs. It seems that if we add a second og:image
|
||||
# object when a Video or GIF is attached it will display that in the Whatsapp Rich Preview.
|
||||
# object when a Video or GIF is attached it will display that in Whatsapp Rich Preview.
|
||||
case media_type do
|
||||
"audio" ->
|
||||
[
|
||||
|
|
|
|||
|
|
@ -97,7 +97,8 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
|
|||
| acc
|
||||
]
|
||||
|
||||
# TODO: Need the true width and height values here or Twitter renders an iFrame with a bad aspect ratio
|
||||
# TODO: Need the true width and height values here or Twitter renders an iFrame with
|
||||
# a bad aspect ratio
|
||||
"video" ->
|
||||
[
|
||||
{:meta, [property: "twitter:card", content: "player"], []},
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright \xc2\xa9 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Metadata.Utils do
|
||||
alias Pleroma.HTML
|
||||
alias Pleroma.Formatter
|
||||
alias Pleroma.HTML
|
||||
alias Pleroma.Web.MediaProxy
|
||||
|
||||
def scrub_html_and_truncate(%{data: %{"content" => content}} = object) do
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
|
||||
|
|
@ -5,10 +5,10 @@
|
|||
defmodule Pleroma.Web.OAuth.Authorization do
|
||||
use Ecto.Schema
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Web.OAuth.Authorization
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.OAuth.App
|
||||
alias Pleroma.Web.OAuth.Authorization
|
||||
|
||||
import Ecto.Changeset
|
||||
import Ecto.Query
|
||||
|
|
@ -16,7 +16,7 @@ defmodule Pleroma.Web.OAuth.Authorization do
|
|||
schema "oauth_authorizations" do
|
||||
field(:token, :string)
|
||||
field(:scopes, {:array, :string}, default: [])
|
||||
field(:valid_until, :naive_datetime)
|
||||
field(:valid_until, :naive_datetime_usec)
|
||||
field(:used, :boolean, default: false)
|
||||
belongs_to(:user, Pleroma.User, type: Pleroma.FlakeId)
|
||||
belongs_to(:app, App)
|
||||
|
|
|
|||
|
|
@ -5,13 +5,12 @@
|
|||
defmodule Pleroma.Web.OAuth.OAuthController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
alias Pleroma.Web.Auth.Authenticator
|
||||
alias Pleroma.Web.OAuth.Authorization
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
alias Pleroma.Web.OAuth.App
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Comeonin.Pbkdf2
|
||||
alias Pleroma.Web.Auth.Authenticator
|
||||
alias Pleroma.Web.OAuth.App
|
||||
alias Pleroma.Web.OAuth.Authorization
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
|
||||
import Pleroma.Web.ControllerHelper, only: [oauth_scopes: 2]
|
||||
|
||||
|
|
@ -105,6 +104,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
|
|||
fixed_token = fix_padding(params["code"]),
|
||||
%Authorization{} = auth <-
|
||||
Repo.get_by(Authorization, token: fixed_token, app_id: app.id),
|
||||
%User{} = user <- Repo.get(User, auth.user_id),
|
||||
{:ok, token} <- Token.exchange_token(app, auth),
|
||||
{:ok, inserted_at} <- DateTime.from_naive(token.inserted_at, "Etc/UTC") do
|
||||
response = %{
|
||||
|
|
@ -113,7 +113,8 @@ defmodule Pleroma.Web.OAuth.OAuthController do
|
|||
refresh_token: token.refresh_token,
|
||||
created_at: DateTime.to_unix(inserted_at),
|
||||
expires_in: 60 * 10,
|
||||
scope: Enum.join(token.scopes, " ")
|
||||
scope: Enum.join(token.scopes, " "),
|
||||
me: user.ap_id
|
||||
}
|
||||
|
||||
json(conn, response)
|
||||
|
|
@ -126,11 +127,10 @@ defmodule Pleroma.Web.OAuth.OAuthController do
|
|||
|
||||
def token_exchange(
|
||||
conn,
|
||||
%{"grant_type" => "password", "username" => name, "password" => password} = params
|
||||
%{"grant_type" => "password"} = params
|
||||
) do
|
||||
with %App{} = app <- get_app_from_request(conn, params),
|
||||
%User{} = user <- User.get_by_nickname_or_email(name),
|
||||
true <- Pbkdf2.checkpw(password, user.password_hash),
|
||||
with {_, {:ok, %User{} = user}} <- {:get_user, Authenticator.get_user(conn)},
|
||||
%App{} = app <- get_app_from_request(conn, params),
|
||||
{:auth_active, true} <- {:auth_active, User.auth_active?(user)},
|
||||
scopes <- oauth_scopes(params, app.scopes),
|
||||
[] <- scopes -- app.scopes,
|
||||
|
|
@ -142,7 +142,8 @@ defmodule Pleroma.Web.OAuth.OAuthController do
|
|||
access_token: token.token,
|
||||
refresh_token: token.refresh_token,
|
||||
expires_in: 60 * 10,
|
||||
scope: Enum.join(token.scopes, " ")
|
||||
scope: Enum.join(token.scopes, " "),
|
||||
me: user.ap_id
|
||||
}
|
||||
|
||||
json(conn, response)
|
||||
|
|
|
|||
|
|
@ -7,17 +7,17 @@ defmodule Pleroma.Web.OAuth.Token do
|
|||
|
||||
import Ecto.Query
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.OAuth.App
|
||||
alias Pleroma.Web.OAuth.Authorization
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
|
||||
schema "oauth_tokens" do
|
||||
field(:token, :string)
|
||||
field(:refresh_token, :string)
|
||||
field(:scopes, {:array, :string}, default: [])
|
||||
field(:valid_until, :naive_datetime)
|
||||
field(:valid_until, :naive_datetime_usec)
|
||||
belongs_to(:user, Pleroma.User, type: Pleroma.FlakeId)
|
||||
belongs_to(:app, App)
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
defmodule Pleroma.Web.OStatus.ActivityRepresenter do
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.OStatus.UserRepresenter
|
||||
|
||||
require Logger
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
defmodule Pleroma.Web.OStatus.FeedRepresenter do
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.MediaProxy
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.OStatus.ActivityRepresenter
|
||||
alias Pleroma.Web.OStatus.UserRepresenter
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
defmodule Pleroma.Web.OStatus.DeleteHandler do
|
||||
require Logger
|
||||
alias Pleroma.Web.XML
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.XML
|
||||
|
||||
def handle_delete(entry, _doc \\ nil) do
|
||||
with id <- XML.string_from_xpath("//id", entry),
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.OStatus.FollowHandler do
|
||||
alias Pleroma.Web.XML
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.XML
|
||||
|
||||
def handle(entry, doc) do
|
||||
with {:ok, actor} <- OStatus.find_make_or_update_user(doc),
|
||||
|
|
|
|||
|
|
@ -4,13 +4,14 @@
|
|||
|
||||
defmodule Pleroma.Web.OStatus.NoteHandler do
|
||||
require Logger
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.XML
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.XML
|
||||
|
||||
@doc """
|
||||
Get the context for this note. Uses this:
|
||||
|
|
@ -18,13 +19,13 @@ defmodule Pleroma.Web.OStatus.NoteHandler do
|
|||
2. The conversation reference in the ostatus xml
|
||||
3. A newly generated context id.
|
||||
"""
|
||||
def get_context(entry, inReplyTo) do
|
||||
def get_context(entry, in_reply_to) do
|
||||
context =
|
||||
(XML.string_from_xpath("//ostatus:conversation[1]", entry) ||
|
||||
XML.string_from_xpath("//ostatus:conversation[1]/@ref", entry) || "")
|
||||
|> String.trim()
|
||||
|
||||
with %{data: %{"context" => context}} <- Object.get_cached_by_ap_id(inReplyTo) do
|
||||
with %{data: %{"context" => context}} <- Object.get_cached_by_ap_id(in_reply_to) do
|
||||
context
|
||||
else
|
||||
_e ->
|
||||
|
|
@ -87,14 +88,14 @@ defmodule Pleroma.Web.OStatus.NoteHandler do
|
|||
Map.put(note, "external_url", url)
|
||||
end
|
||||
|
||||
def fetch_replied_to_activity(entry, inReplyTo) do
|
||||
with %Activity{} = activity <- Activity.get_create_by_object_ap_id(inReplyTo) do
|
||||
def fetch_replied_to_activity(entry, in_reply_to) do
|
||||
with %Activity{} = activity <- Activity.get_create_by_object_ap_id(in_reply_to) do
|
||||
activity
|
||||
else
|
||||
_e ->
|
||||
with inReplyToHref when not is_nil(inReplyToHref) <-
|
||||
with in_reply_to_href when not is_nil(in_reply_to_href) <-
|
||||
XML.string_from_xpath("//thr:in-reply-to[1]/@href", entry),
|
||||
{:ok, [activity | _]} <- OStatus.fetch_activity_from_url(inReplyToHref) do
|
||||
{:ok, [activity | _]} <- OStatus.fetch_activity_from_url(in_reply_to_href) do
|
||||
activity
|
||||
else
|
||||
_e -> nil
|
||||
|
|
@ -110,11 +111,12 @@ defmodule Pleroma.Web.OStatus.NoteHandler do
|
|||
{:ok, actor} <- OStatus.find_make_or_update_user(author),
|
||||
content_html <- OStatus.get_content(entry),
|
||||
cw <- OStatus.get_cw(entry),
|
||||
inReplyTo <- XML.string_from_xpath("//thr:in-reply-to[1]/@ref", entry),
|
||||
inReplyToActivity <- fetch_replied_to_activity(entry, inReplyTo),
|
||||
inReplyTo <- (inReplyToActivity && inReplyToActivity.data["object"]["id"]) || inReplyTo,
|
||||
in_reply_to <- XML.string_from_xpath("//thr:in-reply-to[1]/@ref", entry),
|
||||
in_reply_to_activity <- fetch_replied_to_activity(entry, in_reply_to),
|
||||
in_reply_to <-
|
||||
(in_reply_to_activity && in_reply_to_activity.data["object"]["id"]) || in_reply_to,
|
||||
attachments <- OStatus.get_attachments(entry),
|
||||
context <- get_context(entry, inReplyTo),
|
||||
context <- get_context(entry, in_reply_to),
|
||||
tags <- OStatus.get_tags(entry),
|
||||
mentions <- get_mentions(entry),
|
||||
to <- make_to_list(actor, mentions),
|
||||
|
|
@ -128,7 +130,7 @@ defmodule Pleroma.Web.OStatus.NoteHandler do
|
|||
context,
|
||||
content_html,
|
||||
attachments,
|
||||
inReplyToActivity,
|
||||
in_reply_to_activity,
|
||||
[],
|
||||
cw
|
||||
),
|
||||
|
|
@ -140,8 +142,8 @@ defmodule Pleroma.Web.OStatus.NoteHandler do
|
|||
# TODO: Handle this case in make_note_data
|
||||
note <-
|
||||
if(
|
||||
inReplyTo && !inReplyToActivity,
|
||||
do: note |> Map.put("inReplyTo", inReplyTo),
|
||||
in_reply_to && !in_reply_to_activity,
|
||||
do: note |> Map.put("inReplyTo", in_reply_to),
|
||||
else: note
|
||||
) do
|
||||
ActivityPub.create(%{
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.OStatus.UnfollowHandler do
|
||||
alias Pleroma.Web.XML
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.XML
|
||||
|
||||
def handle(entry, doc) do
|
||||
with {:ok, actor} <- OStatus.find_make_or_update_user(doc),
|
||||
|
|
|
|||
|
|
@ -9,19 +9,19 @@ defmodule Pleroma.Web.OStatus do
|
|||
import Pleroma.Web.XML
|
||||
require Logger
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.OStatus.DeleteHandler
|
||||
alias Pleroma.Web.OStatus.FollowHandler
|
||||
alias Pleroma.Web.OStatus.NoteHandler
|
||||
alias Pleroma.Web.OStatus.UnfollowHandler
|
||||
alias Pleroma.Web.WebFinger
|
||||
alias Pleroma.Web.Websub
|
||||
alias Pleroma.Web.OStatus.FollowHandler
|
||||
alias Pleroma.Web.OStatus.UnfollowHandler
|
||||
alias Pleroma.Web.OStatus.NoteHandler
|
||||
alias Pleroma.Web.OStatus.DeleteHandler
|
||||
|
||||
def is_representable?(%Activity{data: data}) do
|
||||
object = Object.normalize(data["object"])
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@ defmodule Pleroma.Web.OStatus.OStatusController do
|
|||
alias Pleroma.Object
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.ActivityPub.ActivityPubController
|
||||
alias Pleroma.Web.ActivityPub.ObjectView
|
||||
alias Pleroma.Web.OStatus.ActivityRepresenter
|
||||
alias Pleroma.Web.OStatus.FeedRepresenter
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.Federator
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.OStatus.ActivityRepresenter
|
||||
alias Pleroma.Web.OStatus.FeedRepresenter
|
||||
alias Pleroma.Web.XML
|
||||
|
||||
plug(Pleroma.Web.FederatingPlug when action in [:salmon_incoming])
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@
|
|||
defmodule Pleroma.Web.Push.Impl do
|
||||
@moduledoc "The module represents implementation push web notification"
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.Push.Subscription
|
||||
alias Pleroma.Web.Metadata.Utils
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Web.Push.Subscription
|
||||
|
||||
require Logger
|
||||
import Ecto.Query
|
||||
|
|
|
|||
|
|
@ -13,15 +13,15 @@ defmodule Pleroma.Web.Push do
|
|||
# Client API #
|
||||
##############
|
||||
|
||||
def start_link() do
|
||||
def start_link do
|
||||
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
|
||||
end
|
||||
|
||||
def vapid_config() do
|
||||
def vapid_config do
|
||||
Application.get_env(:web_push_encryption, :vapid_details, [])
|
||||
end
|
||||
|
||||
def enabled() do
|
||||
def enabled do
|
||||
case vapid_config() do
|
||||
[] -> false
|
||||
list when is_list(list) -> true
|
||||
|
|
|
|||
|
|
@ -82,8 +82,8 @@ defmodule Pleroma.Web.Push.Subscription do
|
|||
end
|
||||
|
||||
# Some webpush clients (e.g. iOS Toot!) use an non urlsafe base64 as an encoding for the key.
|
||||
# However, the web push rfs specify to use base64 urlsafe, and the `web_push_encryption` library we use
|
||||
# requires the key to be properly encoded. So we just convert base64 to urlsafe base64.
|
||||
# However, the web push rfs specify to use base64 urlsafe, and the `web_push_encryption` library
|
||||
# we use requires the key to be properly encoded. So we just convert base64 to urlsafe base64.
|
||||
defp ensure_base64_urlsafe(string) do
|
||||
string
|
||||
|> String.replace("+", "-")
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
defmodule Pleroma.Web.RichMedia.Helpers do
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.HTML
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.RichMedia.Parser
|
||||
|
||||
defp validate_page_url(page_url) when is_binary(page_url) do
|
||||
|
|
|
|||
|
|
@ -190,6 +190,12 @@ defmodule Pleroma.Web.Router do
|
|||
post("/blocks_import", UtilController, :blocks_import)
|
||||
post("/follow_import", UtilController, :follow_import)
|
||||
end
|
||||
|
||||
scope [] do
|
||||
pipe_through(:oauth_read)
|
||||
|
||||
post("/notifications/read", UtilController, :notifications_read)
|
||||
end
|
||||
end
|
||||
|
||||
scope "/oauth", Pleroma.Web.OAuth do
|
||||
|
|
@ -631,8 +637,8 @@ end
|
|||
|
||||
defmodule Fallback.RedirectController do
|
||||
use Pleroma.Web, :controller
|
||||
alias Pleroma.Web.Metadata
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.Metadata
|
||||
|
||||
def redirector(conn, _params, code \\ 200) do
|
||||
conn
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ defmodule Pleroma.Web.Salmon do
|
|||
|
||||
alias Pleroma.Instances
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.XML
|
||||
alias Pleroma.Web.OStatus.ActivityRepresenter
|
||||
alias Pleroma.Web.XML
|
||||
|
||||
require Logger
|
||||
|
||||
|
|
@ -86,10 +86,10 @@ defmodule Pleroma.Web.Salmon do
|
|||
# Native generation of RSA keys is only available since OTP 20+ and in default build conditions
|
||||
# We try at compile time to generate natively an RSA key otherwise we fallback on the old way.
|
||||
try do
|
||||
_ = :public_key.generate_key({:rsa, 2048, 65537})
|
||||
_ = :public_key.generate_key({:rsa, 2048, 65_537})
|
||||
|
||||
def generate_rsa_pem do
|
||||
key = :public_key.generate_key({:rsa, 2048, 65537})
|
||||
key = :public_key.generate_key({:rsa, 2048, 65_537})
|
||||
entry = :public_key.pem_entry_encode(:RSAPrivateKey, key)
|
||||
pem = :public_key.pem_encode([entry]) |> String.trim_trailing()
|
||||
{:ok, pem}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,14 @@
|
|||
defmodule Pleroma.Web.Streamer do
|
||||
use GenServer
|
||||
require Logger
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.MastodonAPI.NotificationView
|
||||
|
||||
@keepalive_interval :timer.seconds(30)
|
||||
|
||||
|
|
@ -106,10 +108,10 @@ defmodule Pleroma.Web.Streamer do
|
|||
%{
|
||||
event: "notification",
|
||||
payload:
|
||||
Pleroma.Web.MastodonAPI.MastodonAPIController.render_notification(
|
||||
socket.assigns["user"],
|
||||
item
|
||||
)
|
||||
NotificationView.render("show.json", %{
|
||||
notification: item,
|
||||
for: socket.assigns["user"]
|
||||
})
|
||||
|> Jason.encode!()
|
||||
}
|
||||
|> Jason.encode!()
|
||||
|
|
@ -198,10 +200,12 @@ defmodule Pleroma.Web.Streamer do
|
|||
user = User.get_cached_by_ap_id(socket.assigns[:user].ap_id)
|
||||
blocks = user.info.blocks || []
|
||||
mutes = user.info.mutes || []
|
||||
reblog_mutes = user.info.muted_reblogs || []
|
||||
|
||||
parent = Object.normalize(item.data["object"])
|
||||
|
||||
unless is_nil(parent) or item.actor in blocks or item.actor in mutes or
|
||||
item.actor in reblog_mutes or not ActivityPub.contain_activity(item, user) or
|
||||
parent.data["actor"] in blocks or parent.data["actor"] in mutes do
|
||||
send(socket.transport_pid, {:text, represent_update(item, user)})
|
||||
end
|
||||
|
|
@ -232,7 +236,8 @@ defmodule Pleroma.Web.Streamer do
|
|||
blocks = user.info.blocks || []
|
||||
mutes = user.info.mutes || []
|
||||
|
||||
unless item.actor in blocks or item.actor in mutes do
|
||||
unless item.actor in blocks or item.actor in mutes or
|
||||
not ActivityPub.contain_activity(item, user) do
|
||||
send(socket.transport_pid, {:text, represent_update(item, user)})
|
||||
end
|
||||
else
|
||||
|
|
|
|||
|
|
@ -9,14 +9,15 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
|||
|
||||
alias Comeonin.Pbkdf2
|
||||
alias Pleroma.Emoji
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.PasswordResetToken
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.WebFinger
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
|
||||
def show_password_reset(conn, %{"token" => token}) do
|
||||
with %{used: false} = token <- Repo.get_by(PasswordResetToken, %{token: token}),
|
||||
|
|
@ -142,6 +143,17 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
|||
end
|
||||
end
|
||||
|
||||
def notifications_read(%{assigns: %{user: user}} = conn, %{"id" => notification_id}) do
|
||||
with {:ok, _} <- Notification.read_one(user, notification_id) do
|
||||
json(conn, %{status: "success"})
|
||||
else
|
||||
{:error, message} ->
|
||||
conn
|
||||
|> put_resp_content_type("application/json")
|
||||
|> send_resp(403, Jason.encode!(%{"error" => message}))
|
||||
end
|
||||
end
|
||||
|
||||
def config(conn, _params) do
|
||||
instance = Pleroma.Config.get(:instance)
|
||||
instance_fe = Pleroma.Config.get(:fe)
|
||||
|
|
|
|||
|
|
@ -3,16 +3,16 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
||||
alias Pleroma.UserInviteToken
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.UserEmail
|
||||
alias Pleroma.Mailer
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.UserEmail
|
||||
alias Pleroma.UserInviteToken
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.TwitterAPI.UserView
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.TwitterAPI.UserView
|
||||
|
||||
import Ecto.Query
|
||||
|
||||
|
|
@ -35,11 +35,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
|||
|
||||
def unfollow(%User{} = follower, params) do
|
||||
with {:ok, %User{} = unfollowed} <- get_user(params),
|
||||
{:ok, follower, _follow_activity} <- User.unfollow(follower, unfollowed),
|
||||
{:ok, _activity} <- ActivityPub.unfollow(follower, unfollowed) do
|
||||
{:ok, follower} <- CommonAPI.unfollow(follower, unfollowed) do
|
||||
{:ok, follower, unfollowed}
|
||||
else
|
||||
err -> err
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -133,7 +130,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
|||
end
|
||||
|
||||
def register_user(params) do
|
||||
tokenString = params["token"]
|
||||
token_string = params["token"]
|
||||
|
||||
params = %{
|
||||
nickname: params["nickname"],
|
||||
|
|
@ -170,8 +167,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
|||
|
||||
# no need to query DB if registration is open
|
||||
token =
|
||||
unless registrations_open || is_nil(tokenString) do
|
||||
Repo.get_by(UserInviteToken, %{token: tokenString})
|
||||
unless registrations_open || is_nil(token_string) do
|
||||
Repo.get_by(UserInviteToken, %{token: token_string})
|
||||
end
|
||||
|
||||
cond do
|
||||
|
|
|
|||
|
|
@ -8,23 +8,20 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
|
|||
import Pleroma.Web.ControllerHelper, only: [json_response: 3]
|
||||
|
||||
alias Ecto.Changeset
|
||||
alias Pleroma.Web.TwitterAPI.{TwitterAPI, UserView, ActivityView, NotificationView, TokenView}
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.{Repo, Activity, Object, User, Notification}
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.TwitterAPI.ActivityView
|
||||
alias Pleroma.Web.TwitterAPI.NotificationView
|
||||
alias Pleroma.Web.TwitterAPI.TwitterAPI
|
||||
alias Pleroma.Web.TwitterAPI.UserView
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
alias Pleroma.Web.TwitterAPI.ActivityView
|
||||
alias Pleroma.Web.TwitterAPI.NotificationView
|
||||
alias Pleroma.Web.TwitterAPI.TokenView
|
||||
alias Pleroma.Web.TwitterAPI.TwitterAPI
|
||||
alias Pleroma.Web.TwitterAPI.UserView
|
||||
|
||||
require Logger
|
||||
|
||||
|
|
@ -590,16 +587,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
|
|||
def approve_friend_request(conn, %{"user_id" => uid} = _params) do
|
||||
with followed <- conn.assigns[:user],
|
||||
%User{} = follower <- Repo.get(User, uid),
|
||||
{:ok, follower} <- User.maybe_follow(follower, followed),
|
||||
%Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed),
|
||||
{:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "accept"),
|
||||
{:ok, _activity} <-
|
||||
ActivityPub.accept(%{
|
||||
to: [follower.ap_id],
|
||||
actor: followed,
|
||||
object: follow_activity.data["id"],
|
||||
type: "Accept"
|
||||
}) do
|
||||
{:ok, follower} <- CommonAPI.accept_follow_request(follower, followed) do
|
||||
conn
|
||||
|> put_view(UserView)
|
||||
|> render("show.json", %{user: follower, for: followed})
|
||||
|
|
@ -611,15 +599,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
|
|||
def deny_friend_request(conn, %{"user_id" => uid} = _params) do
|
||||
with followed <- conn.assigns[:user],
|
||||
%User{} = follower <- Repo.get(User, uid),
|
||||
%Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed),
|
||||
{:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "reject"),
|
||||
{:ok, _activity} <-
|
||||
ActivityPub.reject(%{
|
||||
to: [follower.ap_id],
|
||||
actor: followed,
|
||||
object: follow_activity.data["id"],
|
||||
type: "Reject"
|
||||
}) do
|
||||
{:ok, follower} <- CommonAPI.reject_follow_request(follower, followed) do
|
||||
conn
|
||||
|> put_view(UserView)
|
||||
|> render("show.json", %{user: follower, for: followed})
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do
|
|||
alias Pleroma.Web.CommonAPI.Utils
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
alias Pleroma.Web.TwitterAPI.ActivityView
|
||||
alias Pleroma.Web.TwitterAPI.Representers.ObjectRepresenter
|
||||
alias Pleroma.Web.TwitterAPI.TwitterAPI
|
||||
alias Pleroma.Web.TwitterAPI.UserView
|
||||
alias Pleroma.Web.TwitterAPI.Representers.ObjectRepresenter
|
||||
|
||||
import Ecto.Query
|
||||
require Logger
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ defmodule Pleroma.Web.WebFinger do
|
|||
@httpoison Application.get_env(:pleroma, :httpoison)
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.XmlBuilder
|
||||
alias Pleroma.Web
|
||||
alias Pleroma.Web.XML
|
||||
alias Pleroma.Web.Salmon
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.Salmon
|
||||
alias Pleroma.Web.XML
|
||||
alias Pleroma.XmlBuilder
|
||||
require Jason
|
||||
require Logger
|
||||
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@ defmodule Pleroma.Web.Websub do
|
|||
alias Ecto.Changeset
|
||||
alias Pleroma.Instances
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Web.Websub.WebsubServerSubscription
|
||||
alias Pleroma.Web.Websub.WebsubClientSubscription
|
||||
alias Pleroma.Web.OStatus.FeedRepresenter
|
||||
alias Pleroma.Web.XML
|
||||
alias Pleroma.Web.Endpoint
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.Router.Helpers
|
||||
alias Pleroma.Web.Federator
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.OStatus.FeedRepresenter
|
||||
alias Pleroma.Web.Router.Helpers
|
||||
alias Pleroma.Web.Websub.WebsubClientSubscription
|
||||
alias Pleroma.Web.Websub.WebsubServerSubscription
|
||||
alias Pleroma.Web.XML
|
||||
require Logger
|
||||
|
||||
import Ecto.Query
|
||||
|
|
@ -200,8 +200,8 @@ defmodule Pleroma.Web.Websub do
|
|||
uri when not is_nil(uri) <- XML.string_from_xpath("/feed/author[1]/uri", doc),
|
||||
hub when not is_nil(hub) <- XML.string_from_xpath(~S{/feed/link[@rel="hub"]/@href}, doc) do
|
||||
name = XML.string_from_xpath("/feed/author[1]/name", doc)
|
||||
preferredUsername = XML.string_from_xpath("/feed/author[1]/poco:preferredUsername", doc)
|
||||
displayName = XML.string_from_xpath("/feed/author[1]/poco:displayName", doc)
|
||||
preferred_username = XML.string_from_xpath("/feed/author[1]/poco:preferredUsername", doc)
|
||||
display_name = XML.string_from_xpath("/feed/author[1]/poco:displayName", doc)
|
||||
avatar = OStatus.make_avatar_object(doc)
|
||||
bio = XML.string_from_xpath("/feed/author[1]/summary", doc)
|
||||
|
||||
|
|
@ -209,8 +209,8 @@ defmodule Pleroma.Web.Websub do
|
|||
%{
|
||||
"uri" => uri,
|
||||
"hub" => hub,
|
||||
"nickname" => preferredUsername || name,
|
||||
"name" => displayName || name,
|
||||
"nickname" => preferred_username || name,
|
||||
"name" => display_name || name,
|
||||
"host" => URI.parse(uri).host,
|
||||
"avatar" => avatar,
|
||||
"bio" => bio
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ defmodule Pleroma.Web.Websub.WebsubClientSubscription do
|
|||
schema "websub_client_subscriptions" do
|
||||
field(:topic, :string)
|
||||
field(:secret, :string)
|
||||
field(:valid_until, :naive_datetime)
|
||||
field(:valid_until, :naive_datetime_usec)
|
||||
field(:state, :string)
|
||||
field(:subscribers, {:array, :string}, default: [])
|
||||
field(:hub, :string)
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ defmodule Pleroma.Web.Websub.WebsubController do
|
|||
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.Websub
|
||||
alias Pleroma.Web.Federator
|
||||
alias Pleroma.Web.Websub
|
||||
alias Pleroma.Web.Websub.WebsubClientSubscription
|
||||
|
||||
require Logger
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue