aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/mix/tasks/pleroma/robotstxt.ex32
-rw-r--r--lib/pleroma/notification.ex14
-rw-r--r--lib/pleroma/plugs/instance_static.ex3
-rw-r--r--lib/pleroma/plugs/uploaded_media.ex12
-rw-r--r--lib/pleroma/reverse_proxy.ex20
-rw-r--r--lib/pleroma/upload.ex14
-rw-r--r--lib/pleroma/user.ex4
-rw-r--r--lib/pleroma/user/info.ex13
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex13
-rw-r--r--lib/pleroma/web/auth/ldap_authenticator.ex143
-rw-r--r--lib/pleroma/web/auth/pleroma_authenticator.ex9
-rw-r--r--lib/pleroma/web/common_api/common_api.ex20
-rw-r--r--lib/pleroma/web/endpoint.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex66
-rw-r--r--lib/pleroma/web/mastodon_api/views/account_view.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/views/notification_view.ex64
-rw-r--r--lib/pleroma/web/mastodon_api/views/status_view.ex3
-rw-r--r--lib/pleroma/web/oauth/oauth_controller.ex8
-rw-r--r--lib/pleroma/web/router.ex6
-rw-r--r--lib/pleroma/web/streamer.ex15
-rw-r--r--lib/pleroma/web/twitter_api/controllers/util_controller.ex12
21 files changed, 408 insertions, 67 deletions
diff --git a/lib/mix/tasks/pleroma/robotstxt.ex b/lib/mix/tasks/pleroma/robotstxt.ex
new file mode 100644
index 000000000..2128e1cd6
--- /dev/null
+++ b/lib/mix/tasks/pleroma/robotstxt.ex
@@ -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
diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex
index fe8181d8b..765191275 100644
--- a/lib/pleroma/notification.ex
+++ b/lib/pleroma/notification.ex
@@ -13,6 +13,7 @@ defmodule Pleroma.Notification do
alias Pleroma.Web.CommonAPI.Utils
import Ecto.Query
+ import Ecto.Changeset
schema "notifications" do
field(:seen, :boolean, default: false)
@@ -22,6 +23,11 @@ defmodule Pleroma.Notification do
timestamps()
end
+ def changeset(%Notification{} = notification, attrs) do
+ notification
+ |> cast(attrs, [:seen])
+ 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)
@@ -68,6 +74,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(
diff --git a/lib/pleroma/plugs/instance_static.ex b/lib/pleroma/plugs/instance_static.ex
index 41125921a..a64f1ea80 100644
--- a/lib/pleroma/plugs/instance_static.ex
+++ b/lib/pleroma/plugs/instance_static.ex
@@ -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
diff --git a/lib/pleroma/plugs/uploaded_media.ex b/lib/pleroma/plugs/uploaded_media.ex
index 13aa8641a..fd77b8d8f 100644
--- a/lib/pleroma/plugs/uploaded_media.ex
+++ b/lib/pleroma/plugs/uploaded_media.ex
@@ -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),
diff --git a/lib/pleroma/reverse_proxy.ex b/lib/pleroma/reverse_proxy.ex
index 6298b92f4..a3f177fec 100644
--- a/lib/pleroma/reverse_proxy.ex
+++ b/lib/pleroma/reverse_proxy.ex
@@ -311,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
diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex
index 1a97e9fde..f72334930 100644
--- a/lib/pleroma/upload.ex
+++ b/lib/pleroma/upload.ex
@@ -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
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 1ce9882f6..692ae836c 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -1385,4 +1385,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
diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex
index e3fd65a6e..740a46727 100644
--- a/lib/pleroma/user/info.ex
+++ b/lib/pleroma/user/info.ex
@@ -21,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)
@@ -259,4 +260,16 @@ defmodule Pleroma.User.Info do
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
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 70db419ca..a65d6e020 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -679,6 +679,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(
@@ -706,6 +718,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
diff --git a/lib/pleroma/web/auth/ldap_authenticator.ex b/lib/pleroma/web/auth/ldap_authenticator.ex
new file mode 100644
index 000000000..88217aab8
--- /dev/null
+++ b/lib/pleroma/web/auth/ldap_authenticator.ex
@@ -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
diff --git a/lib/pleroma/web/auth/pleroma_authenticator.ex b/lib/pleroma/web/auth/pleroma_authenticator.ex
index 333446bef..94a19ad49 100644
--- a/lib/pleroma/web/auth/pleroma_authenticator.ex
+++ b/lib/pleroma/web/auth/pleroma_authenticator.ex
@@ -9,7 +9,14 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do
@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
diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex
index de0759fb0..84d66efc9 100644
--- a/lib/pleroma/web/common_api/common_api.ex
+++ b/lib/pleroma/web/common_api/common_api.ex
@@ -299,4 +299,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
diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex
index 697b1bc3a..fa2d1cbe7 100644
--- a/lib/pleroma/web/endpoint.ex
+++ b/lib/pleroma/web/endpoint.ex
@@ -25,7 +25,7 @@ defmodule Pleroma.Web.Endpoint do
at: "/",
from: :pleroma,
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
)
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index e578f707e..952aa2453 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -22,6 +22,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
alias Pleroma.Web.MastodonAPI.ListView
alias Pleroma.Web.MastodonAPI.MastodonAPI
alias Pleroma.Web.MastodonAPI.MastodonView
+ alias Pleroma.Web.MastodonAPI.NotificationView
alias Pleroma.Web.MastodonAPI.ReportView
alias Pleroma.Web.MastodonAPI.StatusView
alias Pleroma.Web.MediaProxy
@@ -503,19 +504,17 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
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)
-
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
@@ -724,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")
@@ -1309,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)
diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex
index c32f27be2..b5f3bbb9d 100644
--- a/lib/pleroma/web/mastodon_api/views/account_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/account_view.ex
@@ -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
diff --git a/lib/pleroma/web/mastodon_api/views/notification_view.ex b/lib/pleroma/web/mastodon_api/views/notification_view.ex
new file mode 100644
index 000000000..27e9cab06
--- /dev/null
+++ b/lib/pleroma/web/mastodon_api/views/notification_view.ex
@@ -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
diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex
index bf3aaf025..209119dd5 100644
--- a/lib/pleroma/web/mastodon_api/views/status_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -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
diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex
index a2c876627..d151efe9e 100644
--- a/lib/pleroma/web/oauth/oauth_controller.ex
+++ b/lib/pleroma/web/oauth/oauth_controller.ex
@@ -5,7 +5,6 @@
defmodule Pleroma.Web.OAuth.OAuthController do
use Pleroma.Web, :controller
- alias Comeonin.Pbkdf2
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.Auth.Authenticator
@@ -128,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,
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index c56e4a421..befd382ba 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -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
diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex
index aec11a79f..7425bfb54 100644
--- a/lib/pleroma/web/streamer.ex
+++ b/lib/pleroma/web/streamer.ex
@@ -10,7 +10,9 @@ defmodule Pleroma.Web.Streamer do
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
diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
index 8ed02a93f..320ec778c 100644
--- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
@@ -9,6 +9,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
alias Comeonin.Pbkdf2
alias Pleroma.Emoji
+ alias Pleroma.Notification
alias Pleroma.PasswordResetToken
alias Pleroma.Repo
alias Pleroma.User
@@ -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)