summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/mix/tasks/make_moderator.ex15
-rw-r--r--lib/mix/tasks/set_admin.ex18
-rw-r--r--lib/mix/tasks/set_locked.ex17
-rw-r--r--lib/pleroma/formatter.ex10
-rw-r--r--lib/pleroma/html.ex4
-rw-r--r--lib/pleroma/plugs/oauth_plug.ex74
-rw-r--r--lib/pleroma/user.ex1
-rw-r--r--lib/pleroma/user/info.ex2
-rw-r--r--lib/pleroma/web/activity_pub/views/user_view.ex12
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex19
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api_controller.ex22
11 files changed, 135 insertions, 59 deletions
diff --git a/lib/mix/tasks/make_moderator.ex b/lib/mix/tasks/make_moderator.ex
index 15586dc30..8dc0a04dd 100644
--- a/lib/mix/tasks/make_moderator.ex
+++ b/lib/mix/tasks/make_moderator.ex
@@ -8,7 +8,7 @@ defmodule Mix.Tasks.SetModerator do
"""
use Mix.Task
- import Mix.Ecto
+ import Ecto.Changeset
alias Pleroma.{Repo, User}
def run([nickname | rest]) do
@@ -21,14 +21,15 @@ defmodule Mix.Tasks.SetModerator do
end
with %User{local: true} = user <- User.get_by_nickname(nickname) do
- info =
- user.info
- |> Map.put("is_moderator", !!moderator)
+ info_cng = User.Info.admin_api_update(user.info, %{is_moderator: !!moderator})
- cng = User.info_changeset(user, %{info: info})
- {:ok, user} = User.update_and_set_cache(cng)
+ user_cng =
+ Ecto.Changeset.change(user)
+ |> put_embed(:info, info_cng)
- IO.puts("Moderator status of #{nickname}: #{user.info["is_moderator"]}")
+ {:ok, user} = User.update_and_set_cache(user_cng)
+
+ IO.puts("Moderator status of #{nickname}: #{user.info.is_moderator}")
else
_ ->
IO.puts("No local user #{nickname}")
diff --git a/lib/mix/tasks/set_admin.ex b/lib/mix/tasks/set_admin.ex
index d5ccf261b..ac26516f1 100644
--- a/lib/mix/tasks/set_admin.ex
+++ b/lib/mix/tasks/set_admin.ex
@@ -1,5 +1,6 @@
defmodule Mix.Tasks.SetAdmin do
use Mix.Task
+ import Ecto.Changeset
alias Pleroma.User
@doc """
@@ -9,21 +10,22 @@ defmodule Mix.Tasks.SetAdmin do
def run([nickname | rest]) do
Application.ensure_all_started(:pleroma)
- status =
+ admin =
case rest do
- [status] -> status == "true"
+ [admin] -> admin == "true"
_ -> true
end
with %User{local: true} = user <- User.get_by_nickname(nickname) do
- info =
- user.info
- |> Map.put("is_admin", !!status)
+ info_cng = User.Info.admin_api_update(user.info, %{is_admin: !!admin})
- cng = User.info_changeset(user, %{info: info})
- {:ok, user} = User.update_and_set_cache(cng)
+ user_cng =
+ Ecto.Changeset.change(user)
+ |> put_embed(:info, info_cng)
- IO.puts("Admin status of #{nickname}: #{user.info["is_admin"]}")
+ {:ok, user} = User.update_and_set_cache(user_cng)
+
+ IO.puts("Admin status of #{nickname}: #{user.info.is_admin}")
else
_ ->
IO.puts("No local user #{nickname}")
diff --git a/lib/mix/tasks/set_locked.ex b/lib/mix/tasks/set_locked.ex
index a154595ca..e93a63505 100644
--- a/lib/mix/tasks/set_locked.ex
+++ b/lib/mix/tasks/set_locked.ex
@@ -10,11 +10,11 @@ defmodule Mix.Tasks.SetLocked do
"""
use Mix.Task
- import Mix.Ecto
+ import Ecto.Changeset
alias Pleroma.{Repo, User}
def run([nickname | rest]) do
- ensure_started(Repo, [])
+ Application.ensure_all_started(:pleroma)
locked =
case rest do
@@ -23,14 +23,15 @@ defmodule Mix.Tasks.SetLocked do
end
with %User{local: true} = user <- User.get_by_nickname(nickname) do
- info =
- user.info
- |> Map.put("locked", !!locked)
+ info_cng = User.Info.profile_update(user.info, %{locked: !!locked})
- cng = User.info_changeset(user, %{info: info})
- user = Repo.update!(cng)
+ user_cng =
+ Ecto.Changeset.change(user)
+ |> put_embed(:info, info_cng)
- IO.puts("locked status of #{nickname}: #{user.info["locked"]}")
+ {:ok, user} = User.update_and_set_cache(user_cng)
+
+ IO.puts("Locked status of #{nickname}: #{user.info.locked}")
else
_ ->
IO.puts("No local user #{nickname}")
diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex
index 1a5c07c8a..5b03e9aeb 100644
--- a/lib/pleroma/formatter.ex
+++ b/lib/pleroma/formatter.ex
@@ -114,7 +114,7 @@ defmodule Pleroma.Formatter do
subs =
subs ++
- Enum.map(mentions, fn {match, %User{ap_id: ap_id, info: info}, uuid} ->
+ Enum.map(mentions, fn {match, %User{id: id, ap_id: ap_id, info: info}, uuid} ->
ap_id =
if is_binary(info.source_data["url"]) do
info.source_data["url"]
@@ -125,7 +125,7 @@ defmodule Pleroma.Formatter do
short_match = String.split(match, "@") |> tl() |> hd()
{uuid,
- "<span><a class='mention' href='#{ap_id}'>@<span>#{short_match}</span></a></span>"}
+ "<span><a data-user='#{id}' class='mention' href='#{ap_id}'>@<span>#{short_match}</span></a></span>"}
end)
{subs, uuid_text}
@@ -147,7 +147,11 @@ defmodule Pleroma.Formatter do
subs =
subs ++
Enum.map(tags, fn {tag_text, tag, uuid} ->
- url = "<a href='#{Pleroma.Web.base_url()}/tag/#{tag}' rel='tag'>#{tag_text}</a>"
+ url =
+ "<a data-tag='#{tag}' href='#{Pleroma.Web.base_url()}/tag/#{tag}' rel='tag'>#{
+ tag_text
+ }</a>"
+
{uuid, url}
end)
diff --git a/lib/pleroma/html.ex b/lib/pleroma/html.ex
index 1b920d7fd..5daaa5e69 100644
--- a/lib/pleroma/html.ex
+++ b/lib/pleroma/html.ex
@@ -45,7 +45,7 @@ defmodule Pleroma.HTML.Scrubber.TwitterText do
Meta.strip_comments()
# links
- Meta.allow_tag_with_uri_attributes("a", ["href"], @valid_schemes)
+ Meta.allow_tag_with_uri_attributes("a", ["href", "data-user", "data-tag"], @valid_schemes)
Meta.allow_tag_with_these_attributes("a", ["name", "title"])
# paragraphs and linebreaks
@@ -86,7 +86,7 @@ defmodule Pleroma.HTML.Scrubber.Default do
Meta.remove_cdata_sections_before_scrub()
Meta.strip_comments()
- Meta.allow_tag_with_uri_attributes("a", ["href"], @valid_schemes)
+ Meta.allow_tag_with_uri_attributes("a", ["href", "data-user", "data-tag"], @valid_schemes)
Meta.allow_tag_with_these_attributes("a", ["name", "title"])
Meta.allow_tag_with_these_attributes("abbr", ["title"])
diff --git a/lib/pleroma/plugs/oauth_plug.ex b/lib/pleroma/plugs/oauth_plug.ex
index 630f15eec..75f9209c2 100644
--- a/lib/pleroma/plugs/oauth_plug.ex
+++ b/lib/pleroma/plugs/oauth_plug.ex
@@ -1,30 +1,68 @@
defmodule Pleroma.Plugs.OAuthPlug do
import Plug.Conn
- alias Pleroma.User
- alias Pleroma.Repo
- alias Pleroma.Web.OAuth.Token
+ import Ecto.Query
- def init(options) do
- options
- end
+ alias Pleroma.{
+ User,
+ Repo,
+ Web.OAuth.Token
+ }
+
+ @realm_reg Regex.compile!("Bearer\:?\s+(.*)$", "i")
+
+ def init(options), do: options
def call(%{assigns: %{user: %User{}}} = conn, _), do: conn
def call(conn, _) do
- token =
- case get_req_header(conn, "authorization") do
- ["Bearer " <> header] -> header
- _ -> get_session(conn, :oauth_token)
- end
-
- with token when not is_nil(token) <- token,
- %Token{user_id: user_id} <- Repo.get_by(Token, token: token),
- %User{} = user <- Repo.get(User, user_id),
- false <- !!user.info.deactivated do
- conn
- |> assign(:user, user)
+ with {:ok, token} <- fetch_token(conn),
+ {:ok, user} <- fetch_user(token) do
+ assign(conn, :user, user)
else
_ -> conn
end
end
+
+ # Gets user by token
+ #
+ @spec fetch_user(String.t()) :: {:ok, User.t()} | nil
+ defp fetch_user(token) do
+ query = from(q in Token, where: q.token == ^token, preload: [:user])
+
+ with %Token{user: %{info: %{deactivated: false} = _} = user} <- Repo.one(query) do
+ {:ok, user}
+ end
+ end
+
+ # Gets token from session by :oauth_token key
+ #
+ @spec fetch_token_from_session(Plug.Conn.t()) :: :no_token_found | {:ok, String.t()}
+ defp fetch_token_from_session(conn) do
+ case get_session(conn, :oauth_token) do
+ nil -> :no_token_found
+ token -> {:ok, token}
+ end
+ end
+
+ # Gets token from headers
+ #
+ @spec fetch_token(Plug.Conn.t()) :: :no_token_found | {:ok, String.t()}
+ defp fetch_token(%Plug.Conn{} = conn) do
+ headers = get_req_header(conn, "authorization")
+
+ with :no_token_found <- fetch_token(headers),
+ do: fetch_token_from_session(conn)
+ end
+
+ @spec fetch_token(Keyword.t()) :: :no_token_found | {:ok, String.t()}
+ defp fetch_token([]), do: :no_token_found
+
+ defp fetch_token([token | tail]) do
+ trimmed_token = String.trim(token)
+
+ case Regex.run(@realm_reg, trimmed_token) do
+ [_, match] -> {:ok, String.trim(match)}
+ _ -> fetch_token(tail)
+ end
+ end
end
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 3bd92c157..74ae5ef0d 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -177,6 +177,7 @@ defmodule Pleroma.User do
|> validate_format(:email, @email_regex)
|> validate_length(:bio, max: 1000)
|> validate_length(:name, min: 1, max: 100)
+ |> put_change(:info, %Pleroma.User.Info{})
if changeset.valid? do
hashed = Pbkdf2.hashpwsalt(changeset.changes[:password])
diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex
index 49b2f0eda..7a99787f8 100644
--- a/lib/pleroma/user/info.ex
+++ b/lib/pleroma/user/info.ex
@@ -24,6 +24,7 @@ defmodule Pleroma.User.Info do
field(:topic, :string, default: nil)
field(:hub, :string, default: nil)
field(:salmon, :string, default: nil)
+ field(:hide_network, :boolean, default: false)
# Found in the wild
# ap_id -> Where is this used?
@@ -135,6 +136,7 @@ defmodule Pleroma.User.Info do
:no_rich_text,
:default_scope,
:banner,
+ :hide_network,
:background
])
end
diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex
index aaa777602..869934172 100644
--- a/lib/pleroma/web/activity_pub/views/user_view.ex
+++ b/lib/pleroma/web/activity_pub/views/user_view.ex
@@ -82,7 +82,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
query = from(user in query, select: [:ap_id])
following = Repo.all(query)
- collection(following, "#{user.ap_id}/following", page)
+ collection(following, "#{user.ap_id}/following", page, !user.info.hide_network)
|> Map.merge(Utils.make_json_ld_header())
end
@@ -95,7 +95,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"id" => "#{user.ap_id}/following",
"type" => "OrderedCollection",
"totalItems" => length(following),
- "first" => collection(following, "#{user.ap_id}/following", 1)
+ "first" => collection(following, "#{user.ap_id}/following", 1, !user.info.hide_network)
}
|> Map.merge(Utils.make_json_ld_header())
end
@@ -105,7 +105,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
query = from(user in query, select: [:ap_id])
followers = Repo.all(query)
- collection(followers, "#{user.ap_id}/followers", page)
+ collection(followers, "#{user.ap_id}/followers", page, !user.info.hide_network)
|> Map.merge(Utils.make_json_ld_header())
end
@@ -118,7 +118,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"id" => "#{user.ap_id}/followers",
"type" => "OrderedCollection",
"totalItems" => length(followers),
- "first" => collection(followers, "#{user.ap_id}/followers", 1)
+ "first" => collection(followers, "#{user.ap_id}/followers", 1, !user.info.hide_network)
}
|> Map.merge(Utils.make_json_ld_header())
end
@@ -172,7 +172,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
end
end
- def collection(collection, iri, page, total \\ nil) do
+ def collection(collection, iri, page, show_items \\ true, total \\ nil) do
offset = (page - 1) * 10
items = Enum.slice(collection, offset, 10)
items = Enum.map(items, fn user -> user.ap_id end)
@@ -183,7 +183,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"type" => "OrderedCollectionPage",
"partOf" => iri,
"totalItems" => total,
- "orderedItems" => items
+ "orderedItems" => if(show_items, do: items, else: [])
}
if offset < total do
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index f9007a808..300bdc04a 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -502,17 +502,30 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity})
end
- # TODO: Pagination
- def followers(conn, %{"id" => id}) do
+ def followers(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do
with %User{} = user <- Repo.get(User, id),
{:ok, followers} <- User.get_followers(user) do
+ followers =
+ cond do
+ for_user && user.id == for_user.id -> followers
+ user.info.hide_network -> []
+ true -> followers
+ end
+
render(conn, AccountView, "accounts.json", %{users: followers, as: :user})
end
end
- def following(conn, %{"id" => id}) do
+ def following(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do
with %User{} = user <- Repo.get(User, id),
{:ok, followers} <- User.get_friends(user) do
+ followers =
+ cond do
+ for_user && user.id == for_user.id -> followers
+ user.info.hide_network -> []
+ true -> followers
+ end
+
render(conn, AccountView, "accounts.json", %{users: followers, as: :user})
end
end
diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
index 961250d92..8fd6ea078 100644
--- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
@@ -340,18 +340,32 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
end
end
- def followers(conn, params) do
- with {:ok, user} <- TwitterAPI.get_user(conn.assigns[:user], params),
+ def followers(%{assigns: %{user: for_user}} = conn, params) do
+ with {:ok, user} <- TwitterAPI.get_user(for_user, params),
{:ok, followers} <- User.get_followers(user) do
+ followers =
+ cond do
+ for_user && user.id == for_user.id -> followers
+ user.info.hide_network -> []
+ true -> followers
+ end
+
render(conn, UserView, "index.json", %{users: followers, for: conn.assigns[:user]})
else
_e -> bad_request_reply(conn, "Can't get followers")
end
end
- def friends(conn, params) do
+ def friends(%{assigns: %{user: for_user}} = conn, params) do
with {:ok, user} <- TwitterAPI.get_user(conn.assigns[:user], params),
{:ok, friends} <- User.get_friends(user) do
+ friends =
+ cond do
+ for_user && user.id == for_user.id -> friends
+ user.info.hide_network -> []
+ true -> friends
+ end
+
render(conn, UserView, "index.json", %{users: friends, for: conn.assigns[:user]})
else
_e -> bad_request_reply(conn, "Can't get friends")
@@ -429,7 +443,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
defp build_info_cng(user, params) do
info_params =
- ["no_rich_text", "locked"]
+ ["no_rich_text", "locked", "hide_network"]
|> Enum.reduce(%{}, fn key, res ->
if value = params[key] do
Map.put(res, key, value == "true")