forked from AkkomaGang/akkoma
Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma into develop
This commit is contained in:
commit
58f9ce0deb
209 changed files with 2743 additions and 1052 deletions
|
@ -1,3 +1,3 @@
|
||||||
[
|
[
|
||||||
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}", "priv/repo/migrations/*.exs"]
|
||||||
]
|
]
|
||||||
|
|
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -12,6 +12,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Pleroma API: `GET /api/v1/pleroma/accounts/:id/scrobbles` to get a list of recently scrobbled items
|
- Pleroma API: `GET /api/v1/pleroma/accounts/:id/scrobbles` to get a list of recently scrobbled items
|
||||||
- Pleroma API: `POST /api/v1/pleroma/scrobble` to scrobble a media item
|
- Pleroma API: `POST /api/v1/pleroma/scrobble` to scrobble a media item
|
||||||
- Mastodon API: Add `upload_limit`, `avatar_upload_limit`, `background_upload_limit`, and `banner_upload_limit` to `/api/v1/instance`
|
- Mastodon API: Add `upload_limit`, `avatar_upload_limit`, `background_upload_limit`, and `banner_upload_limit` to `/api/v1/instance`
|
||||||
|
- Mastodon API: Add `pleroma.unread_conversation_count` to the Account entity
|
||||||
|
- OAuth: support for hierarchical permissions / [Mastodon 2.4.3 OAuth permissions](https://docs.joinmastodon.org/api/permissions/)
|
||||||
|
- Authentication: Added rate limit for password-authorized actions / login existence checks
|
||||||
|
- Metadata Link: Atom syndication Feed
|
||||||
|
- Mix task to re-count statuses for all users (`mix pleroma.count_statuses`)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- **Breaking:** Elixir >=1.8 is now required (was >= 1.7)
|
- **Breaking:** Elixir >=1.8 is now required (was >= 1.7)
|
||||||
|
@ -21,11 +26,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Admin API: Return `total` when querying for reports
|
- Admin API: Return `total` when querying for reports
|
||||||
- Mastodon API: Return `pleroma.direct_conversation_id` when creating a direct message (`POST /api/v1/statuses`)
|
- Mastodon API: Return `pleroma.direct_conversation_id` when creating a direct message (`POST /api/v1/statuses`)
|
||||||
- Admin API: Return link alongside with token on password reset
|
- Admin API: Return link alongside with token on password reset
|
||||||
|
- MRF (Simple Policy): Also use `:accept`/`:reject` on the actors rather than only their activities
|
||||||
|
- OStatus: Extract RSS functionality
|
||||||
|
- Mastodon API: Add `pleroma.direct_conversation_id` to the status endpoint (`GET /api/v1/statuses/:id`)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Mastodon API: Fix private and direct statuses not being filtered out from the public timeline for an authenticated user (`GET /api/v1/timelines/public`)
|
- Mastodon API: Fix private and direct statuses not being filtered out from the public timeline for an authenticated user (`GET /api/v1/timelines/public`)
|
||||||
- Mastodon API: Inability to get some local users by nickname in `/api/v1/accounts/:id_or_nickname`
|
- Mastodon API: Inability to get some local users by nickname in `/api/v1/accounts/:id_or_nickname`
|
||||||
- Added `:instance, extended_nickname_format` setting to the default config
|
- Added `:instance, extended_nickname_format` setting to the default config
|
||||||
|
- Report emails now include functional links to profiles of remote user accounts
|
||||||
|
|
||||||
## [1.1.0] - 2019-??-??
|
## [1.1.0] - 2019-??-??
|
||||||
### Security
|
### Security
|
||||||
|
@ -78,6 +87,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- ActivityPub: Fix `/users/:nickname/inbox` crashing without an authenticated user
|
- ActivityPub: Fix `/users/:nickname/inbox` crashing without an authenticated user
|
||||||
- MRF: fix ability to follow a relay when AntiFollowbotPolicy was enabled
|
- MRF: fix ability to follow a relay when AntiFollowbotPolicy was enabled
|
||||||
- Mastodon API: Blocks are now treated consistently between the Streaming API and the Timeline APIs
|
- Mastodon API: Blocks are now treated consistently between the Streaming API and the Timeline APIs
|
||||||
|
- Mastodon API: `exclude_replies` is correctly handled again.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Expiring/ephemeral activites. All activities can have expires_at value set, which controls when they should be deleted automatically.
|
- Expiring/ephemeral activites. All activities can have expires_at value set, which controls when they should be deleted automatically.
|
||||||
|
|
|
@ -409,7 +409,8 @@
|
||||||
providers: [
|
providers: [
|
||||||
Pleroma.Web.Metadata.Providers.OpenGraph,
|
Pleroma.Web.Metadata.Providers.OpenGraph,
|
||||||
Pleroma.Web.Metadata.Providers.TwitterCard,
|
Pleroma.Web.Metadata.Providers.TwitterCard,
|
||||||
Pleroma.Web.Metadata.Providers.RelMe
|
Pleroma.Web.Metadata.Providers.RelMe,
|
||||||
|
Pleroma.Web.Metadata.Providers.Feed
|
||||||
],
|
],
|
||||||
unfurl_nsfw: false
|
unfurl_nsfw: false
|
||||||
|
|
||||||
|
@ -588,7 +589,7 @@
|
||||||
config :http_signatures,
|
config :http_signatures,
|
||||||
adapter: Pleroma.Signature
|
adapter: Pleroma.Signature
|
||||||
|
|
||||||
config :pleroma, :rate_limit, nil
|
config :pleroma, :rate_limit, authentication: {60_000, 15}
|
||||||
|
|
||||||
config :pleroma, Pleroma.ActivityExpiration, enabled: true
|
config :pleroma, Pleroma.ActivityExpiration, enabled: true
|
||||||
|
|
||||||
|
|
|
@ -2290,7 +2290,8 @@
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :rate_limit,
|
key: :rate_limit,
|
||||||
type: :group,
|
type: :group,
|
||||||
description: "Rate limit settings. This is an advanced feature and disabled by default.",
|
description:
|
||||||
|
"Rate limit settings. This is an advanced feature enabled only for :authentication by default.",
|
||||||
children: [
|
children: [
|
||||||
%{
|
%{
|
||||||
key: :search,
|
key: :search,
|
||||||
|
@ -2329,6 +2330,12 @@
|
||||||
description:
|
description:
|
||||||
"for fav / unfav or reblog / unreblog actions on the same status by the same user",
|
"for fav / unfav or reblog / unreblog actions on the same status by the same user",
|
||||||
suggestions: [{1000, 10}, [{10_000, 10}, {10_000, 50}]]
|
suggestions: [{1000, 10}, [{10_000, 10}, {10_000, 50}]]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :authentication,
|
||||||
|
type: [:tuple, {:list, :tuple}],
|
||||||
|
description: "for authentication create / password check / user existence check requests",
|
||||||
|
suggestions: [{60_000, 15}]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -56,6 +56,7 @@ Has these additional fields under the `pleroma` object:
|
||||||
- `settings_store`: A generic map of settings for frontends. Opaque to the backend. Only returned in `verify_credentials` and `update_credentials`
|
- `settings_store`: A generic map of settings for frontends. Opaque to the backend. Only returned in `verify_credentials` and `update_credentials`
|
||||||
- `chat_token`: The token needed for Pleroma chat. Only returned in `verify_credentials`
|
- `chat_token`: The token needed for Pleroma chat. Only returned in `verify_credentials`
|
||||||
- `deactivated`: boolean, true when the user is deactivated
|
- `deactivated`: boolean, true when the user is deactivated
|
||||||
|
- `unread_conversation_count`: The count of unread conversations. Only returned to the account owner.
|
||||||
|
|
||||||
### Source
|
### Source
|
||||||
|
|
||||||
|
|
|
@ -475,6 +475,7 @@ config :pleroma, :workers,
|
||||||
* Pleroma.Web.Metadata.Providers.OpenGraph
|
* Pleroma.Web.Metadata.Providers.OpenGraph
|
||||||
* Pleroma.Web.Metadata.Providers.TwitterCard
|
* Pleroma.Web.Metadata.Providers.TwitterCard
|
||||||
* Pleroma.Web.Metadata.Providers.RelMe - add links from user bio with rel=me into the `<header>` as `<link rel=me>`
|
* Pleroma.Web.Metadata.Providers.RelMe - add links from user bio with rel=me into the `<header>` as `<link rel=me>`
|
||||||
|
* Pleroma.Web.Metadata.Providers.Feed - add a link to a user's Atom feed into the `<header>` as `<link rel=alternate>`
|
||||||
* `unfurl_nsfw`: If set to `true` nsfw attachments will be shown in previews
|
* `unfurl_nsfw`: If set to `true` nsfw attachments will be shown in previews
|
||||||
|
|
||||||
## :rich_media
|
## :rich_media
|
||||||
|
|
22
lib/mix/tasks/pleroma/count_statuses.ex
Normal file
22
lib/mix/tasks/pleroma/count_statuses.ex
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
defmodule Mix.Tasks.Pleroma.CountStatuses do
|
||||||
|
@shortdoc "Re-counts statuses for all users"
|
||||||
|
|
||||||
|
use Mix.Task
|
||||||
|
alias Pleroma.User
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
def run([]) do
|
||||||
|
Mix.Pleroma.start_pleroma()
|
||||||
|
|
||||||
|
stream =
|
||||||
|
User
|
||||||
|
|> where(local: true)
|
||||||
|
|> Pleroma.Repo.stream()
|
||||||
|
|
||||||
|
Pleroma.Repo.transaction(fn ->
|
||||||
|
Enum.each(stream, &User.update_note_count/1)
|
||||||
|
end)
|
||||||
|
|
||||||
|
Mix.Pleroma.shell_info("Done")
|
||||||
|
end
|
||||||
|
end
|
|
@ -67,6 +67,8 @@ def create_or_bump_for(activity, opts \\ []) do
|
||||||
|
|
||||||
participations =
|
participations =
|
||||||
Enum.map(users, fn user ->
|
Enum.map(users, fn user ->
|
||||||
|
User.increment_unread_conversation_count(conversation, user)
|
||||||
|
|
||||||
{:ok, participation} =
|
{:ok, participation} =
|
||||||
Participation.create_for_user_and_conversation(user, conversation, opts)
|
Participation.create_for_user_and_conversation(user, conversation, opts)
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,15 @@ def mark_as_read(participation) do
|
||||||
participation
|
participation
|
||||||
|> read_cng(%{read: true})
|
|> read_cng(%{read: true})
|
||||||
|> Repo.update()
|
|> Repo.update()
|
||||||
|
|> case do
|
||||||
|
{:ok, participation} ->
|
||||||
|
participation = Repo.preload(participation, :user)
|
||||||
|
User.set_unread_conversation_count(participation.user)
|
||||||
|
{:ok, participation}
|
||||||
|
|
||||||
|
error ->
|
||||||
|
error
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def mark_as_unread(participation) do
|
def mark_as_unread(participation) do
|
||||||
|
@ -135,4 +144,12 @@ def set_recipients(participation, user_ids) do
|
||||||
|
|
||||||
{:ok, Repo.preload(participation, :recipients, force: true)}
|
{:ok, Repo.preload(participation, :recipients, force: true)}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def unread_conversation_count_for_user(user) do
|
||||||
|
from(p in __MODULE__,
|
||||||
|
where: p.user_id == ^user.id,
|
||||||
|
where: not p.read,
|
||||||
|
select: %{count: count(p.id)}
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,7 +17,7 @@ defp instance_notify_email do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp user_url(user) do
|
defp user_url(user) do
|
||||||
Helpers.o_status_url(Pleroma.Web.Endpoint, :feed_redirect, user.nickname)
|
Helpers.feed_url(Pleroma.Web.Endpoint, :feed_redirect, user.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def report(to, reporter, account, statuses, comment) do
|
def report(to, reporter, account, statuses, comment) do
|
||||||
|
|
|
@ -6,6 +6,8 @@ defmodule Pleroma.Plugs.OAuthScopesPlug do
|
||||||
import Plug.Conn
|
import Plug.Conn
|
||||||
import Pleroma.Web.Gettext
|
import Pleroma.Web.Gettext
|
||||||
|
|
||||||
|
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
|
||||||
|
|
||||||
@behaviour Plug
|
@behaviour Plug
|
||||||
|
|
||||||
def init(%{scopes: _} = options), do: options
|
def init(%{scopes: _} = options), do: options
|
||||||
|
@ -13,24 +15,26 @@ def init(%{scopes: _} = options), do: options
|
||||||
def call(%Plug.Conn{assigns: assigns} = conn, %{scopes: scopes} = options) do
|
def call(%Plug.Conn{assigns: assigns} = conn, %{scopes: scopes} = options) do
|
||||||
op = options[:op] || :|
|
op = options[:op] || :|
|
||||||
token = assigns[:token]
|
token = assigns[:token]
|
||||||
|
matched_scopes = token && filter_descendants(scopes, token.scopes)
|
||||||
|
|
||||||
cond do
|
cond do
|
||||||
is_nil(token) ->
|
is_nil(token) ->
|
||||||
|
maybe_perform_instance_privacy_check(conn, options)
|
||||||
|
|
||||||
|
op == :| && Enum.any?(matched_scopes) ->
|
||||||
conn
|
conn
|
||||||
|
|
||||||
op == :| && scopes -- token.scopes != scopes ->
|
op == :& && matched_scopes == scopes ->
|
||||||
conn
|
|
||||||
|
|
||||||
op == :& && scopes -- token.scopes == [] ->
|
|
||||||
conn
|
conn
|
||||||
|
|
||||||
options[:fallback] == :proceed_unauthenticated ->
|
options[:fallback] == :proceed_unauthenticated ->
|
||||||
conn
|
conn
|
||||||
|> assign(:user, nil)
|
|> assign(:user, nil)
|
||||||
|> assign(:token, nil)
|
|> assign(:token, nil)
|
||||||
|
|> maybe_perform_instance_privacy_check(options)
|
||||||
|
|
||||||
true ->
|
true ->
|
||||||
missing_scopes = scopes -- token.scopes
|
missing_scopes = scopes -- matched_scopes
|
||||||
permissions = Enum.join(missing_scopes, " #{op} ")
|
permissions = Enum.join(missing_scopes, " #{op} ")
|
||||||
|
|
||||||
error_message =
|
error_message =
|
||||||
|
@ -42,4 +46,25 @@ def call(%Plug.Conn{assigns: assigns} = conn, %{scopes: scopes} = options) do
|
||||||
|> halt()
|
|> halt()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc "Filters descendants of supported scopes"
|
||||||
|
def filter_descendants(scopes, supported_scopes) do
|
||||||
|
Enum.filter(
|
||||||
|
scopes,
|
||||||
|
fn scope ->
|
||||||
|
Enum.find(
|
||||||
|
supported_scopes,
|
||||||
|
&(scope == &1 || String.starts_with?(scope, &1 <> ":"))
|
||||||
|
)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_perform_instance_privacy_check(%Plug.Conn{} = conn, options) do
|
||||||
|
if options[:skip_instance_privacy_check] do
|
||||||
|
conn
|
||||||
|
else
|
||||||
|
EnsurePublicOrAuthenticatedPlug.call(conn, [])
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -48,7 +48,7 @@ def refetch_public_key(conn) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def sign(%User{} = user, headers) do
|
def sign(%User{} = user, headers) do
|
||||||
with {:ok, %{info: %{keys: keys}}} <- User.ensure_keys_present(user),
|
with {:ok, %{keys: keys}} <- User.ensure_keys_present(user),
|
||||||
{:ok, private_key, _} <- Keys.keys_from_pem(keys) do
|
{:ok, private_key, _} <- Keys.keys_from_pem(keys) do
|
||||||
HTTPSignatures.sign(private_key, user.ap_id <> "#main-key", headers)
|
HTTPSignatures.sign(private_key, user.ap_id <> "#main-key", headers)
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,6 +11,7 @@ defmodule Pleroma.User do
|
||||||
alias Comeonin.Pbkdf2
|
alias Comeonin.Pbkdf2
|
||||||
alias Ecto.Multi
|
alias Ecto.Multi
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
|
alias Pleroma.Conversation.Participation
|
||||||
alias Pleroma.Delivery
|
alias Pleroma.Delivery
|
||||||
alias Pleroma.Keys
|
alias Pleroma.Keys
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
|
@ -50,6 +51,7 @@ defmodule Pleroma.User do
|
||||||
field(:password_hash, :string)
|
field(:password_hash, :string)
|
||||||
field(:password, :string, virtual: true)
|
field(:password, :string, virtual: true)
|
||||||
field(:password_confirmation, :string, virtual: true)
|
field(:password_confirmation, :string, virtual: true)
|
||||||
|
field(:keys, :string)
|
||||||
field(:following, {:array, :string}, default: [])
|
field(:following, {:array, :string}, default: [])
|
||||||
field(:ap_id, :string)
|
field(:ap_id, :string)
|
||||||
field(:avatar, :map)
|
field(:avatar, :map)
|
||||||
|
@ -842,6 +844,61 @@ def maybe_update_following_count(%User{local: false} = user) do
|
||||||
|
|
||||||
def maybe_update_following_count(user), do: user
|
def maybe_update_following_count(user), do: user
|
||||||
|
|
||||||
|
def set_unread_conversation_count(%User{local: true} = user) do
|
||||||
|
unread_query = Participation.unread_conversation_count_for_user(user)
|
||||||
|
|
||||||
|
User
|
||||||
|
|> join(:inner, [u], p in subquery(unread_query))
|
||||||
|
|> update([u, p],
|
||||||
|
set: [
|
||||||
|
info:
|
||||||
|
fragment(
|
||||||
|
"jsonb_set(?, '{unread_conversation_count}', ?::varchar::jsonb, true)",
|
||||||
|
u.info,
|
||||||
|
p.count
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|> where([u], u.id == ^user.id)
|
||||||
|
|> select([u], u)
|
||||||
|
|> Repo.update_all([])
|
||||||
|
|> case do
|
||||||
|
{1, [user]} -> set_cache(user)
|
||||||
|
_ -> {:error, user}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_unread_conversation_count(_), do: :noop
|
||||||
|
|
||||||
|
def increment_unread_conversation_count(conversation, %User{local: true} = user) do
|
||||||
|
unread_query =
|
||||||
|
Participation.unread_conversation_count_for_user(user)
|
||||||
|
|> where([p], p.conversation_id == ^conversation.id)
|
||||||
|
|
||||||
|
User
|
||||||
|
|> join(:inner, [u], p in subquery(unread_query))
|
||||||
|
|> update([u, p],
|
||||||
|
set: [
|
||||||
|
info:
|
||||||
|
fragment(
|
||||||
|
"jsonb_set(?, '{unread_conversation_count}', (coalesce((?->>'unread_conversation_count')::int, 0) + 1)::varchar::jsonb, true)",
|
||||||
|
u.info,
|
||||||
|
u.info
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|> where([u], u.id == ^user.id)
|
||||||
|
|> where([u, p], p.count == 0)
|
||||||
|
|> select([u], u)
|
||||||
|
|> Repo.update_all([])
|
||||||
|
|> case do
|
||||||
|
{1, [user]} -> set_cache(user)
|
||||||
|
_ -> {:error, user}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def increment_unread_conversation_count(_, _), do: :noop
|
||||||
|
|
||||||
def remove_duplicated_following(%User{following: following} = user) do
|
def remove_duplicated_following(%User{following: following} = user) do
|
||||||
uniq_following = Enum.uniq(following)
|
uniq_following = Enum.uniq(following)
|
||||||
|
|
||||||
|
@ -1498,11 +1555,14 @@ def get_mascot(%{info: %{mascot: mascot}}) when is_nil(mascot) do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def ensure_keys_present(%{info: %{keys: keys}} = user) when not is_nil(keys), do: {:ok, user}
|
def ensure_keys_present(%{keys: keys} = user) when not is_nil(keys), do: {:ok, user}
|
||||||
|
|
||||||
def ensure_keys_present(%User{} = user) do
|
def ensure_keys_present(%User{} = user) do
|
||||||
with {:ok, pem} <- Keys.generate_rsa_pem() do
|
with {:ok, pem} <- Keys.generate_rsa_pem() do
|
||||||
update_info(user, &User.Info.set_keys(&1, pem))
|
user
|
||||||
|
|> cast(%{keys: pem}, [:keys])
|
||||||
|
|> validate_required([:keys])
|
||||||
|
|> update_and_set_cache()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ defmodule Pleroma.User.Info do
|
||||||
field(:hide_followers, :boolean, default: false)
|
field(:hide_followers, :boolean, default: false)
|
||||||
field(:hide_follows, :boolean, default: false)
|
field(:hide_follows, :boolean, default: false)
|
||||||
field(:hide_favorites, :boolean, default: true)
|
field(:hide_favorites, :boolean, default: true)
|
||||||
|
field(:unread_conversation_count, :integer, default: 0)
|
||||||
field(:pinned_activities, {:array, :string}, default: [])
|
field(:pinned_activities, {:array, :string}, default: [])
|
||||||
field(:email_notifications, :map, default: %{"digest" => false})
|
field(:email_notifications, :map, default: %{"digest" => false})
|
||||||
field(:mascot, :map, default: nil)
|
field(:mascot, :map, default: nil)
|
||||||
|
|
|
@ -780,8 +780,8 @@ defp restrict_media(query, _), do: query
|
||||||
|
|
||||||
defp restrict_replies(query, %{"exclude_replies" => val}) when val == "true" or val == "1" do
|
defp restrict_replies(query, %{"exclude_replies" => val}) when val == "true" or val == "1" do
|
||||||
from(
|
from(
|
||||||
activity in query,
|
[_activity, object] in query,
|
||||||
where: fragment("?->'object'->>'inReplyTo' is null", activity.data)
|
where: fragment("?->>'inReplyTo' is null", object.data)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -168,7 +168,9 @@ def filter(%{"id" => actor, "type" => obj_type} = object)
|
||||||
when obj_type in ["Application", "Group", "Organization", "Person", "Service"] do
|
when obj_type in ["Application", "Group", "Organization", "Person", "Service"] do
|
||||||
actor_info = URI.parse(actor)
|
actor_info = URI.parse(actor)
|
||||||
|
|
||||||
with {:ok, object} <- check_avatar_removal(actor_info, object),
|
with {:ok, object} <- check_accept(actor_info, object),
|
||||||
|
{:ok, object} <- check_reject(actor_info, object),
|
||||||
|
{:ok, object} <- check_avatar_removal(actor_info, object),
|
||||||
{:ok, object} <- check_banner_removal(actor_info, object) do
|
{:ok, object} <- check_banner_removal(actor_info, object) do
|
||||||
{:ok, object}
|
{:ok, object}
|
||||||
else
|
else
|
||||||
|
|
|
@ -580,7 +580,7 @@ def handle_incoming(
|
||||||
) do
|
) do
|
||||||
with actor <- Containment.get_actor(data),
|
with actor <- Containment.get_actor(data),
|
||||||
{:ok, %User{} = actor} <- User.get_or_fetch_by_ap_id(actor),
|
{:ok, %User{} = actor} <- User.get_or_fetch_by_ap_id(actor),
|
||||||
{:ok, object} <- get_obj_helper(object_id),
|
{:ok, object} <- get_embedded_obj_helper(object_id, actor),
|
||||||
public <- Visibility.is_public?(data),
|
public <- Visibility.is_public?(data),
|
||||||
{:ok, activity, _object} <- ActivityPub.announce(actor, object, id, false, public) do
|
{:ok, activity, _object} <- ActivityPub.announce(actor, object, id, false, public) do
|
||||||
{:ok, activity}
|
{:ok, activity}
|
||||||
|
@ -782,6 +782,29 @@ def get_obj_helper(id, options \\ []) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec get_embedded_obj_helper(String.t() | Object.t(), User.t()) :: {:ok, Object.t()} | nil
|
||||||
|
def get_embedded_obj_helper(%{"attributedTo" => attributed_to, "id" => object_id} = data, %User{
|
||||||
|
ap_id: ap_id
|
||||||
|
})
|
||||||
|
when attributed_to == ap_id do
|
||||||
|
with {:ok, activity} <-
|
||||||
|
handle_incoming(%{
|
||||||
|
"type" => "Create",
|
||||||
|
"to" => data["to"],
|
||||||
|
"cc" => data["cc"],
|
||||||
|
"actor" => attributed_to,
|
||||||
|
"object" => data
|
||||||
|
}) do
|
||||||
|
{:ok, Object.normalize(activity)}
|
||||||
|
else
|
||||||
|
_ -> get_obj_helper(object_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_embedded_obj_helper(object_id, _) do
|
||||||
|
get_obj_helper(object_id)
|
||||||
|
end
|
||||||
|
|
||||||
def set_reply_to_uri(%{"inReplyTo" => in_reply_to} = object) when is_binary(in_reply_to) do
|
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"),
|
with false <- String.starts_with?(in_reply_to, "http"),
|
||||||
{:ok, %{data: replied_to_object}} <- get_obj_helper(in_reply_to) do
|
{:ok, %{data: replied_to_object}} <- get_obj_helper(in_reply_to) do
|
||||||
|
|
|
@ -33,7 +33,7 @@ def render("endpoints.json", _), do: %{}
|
||||||
|
|
||||||
def render("service.json", %{user: user}) do
|
def render("service.json", %{user: user}) do
|
||||||
{:ok, user} = User.ensure_keys_present(user)
|
{:ok, user} = User.ensure_keys_present(user)
|
||||||
{:ok, _, public_key} = Keys.keys_from_pem(user.info.keys)
|
{:ok, _, public_key} = Keys.keys_from_pem(user.keys)
|
||||||
public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key)
|
public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key)
|
||||||
public_key = :public_key.pem_encode([public_key])
|
public_key = :public_key.pem_encode([public_key])
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ def render("user.json", %{user: %User{nickname: "internal." <> _} = user}),
|
||||||
|
|
||||||
def render("user.json", %{user: user}) do
|
def render("user.json", %{user: user}) do
|
||||||
{:ok, user} = User.ensure_keys_present(user)
|
{:ok, user} = User.ensure_keys_present(user)
|
||||||
{:ok, _, public_key} = Keys.keys_from_pem(user.info.keys)
|
{:ok, _, public_key} = Keys.keys_from_pem(user.keys)
|
||||||
public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key)
|
public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key)
|
||||||
public_key = :public_key.pem_encode([public_key])
|
public_key = :public_key.pem_encode([public_key])
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.ModerationLog
|
alias Pleroma.ModerationLog
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.UserInviteToken
|
alias Pleroma.UserInviteToken
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
@ -26,6 +27,67 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["read:accounts"]}
|
||||||
|
when action in [:list_users, :user_show, :right_get, :invites]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["write:accounts"]}
|
||||||
|
when action in [
|
||||||
|
:get_invite_token,
|
||||||
|
:revoke_invite,
|
||||||
|
:email_invite,
|
||||||
|
:get_password_reset,
|
||||||
|
:user_follow,
|
||||||
|
:user_unfollow,
|
||||||
|
:user_delete,
|
||||||
|
:users_create,
|
||||||
|
:user_toggle_activation,
|
||||||
|
:tag_users,
|
||||||
|
:untag_users,
|
||||||
|
:right_add,
|
||||||
|
:right_delete,
|
||||||
|
:set_activation_status
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["read:reports"]} when action in [:list_reports, :report_show]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["write:reports"]}
|
||||||
|
when action in [:report_update_state, :report_respond]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["read:statuses"]} when action == :list_user_statuses
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["write:statuses"]}
|
||||||
|
when action in [:status_update, :status_delete]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["read"]}
|
||||||
|
when action in [:config_show, :migrate_to_db, :migrate_from_db, :list_log]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["write"]}
|
||||||
|
when action in [:relay_follow, :relay_unfollow, :config_update]
|
||||||
|
)
|
||||||
|
|
||||||
@users_page_size 50
|
@users_page_size 50
|
||||||
|
|
||||||
action_fallback(:errors)
|
action_fallback(:errors)
|
||||||
|
|
63
lib/pleroma/web/feed/feed_controller.ex
Normal file
63
lib/pleroma/web/feed/feed_controller.ex
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.Feed.FeedController do
|
||||||
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
alias Fallback.RedirectController
|
||||||
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
alias Pleroma.Web.ActivityPub.ActivityPubController
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.SetFormatPlug when action in [:feed_redirect])
|
||||||
|
|
||||||
|
action_fallback(:errors)
|
||||||
|
|
||||||
|
def feed_redirect(%{assigns: %{format: "html"}} = conn, %{"nickname" => nickname}) do
|
||||||
|
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname_or_id(nickname)} do
|
||||||
|
RedirectController.redirector_with_meta(conn, %{user: user})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def feed_redirect(%{assigns: %{format: format}} = conn, _params)
|
||||||
|
when format in ["json", "activity+json"] do
|
||||||
|
ActivityPubController.call(conn, :user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def feed_redirect(conn, %{"nickname" => nickname}) do
|
||||||
|
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do
|
||||||
|
redirect(conn, external: "#{feed_url(conn, :feed, user.nickname)}.atom")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def feed(conn, %{"nickname" => nickname} = params) do
|
||||||
|
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do
|
||||||
|
query_params =
|
||||||
|
params
|
||||||
|
|> Map.take(["max_id"])
|
||||||
|
|> Map.put("type", ["Create"])
|
||||||
|
|> Map.put("whole_db", true)
|
||||||
|
|> Map.put("actor_id", user.ap_id)
|
||||||
|
|
||||||
|
activities =
|
||||||
|
query_params
|
||||||
|
|> ActivityPub.fetch_public_activities()
|
||||||
|
|> Enum.reverse()
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_resp_content_type("application/atom+xml")
|
||||||
|
|> render("feed.xml", user: user, activities: activities)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def errors(conn, {:error, :not_found}) do
|
||||||
|
render_error(conn, :not_found, "Not found")
|
||||||
|
end
|
||||||
|
|
||||||
|
def errors(conn, {:fetch_user, nil}), do: errors(conn, {:error, :not_found})
|
||||||
|
|
||||||
|
def errors(conn, _) do
|
||||||
|
render_error(conn, :internal_server_error, "Something went wrong")
|
||||||
|
end
|
||||||
|
end
|
77
lib/pleroma/web/feed/feed_view.ex
Normal file
77
lib/pleroma/web/feed/feed_view.ex
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.Feed.FeedView do
|
||||||
|
use Phoenix.HTML
|
||||||
|
use Pleroma.Web, :view
|
||||||
|
|
||||||
|
alias Pleroma.Object
|
||||||
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Web.MediaProxy
|
||||||
|
|
||||||
|
require Pleroma.Constants
|
||||||
|
|
||||||
|
def most_recent_update(activities, user) do
|
||||||
|
(List.first(activities) || user).updated_at
|
||||||
|
|> NaiveDateTime.to_iso8601()
|
||||||
|
end
|
||||||
|
|
||||||
|
def logo(user) do
|
||||||
|
user
|
||||||
|
|> User.avatar_url()
|
||||||
|
|> MediaProxy.url()
|
||||||
|
end
|
||||||
|
|
||||||
|
def last_activity(activities) do
|
||||||
|
List.last(activities)
|
||||||
|
end
|
||||||
|
|
||||||
|
def activity_object(activity) do
|
||||||
|
Object.normalize(activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
def activity_object_data(activity) do
|
||||||
|
activity
|
||||||
|
|> activity_object()
|
||||||
|
|> Map.get(:data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def activity_content(activity) do
|
||||||
|
content = activity_object_data(activity)["content"]
|
||||||
|
|
||||||
|
content
|
||||||
|
|> String.replace(~r/[\n\r]/, "")
|
||||||
|
|> escape()
|
||||||
|
end
|
||||||
|
|
||||||
|
def activity_context(activity) do
|
||||||
|
activity.data["context"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def attachment_href(attachment) do
|
||||||
|
attachment["url"]
|
||||||
|
|> hd()
|
||||||
|
|> Map.get("href")
|
||||||
|
end
|
||||||
|
|
||||||
|
def attachment_type(attachment) do
|
||||||
|
attachment["url"]
|
||||||
|
|> hd()
|
||||||
|
|> Map.get("mediaType")
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_href(id) do
|
||||||
|
with %Object{data: %{"external_url" => external_url}} <- Object.get_cached_by_ap_id(id) do
|
||||||
|
external_url
|
||||||
|
else
|
||||||
|
_e -> id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def escape(html) do
|
||||||
|
html
|
||||||
|
|> html_escape()
|
||||||
|
|> safe_to_string()
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,8 +5,20 @@
|
||||||
defmodule Pleroma.Web.MastoFEController do
|
defmodule Pleroma.Web.MastoFEController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action == :put_settings)
|
||||||
|
|
||||||
|
# Note: :index action handles attempt of unauthenticated access to private instance with redirect
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["read"], fallback: :proceed_unauthenticated, skip_instance_privacy_check: true}
|
||||||
|
when action == :index
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug when action != :index)
|
||||||
|
|
||||||
@doc "GET /web/*path"
|
@doc "GET /web/*path"
|
||||||
def index(%{assigns: %{user: user}} = conn, _params) do
|
def index(%{assigns: %{user: user}} = conn, _params) do
|
||||||
token = get_session(conn, :oauth_token)
|
token = get_session(conn, :oauth_token)
|
||||||
|
|
|
@ -9,6 +9,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
||||||
only: [add_link_headers: 2, truthy_param?: 1, assign_account_by_id: 2, json_response: 3]
|
only: [add_link_headers: 2, truthy_param?: 1, assign_account_by_id: 2, json_response: 3]
|
||||||
|
|
||||||
alias Pleroma.Emoji
|
alias Pleroma.Emoji
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.Plugs.RateLimiter
|
alias Pleroma.Plugs.RateLimiter
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
@ -19,6 +20,49 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
||||||
alias Pleroma.Web.OAuth.Token
|
alias Pleroma.Web.OAuth.Token
|
||||||
alias Pleroma.Web.TwitterAPI.TwitterAPI
|
alias Pleroma.Web.TwitterAPI.TwitterAPI
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{fallback: :proceed_unauthenticated, scopes: ["read:accounts"]}
|
||||||
|
when action == :show
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["read:accounts"]}
|
||||||
|
when action in [:endorsements, :verify_credentials, :followers, :following]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action == :update_credentials)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read:lists"]} when action == :lists)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["follow", "read:blocks"]} when action == :blocks
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["follow", "write:blocks"]} when action in [:block, :unblock]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read:follows"]} when action == :relationships)
|
||||||
|
|
||||||
|
# Note: :follows (POST /api/v1/follows) is the same as :follow, consider removing :follows
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["follow", "write:follows"]} when action in [:follows, :follow, :unfollow]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["follow", "read:mutes"]} when action == :mutes)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["follow", "write:mutes"]} when action in [:mute, :unmute])
|
||||||
|
|
||||||
|
plug(
|
||||||
|
Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
|
||||||
|
when action != :create
|
||||||
|
)
|
||||||
|
|
||||||
@relations [:follow, :unfollow]
|
@relations [:follow, :unfollow]
|
||||||
@needs_account ~W(followers following lists follow unfollow mute unmute block unblock)a
|
@needs_account ~W(followers following lists follow unfollow mute unmute block unblock)a
|
||||||
|
|
||||||
|
@ -105,6 +149,17 @@ def update_credentials(%{assigns: %{user: original_user}} = conn, params) do
|
||||||
|> Enum.concat(Emoji.Formatter.get_emoji_map(emojis_text))
|
|> Enum.concat(Emoji.Formatter.get_emoji_map(emojis_text))
|
||||||
|> Enum.dedup()
|
|> Enum.dedup()
|
||||||
|
|
||||||
|
params =
|
||||||
|
if Map.has_key?(params, "fields_attributes") do
|
||||||
|
Map.update!(params, "fields_attributes", fn fields ->
|
||||||
|
fields
|
||||||
|
|> normalize_fields_attributes()
|
||||||
|
|> Enum.filter(fn %{"name" => n} -> n != "" end)
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
params
|
||||||
|
end
|
||||||
|
|
||||||
info_params =
|
info_params =
|
||||||
[
|
[
|
||||||
:no_rich_text,
|
:no_rich_text,
|
||||||
|
@ -122,12 +177,12 @@ def update_credentials(%{assigns: %{user: original_user}} = conn, params) do
|
||||||
add_if_present(acc, params, to_string(key), key, &{:ok, truthy_param?(&1)})
|
add_if_present(acc, params, to_string(key), key, &{:ok, truthy_param?(&1)})
|
||||||
end)
|
end)
|
||||||
|> add_if_present(params, "default_scope", :default_scope)
|
|> add_if_present(params, "default_scope", :default_scope)
|
||||||
|> add_if_present(params, "fields", :fields, fn fields ->
|
|> add_if_present(params, "fields_attributes", :fields, fn fields ->
|
||||||
fields = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end)
|
fields = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end)
|
||||||
|
|
||||||
{:ok, fields}
|
{:ok, fields}
|
||||||
end)
|
end)
|
||||||
|> add_if_present(params, "fields", :raw_fields)
|
|> add_if_present(params, "fields_attributes", :raw_fields)
|
||||||
|> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value ->
|
|> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value ->
|
||||||
{:ok, Map.merge(user.info.pleroma_settings_store, value)}
|
{:ok, Map.merge(user.info.pleroma_settings_store, value)}
|
||||||
end)
|
end)
|
||||||
|
@ -168,6 +223,14 @@ defp add_if_present(map, params, params_field, map_field, value_function \\ &{:o
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp normalize_fields_attributes(fields) do
|
||||||
|
if Enum.all?(fields, &is_tuple/1) do
|
||||||
|
Enum.map(fields, fn {_, v} -> v end)
|
||||||
|
else
|
||||||
|
fields
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@doc "GET /api/v1/accounts/relationships"
|
@doc "GET /api/v1/accounts/relationships"
|
||||||
def relationships(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
def relationships(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
targets = User.get_all_by_ids(List.wrap(id))
|
targets = User.get_all_by_ids(List.wrap(id))
|
||||||
|
@ -301,4 +364,30 @@ def unblock(%{assigns: %{user: blocker, account: blocked}} = conn, _params) do
|
||||||
{:error, message} -> json_response(conn, :forbidden, %{error: message})
|
{:error, message} -> json_response(conn, :forbidden, %{error: message})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc "POST /api/v1/follows"
|
||||||
|
def follows(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
|
||||||
|
with {_, %User{} = followed} <- {:followed, User.get_cached_by_nickname(uri)},
|
||||||
|
{_, true} <- {:followed, follower.id != followed.id},
|
||||||
|
{:ok, follower, followed, _} <- CommonAPI.follow(follower, followed) do
|
||||||
|
render(conn, "show.json", user: followed, for: follower)
|
||||||
|
else
|
||||||
|
{:followed, _} -> {:error, :not_found}
|
||||||
|
{:error, message} -> json_response(conn, :forbidden, %{error: message})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "GET /api/v1/mutes"
|
||||||
|
def mutes(%{assigns: %{user: user}} = conn, _) do
|
||||||
|
render(conn, "index.json", users: User.muted_users(user), for: user, as: :user)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "GET /api/v1/blocks"
|
||||||
|
def blocks(%{assigns: %{user: user}} = conn, _) do
|
||||||
|
render(conn, "index.json", users: User.blocked_users(user), for: user, as: :user)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "GET /api/v1/endorsements"
|
||||||
|
def endorsements(conn, params),
|
||||||
|
do: Pleroma.Web.MastodonAPI.MastodonAPIController.empty_array(conn, params)
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
defmodule Pleroma.Web.MastodonAPI.AppController do
|
defmodule Pleroma.Web.MastodonAPI.AppController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.Web.OAuth.App
|
alias Pleroma.Web.OAuth.App
|
||||||
alias Pleroma.Web.OAuth.Scopes
|
alias Pleroma.Web.OAuth.Scopes
|
||||||
|
@ -12,6 +13,8 @@ defmodule Pleroma.Web.MastodonAPI.AppController do
|
||||||
|
|
||||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read"]} when action == :verify_credentials)
|
||||||
|
|
||||||
@local_mastodon_name "Mastodon-Local"
|
@local_mastodon_name "Mastodon-Local"
|
||||||
|
|
||||||
@doc "POST /api/v1/apps"
|
@doc "POST /api/v1/apps"
|
||||||
|
|
|
@ -8,10 +8,16 @@ defmodule Pleroma.Web.MastodonAPI.ConversationController do
|
||||||
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
|
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
|
||||||
|
|
||||||
alias Pleroma.Conversation.Participation
|
alias Pleroma.Conversation.Participation
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
|
|
||||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action == :index)
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["write:conversations"]} when action == :read)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
@doc "GET /api/v1/conversations"
|
@doc "GET /api/v1/conversations"
|
||||||
def index(%{assigns: %{user: user}} = conn, params) do
|
def index(%{assigns: %{user: user}} = conn, params) do
|
||||||
participations = Participation.for_user_with_last_activity_id(user, params)
|
participations = Participation.for_user_with_last_activity_id(user, params)
|
||||||
|
|
|
@ -5,8 +5,21 @@
|
||||||
defmodule Pleroma.Web.MastodonAPI.DomainBlockController do
|
defmodule Pleroma.Web.MastodonAPI.DomainBlockController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["follow", "read:blocks"]} when action == :index
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["follow", "write:blocks"]} when action != :index
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
@doc "GET /api/v1/domain_blocks"
|
@doc "GET /api/v1/domain_blocks"
|
||||||
def index(%{assigns: %{user: %{info: info}}} = conn, _) do
|
def index(%{assigns: %{user: %{info: info}}} = conn, _) do
|
||||||
json(conn, Map.get(info, :domain_blocks, []))
|
json(conn, Map.get(info, :domain_blocks, []))
|
||||||
|
|
|
@ -6,6 +6,18 @@ defmodule Pleroma.Web.MastodonAPI.FilterController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
alias Pleroma.Filter
|
alias Pleroma.Filter
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
|
|
||||||
|
@oauth_read_actions [:show, :index]
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read:filters"]} when action in @oauth_read_actions)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["write:filters"]} when action not in @oauth_read_actions
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
@doc "GET /api/v1/filters"
|
@doc "GET /api/v1/filters"
|
||||||
def index(%{assigns: %{user: user}} = conn, _) do
|
def index(%{assigns: %{user: user}} = conn, _) do
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
defmodule Pleroma.Web.MastodonAPI.FollowRequestController do
|
defmodule Pleroma.Web.MastodonAPI.FollowRequestController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
|
@ -13,6 +14,15 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestController do
|
||||||
|
|
||||||
action_fallback(:errors)
|
action_fallback(:errors)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["follow", "read:follows"]} when action == :index)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["follow", "write:follows"]} when action != :index
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
@doc "GET /api/v1/follow_requests"
|
@doc "GET /api/v1/follow_requests"
|
||||||
def index(%{assigns: %{user: followed}} = conn, _params) do
|
def index(%{assigns: %{user: followed}} = conn, _params) do
|
||||||
follow_requests = User.get_follow_requests(followed)
|
follow_requests = User.get_follow_requests(followed)
|
||||||
|
|
|
@ -5,11 +5,22 @@
|
||||||
defmodule Pleroma.Web.MastodonAPI.ListController do
|
defmodule Pleroma.Web.MastodonAPI.ListController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.MastodonAPI.AccountView
|
alias Pleroma.Web.MastodonAPI.AccountView
|
||||||
|
|
||||||
plug(:list_by_id_and_user when action not in [:index, :create])
|
plug(:list_by_id_and_user when action not in [:index, :create])
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read:lists"]} when action in [:index, :show, :list_accounts])
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["write:lists"]}
|
||||||
|
when action in [:create, :update, :delete, :add_to_list, :remove_from_list]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
|
|
||||||
# GET /api/v1/lists
|
# GET /api/v1/lists
|
||||||
|
|
|
@ -5,86 +5,10 @@
|
||||||
defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
|
|
||||||
|
|
||||||
alias Pleroma.Bookmark
|
|
||||||
alias Pleroma.Pagination
|
|
||||||
alias Pleroma.User
|
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
|
||||||
alias Pleroma.Web.CommonAPI
|
|
||||||
alias Pleroma.Web.MastodonAPI.AccountView
|
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
|
|
||||||
def follows(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
|
|
||||||
with {_, %User{} = followed} <- {:followed, User.get_cached_by_nickname(uri)},
|
|
||||||
{_, true} <- {:followed, follower.id != followed.id},
|
|
||||||
{:ok, follower, followed, _} <- CommonAPI.follow(follower, followed) do
|
|
||||||
conn
|
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("show.json", %{user: followed, for: follower})
|
|
||||||
else
|
|
||||||
{:followed, _} ->
|
|
||||||
{:error, :not_found}
|
|
||||||
|
|
||||||
{:error, message} ->
|
|
||||||
conn
|
|
||||||
|> put_status(:forbidden)
|
|
||||||
|> json(%{error: message})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def mutes(%{assigns: %{user: user}} = conn, _) do
|
|
||||||
with muted_accounts <- User.muted_users(user) do
|
|
||||||
res = AccountView.render("index.json", users: muted_accounts, for: user, as: :user)
|
|
||||||
json(conn, res)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def blocks(%{assigns: %{user: user}} = conn, _) do
|
|
||||||
with blocked_accounts <- User.blocked_users(user) do
|
|
||||||
res = AccountView.render("index.json", users: blocked_accounts, for: user, as: :user)
|
|
||||||
json(conn, res)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def favourites(%{assigns: %{user: user}} = conn, params) do
|
|
||||||
params =
|
|
||||||
params
|
|
||||||
|> Map.put("type", "Create")
|
|
||||||
|> Map.put("favorited_by", user.ap_id)
|
|
||||||
|> Map.put("blocking_user", user)
|
|
||||||
|
|
||||||
activities =
|
|
||||||
ActivityPub.fetch_activities([], params)
|
|
||||||
|> Enum.reverse()
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> add_link_headers(activities)
|
|
||||||
|> put_view(StatusView)
|
|
||||||
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
|
||||||
end
|
|
||||||
|
|
||||||
def bookmarks(%{assigns: %{user: user}} = conn, params) do
|
|
||||||
user = User.get_cached_by_id(user.id)
|
|
||||||
|
|
||||||
bookmarks =
|
|
||||||
Bookmark.for_user_query(user.id)
|
|
||||||
|> Pagination.fetch_paginated(params)
|
|
||||||
|
|
||||||
activities =
|
|
||||||
bookmarks
|
|
||||||
|> Enum.map(fn b -> Map.put(b.activity, :bookmark, Map.delete(b, :activity)) end)
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> add_link_headers(bookmarks)
|
|
||||||
|> put_view(StatusView)
|
|
||||||
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
|
||||||
end
|
|
||||||
|
|
||||||
# Stubs for unimplemented mastodon api
|
# Stubs for unimplemented mastodon api
|
||||||
#
|
#
|
||||||
def empty_array(conn, _) do
|
def empty_array(conn, _) do
|
||||||
|
|
|
@ -6,12 +6,17 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
|
||||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
plug(:put_view, Pleroma.Web.MastodonAPI.StatusView)
|
plug(:put_view, Pleroma.Web.MastodonAPI.StatusView)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["write:media"]})
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
@doc "POST /api/v1/media"
|
@doc "POST /api/v1/media"
|
||||||
def create(%{assigns: %{user: user}} = conn, %{"file" => file} = data) do
|
def create(%{assigns: %{user: user}} = conn, %{"file" => file} = data) do
|
||||||
with {:ok, object} <-
|
with {:ok, object} <-
|
||||||
|
|
|
@ -8,8 +8,20 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
|
||||||
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
|
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
|
||||||
|
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.Web.MastodonAPI.MastodonAPI
|
alias Pleroma.Web.MastodonAPI.MastodonAPI
|
||||||
|
|
||||||
|
@oauth_read_actions [:show, :index]
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["read:notifications"]} when action in @oauth_read_actions
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action not in @oauth_read_actions)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
# GET /api/v1/notifications
|
# GET /api/v1/notifications
|
||||||
def index(%{assigns: %{user: user}} = conn, params) do
|
def index(%{assigns: %{user: user}} = conn, params) do
|
||||||
notifications = MastodonAPI.get_notifications(user, params)
|
notifications = MastodonAPI.get_notifications(user, params)
|
||||||
|
|
|
@ -9,11 +9,21 @@ defmodule Pleroma.Web.MastodonAPI.PollController do
|
||||||
|
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.Web.ActivityPub.Visibility
|
alias Pleroma.Web.ActivityPub.Visibility
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["read:statuses"], fallback: :proceed_unauthenticated} when action == :show
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["write:statuses"]} when action == :vote)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
@doc "GET /api/v1/polls/:id"
|
@doc "GET /api/v1/polls/:id"
|
||||||
def show(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
def show(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60),
|
with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60),
|
||||||
|
|
|
@ -3,10 +3,16 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Web.MastodonAPI.ReportController do
|
defmodule Pleroma.Web.MastodonAPI.ReportController do
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
|
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["write:reports"]} when action == :create)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
@doc "POST /api/v1/reports"
|
@doc "POST /api/v1/reports"
|
||||||
def create(%{assigns: %{user: user}} = conn, params) do
|
def create(%{assigns: %{user: user}} = conn, params) do
|
||||||
with {:ok, activity} <- Pleroma.Web.CommonAPI.report(user, params) do
|
with {:ok, activity} <- Pleroma.Web.CommonAPI.report(user, params) do
|
||||||
|
|
|
@ -7,11 +7,19 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityController do
|
||||||
|
|
||||||
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
|
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
|
||||||
|
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.ScheduledActivity
|
alias Pleroma.ScheduledActivity
|
||||||
alias Pleroma.Web.MastodonAPI.MastodonAPI
|
alias Pleroma.Web.MastodonAPI.MastodonAPI
|
||||||
|
|
||||||
plug(:assign_scheduled_activity when action != :index)
|
plug(:assign_scheduled_activity when action != :index)
|
||||||
|
|
||||||
|
@oauth_read_actions [:show, :index]
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action in @oauth_read_actions)
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["write:statuses"]} when action not in @oauth_read_actions)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
|
|
||||||
@doc "GET /api/v1/scheduled_statuses"
|
@doc "GET /api/v1/scheduled_statuses"
|
||||||
|
|
|
@ -6,6 +6,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.Plugs.RateLimiter
|
alias Pleroma.Plugs.RateLimiter
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
@ -15,6 +16,12 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
|
# Note: Mastodon doesn't allow unauthenticated access (requires read:accounts / read:search)
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read:search"], fallback: :proceed_unauthenticated})
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
plug(RateLimiter, :search when action in [:search, :search2, :account_search])
|
plug(RateLimiter, :search when action in [:search, :search2, :account_search])
|
||||||
|
|
||||||
def account_search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
|
def account_search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
|
||||||
|
|
|
@ -5,13 +5,14 @@
|
||||||
defmodule Pleroma.Web.MastodonAPI.StatusController do
|
defmodule Pleroma.Web.MastodonAPI.StatusController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
import Pleroma.Web.ControllerHelper, only: [try_render: 3]
|
import Pleroma.Web.ControllerHelper, only: [try_render: 3, add_link_headers: 2]
|
||||||
|
|
||||||
require Ecto.Query
|
require Ecto.Query
|
||||||
|
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Bookmark
|
alias Pleroma.Bookmark
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.Plugs.RateLimiter
|
alias Pleroma.Plugs.RateLimiter
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.ScheduledActivity
|
alias Pleroma.ScheduledActivity
|
||||||
|
@ -22,6 +23,61 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
|
||||||
alias Pleroma.Web.MastodonAPI.AccountView
|
alias Pleroma.Web.MastodonAPI.AccountView
|
||||||
alias Pleroma.Web.MastodonAPI.ScheduledActivityView
|
alias Pleroma.Web.MastodonAPI.ScheduledActivityView
|
||||||
|
|
||||||
|
@unauthenticated_access %{fallback: :proceed_unauthenticated, scopes: []}
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{@unauthenticated_access | scopes: ["read:statuses"]}
|
||||||
|
when action in [
|
||||||
|
:index,
|
||||||
|
:show,
|
||||||
|
:card,
|
||||||
|
:context
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["write:statuses"]}
|
||||||
|
when action in [
|
||||||
|
:create,
|
||||||
|
:delete,
|
||||||
|
:reblog,
|
||||||
|
:unreblog
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read:favourites"]} when action == :favourites)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["write:favourites"]} when action in [:favourite, :unfavourite]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["write:mutes"]} when action in [:mute_conversation, :unmute_conversation]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{@unauthenticated_access | scopes: ["read:accounts"]}
|
||||||
|
when action in [:favourited_by, :reblogged_by]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action in [:pin, :unpin])
|
||||||
|
|
||||||
|
# Note: scope not present in Mastodon: read:bookmarks
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read:bookmarks"]} when action == :bookmarks)
|
||||||
|
|
||||||
|
# Note: scope not present in Mastodon: write:bookmarks
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["write:bookmarks"]} when action in [:bookmark, :unbookmark]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
@rate_limited_status_actions ~w(reblog unreblog favourite unfavourite create delete)a
|
@rate_limited_status_actions ~w(reblog unreblog favourite unfavourite create delete)a
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
|
@ -111,7 +167,11 @@ def create(%{assigns: %{user: _user}} = conn, %{"media_ids" => _} = params) do
|
||||||
def show(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
def show(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
||||||
true <- Visibility.visible_for_user?(activity, user) do
|
true <- Visibility.visible_for_user?(activity, user) do
|
||||||
try_render(conn, "show.json", activity: activity, for: user)
|
try_render(conn, "show.json",
|
||||||
|
activity: activity,
|
||||||
|
for: user,
|
||||||
|
with_direct_conversation_id: true
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -283,4 +343,39 @@ def context(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
render(conn, "context.json", activity: activity, activities: activities, user: user)
|
render(conn, "context.json", activity: activity, activities: activities, user: user)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc "GET /api/v1/favourites"
|
||||||
|
def favourites(%{assigns: %{user: user}} = conn, params) do
|
||||||
|
params =
|
||||||
|
params
|
||||||
|
|> Map.put("type", "Create")
|
||||||
|
|> Map.put("favorited_by", user.ap_id)
|
||||||
|
|> Map.put("blocking_user", user)
|
||||||
|
|
||||||
|
activities =
|
||||||
|
ActivityPub.fetch_activities([], params)
|
||||||
|
|> Enum.reverse()
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> add_link_headers(activities)
|
||||||
|
|> render("index.json", activities: activities, for: user, as: :activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "GET /api/v1/bookmarks"
|
||||||
|
def bookmarks(%{assigns: %{user: user}} = conn, params) do
|
||||||
|
user = User.get_cached_by_id(user.id)
|
||||||
|
|
||||||
|
bookmarks =
|
||||||
|
user.id
|
||||||
|
|> Bookmark.for_user_query()
|
||||||
|
|> Pleroma.Pagination.fetch_paginated(params)
|
||||||
|
|
||||||
|
activities =
|
||||||
|
bookmarks
|
||||||
|
|> Enum.map(fn b -> Map.put(b.activity, :bookmark, Map.delete(b, :activity)) end)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> add_link_headers(bookmarks)
|
||||||
|
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,6 +12,10 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionController do
|
||||||
|
|
||||||
action_fallback(:errors)
|
action_fallback(:errors)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["push"]})
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
# Creates PushSubscription
|
# Creates PushSubscription
|
||||||
# POST /api/v1/push/subscription
|
# POST /api/v1/push/subscription
|
||||||
#
|
#
|
||||||
|
|
|
@ -8,11 +8,16 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionController do
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
alias Pleroma.Config
|
alias Pleroma.Config
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.MediaProxy
|
alias Pleroma.Web.MediaProxy
|
||||||
|
|
||||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read"]} when action == :index)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
@doc "GET /api/v1/suggestions"
|
@doc "GET /api/v1/suggestions"
|
||||||
def index(%{assigns: %{user: user}} = conn, _) do
|
def index(%{assigns: %{user: user}} = conn, _) do
|
||||||
if Config.get([:suggestions, :enabled], false) do
|
if Config.get([:suggestions, :enabled], false) do
|
||||||
|
|
|
@ -9,8 +9,14 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
|
||||||
only: [add_link_headers: 2, add_link_headers: 3, truthy_param?: 1]
|
only: [add_link_headers: 2, add_link_headers: 3, truthy_param?: 1]
|
||||||
|
|
||||||
alias Pleroma.Pagination
|
alias Pleroma.Pagination
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action in [:home, :direct])
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read:lists"]} when action == :list)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
plug(:put_view, Pleroma.Web.MastodonAPI.StatusView)
|
plug(:put_view, Pleroma.Web.MastodonAPI.StatusView)
|
||||||
|
|
||||||
# GET /api/v1/timelines/home
|
# GET /api/v1/timelines/home
|
||||||
|
|
|
@ -167,6 +167,7 @@ defp do_render("show.json", %{user: user} = opts) do
|
||||||
|> maybe_put_chat_token(user, opts[:for], opts)
|
|> maybe_put_chat_token(user, opts[:for], opts)
|
||||||
|> maybe_put_activation_status(user, opts[:for])
|
|> maybe_put_activation_status(user, opts[:for])
|
||||||
|> maybe_put_follow_requests_count(user, opts[:for])
|
|> maybe_put_follow_requests_count(user, opts[:for])
|
||||||
|
|> maybe_put_unread_conversation_count(user, opts[:for])
|
||||||
end
|
end
|
||||||
|
|
||||||
defp username_from_nickname(string) when is_binary(string) do
|
defp username_from_nickname(string) when is_binary(string) do
|
||||||
|
@ -248,6 +249,16 @@ defp maybe_put_activation_status(data, user, %User{info: %{is_admin: true}}) do
|
||||||
|
|
||||||
defp maybe_put_activation_status(data, _, _), do: data
|
defp maybe_put_activation_status(data, _, _), do: data
|
||||||
|
|
||||||
|
defp maybe_put_unread_conversation_count(data, %User{id: user_id} = user, %User{id: user_id}) do
|
||||||
|
data
|
||||||
|
|> Kernel.put_in(
|
||||||
|
[:pleroma, :unread_conversation_count],
|
||||||
|
user.info.unread_conversation_count
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_put_unread_conversation_count(data, _, _), do: data
|
||||||
|
|
||||||
defp image_url(%{"url" => [%{"href" => href} | _]}), do: href
|
defp image_url(%{"url" => [%{"href" => href} | _]}), do: href
|
||||||
defp image_url(_), do: nil
|
defp image_url(_), do: nil
|
||||||
end
|
end
|
||||||
|
|
23
lib/pleroma/web/metadata/feed.ex
Normal file
23
lib/pleroma/web/metadata/feed.ex
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.Metadata.Providers.Feed do
|
||||||
|
alias Pleroma.Web.Endpoint
|
||||||
|
alias Pleroma.Web.Metadata.Providers.Provider
|
||||||
|
alias Pleroma.Web.Router.Helpers
|
||||||
|
|
||||||
|
@behaviour Provider
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def build_tags(%{user: user}) do
|
||||||
|
[
|
||||||
|
{:link,
|
||||||
|
[
|
||||||
|
rel: "alternate",
|
||||||
|
type: "application/atom+xml",
|
||||||
|
href: Helpers.feed_path(Endpoint, :feed, user.nickname) <> ".atom"
|
||||||
|
], []}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
|
@ -4,10 +4,15 @@
|
||||||
|
|
||||||
defmodule Pleroma.Web.MongooseIM.MongooseIMController do
|
defmodule Pleroma.Web.MongooseIM.MongooseIMController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
alias Comeonin.Pbkdf2
|
alias Comeonin.Pbkdf2
|
||||||
|
alias Pleroma.Plugs.RateLimiter
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
|
||||||
|
plug(RateLimiter, :authentication when action in [:user_exists, :check_password])
|
||||||
|
plug(RateLimiter, {:authentication, params: ["user"]} when action == :check_password)
|
||||||
|
|
||||||
def user_exists(conn, %{"user" => username}) do
|
def user_exists(conn, %{"user" => username}) do
|
||||||
with %User{} <- Repo.get_by(User, nickname: username, local: true) do
|
with %User{} <- Repo.get_by(User, nickname: username, local: true) do
|
||||||
conn
|
conn
|
||||||
|
|
|
@ -24,6 +24,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
|
||||||
|
|
||||||
plug(:fetch_session)
|
plug(:fetch_session)
|
||||||
plug(:fetch_flash)
|
plug(:fetch_flash)
|
||||||
|
plug(Pleroma.Plugs.RateLimiter, :authentication when action == :create_authorization)
|
||||||
|
|
||||||
action_fallback(Pleroma.Web.OAuth.FallbackController)
|
action_fallback(Pleroma.Web.OAuth.FallbackController)
|
||||||
|
|
||||||
|
@ -474,7 +475,7 @@ defp put_session_registration_id(%Plug.Conn{} = conn, registration_id),
|
||||||
defp validate_scopes(app, params) do
|
defp validate_scopes(app, params) do
|
||||||
params
|
params
|
||||||
|> Scopes.fetch_scopes(app.scopes)
|
|> Scopes.fetch_scopes(app.scopes)
|
||||||
|> Scopes.validates(app.scopes)
|
|> Scopes.validate(app.scopes)
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_redirect_uri(%App{} = app) do
|
def default_redirect_uri(%App{} = app) do
|
||||||
|
|
|
@ -8,7 +8,7 @@ defmodule Pleroma.Web.OAuth.Scopes do
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Fetch scopes from requiest params.
|
Fetch scopes from request params.
|
||||||
|
|
||||||
Note: `scopes` is used by Mastodon — supporting it but sticking to
|
Note: `scopes` is used by Mastodon — supporting it but sticking to
|
||||||
OAuth's standard `scope` wherever we control it
|
OAuth's standard `scope` wherever we control it
|
||||||
|
@ -53,14 +53,14 @@ def to_string(scopes), do: Enum.join(scopes, " ")
|
||||||
@doc """
|
@doc """
|
||||||
Validates scopes.
|
Validates scopes.
|
||||||
"""
|
"""
|
||||||
@spec validates(list() | nil, list()) ::
|
@spec validate(list() | nil, list()) ::
|
||||||
{:ok, list()} | {:error, :missing_scopes | :unsupported_scopes}
|
{:ok, list()} | {:error, :missing_scopes | :unsupported_scopes}
|
||||||
def validates([], _app_scopes), do: {:error, :missing_scopes}
|
def validate([], _app_scopes), do: {:error, :missing_scopes}
|
||||||
def validates(nil, _app_scopes), do: {:error, :missing_scopes}
|
def validate(nil, _app_scopes), do: {:error, :missing_scopes}
|
||||||
|
|
||||||
def validates(scopes, app_scopes) do
|
def validate(scopes, app_scopes) do
|
||||||
case scopes -- app_scopes do
|
case Pleroma.Plugs.OAuthScopesPlug.filter_descendants(scopes, app_scopes) do
|
||||||
[] -> {:ok, scopes}
|
^scopes -> {:ok, scopes}
|
||||||
_ -> {:error, :unsupported_scopes}
|
_ -> {:error, :unsupported_scopes}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,16 +9,13 @@ defmodule Pleroma.Web.OStatus.OStatusController do
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPubController
|
alias Pleroma.Web.ActivityPub.ActivityPubController
|
||||||
alias Pleroma.Web.ActivityPub.ObjectView
|
alias Pleroma.Web.ActivityPub.ObjectView
|
||||||
alias Pleroma.Web.ActivityPub.Visibility
|
alias Pleroma.Web.ActivityPub.Visibility
|
||||||
alias Pleroma.Web.Endpoint
|
alias Pleroma.Web.Endpoint
|
||||||
alias Pleroma.Web.Federator
|
alias Pleroma.Web.Federator
|
||||||
alias Pleroma.Web.Metadata.PlayerView
|
alias Pleroma.Web.Metadata.PlayerView
|
||||||
alias Pleroma.Web.OStatus
|
|
||||||
alias Pleroma.Web.OStatus.ActivityRepresenter
|
alias Pleroma.Web.OStatus.ActivityRepresenter
|
||||||
alias Pleroma.Web.OStatus.FeedRepresenter
|
|
||||||
alias Pleroma.Web.Router
|
alias Pleroma.Web.Router
|
||||||
alias Pleroma.Web.XML
|
alias Pleroma.Web.XML
|
||||||
|
|
||||||
|
@ -31,49 +28,11 @@ defmodule Pleroma.Web.OStatus.OStatusController do
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
Pleroma.Plugs.SetFormatPlug
|
Pleroma.Plugs.SetFormatPlug
|
||||||
when action in [:feed_redirect, :object, :activity, :notice]
|
when action in [:object, :activity, :notice]
|
||||||
)
|
)
|
||||||
|
|
||||||
action_fallback(:errors)
|
action_fallback(:errors)
|
||||||
|
|
||||||
def feed_redirect(%{assigns: %{format: "html"}} = conn, %{"nickname" => nickname}) do
|
|
||||||
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname_or_id(nickname)} do
|
|
||||||
RedirectController.redirector_with_meta(conn, %{user: user})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def feed_redirect(%{assigns: %{format: format}} = conn, _params)
|
|
||||||
when format in ["json", "activity+json"] do
|
|
||||||
ActivityPubController.call(conn, :user)
|
|
||||||
end
|
|
||||||
|
|
||||||
def feed_redirect(conn, %{"nickname" => nickname}) do
|
|
||||||
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do
|
|
||||||
redirect(conn, external: OStatus.feed_path(user))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def feed(conn, %{"nickname" => nickname} = params) do
|
|
||||||
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do
|
|
||||||
activities =
|
|
||||||
params
|
|
||||||
|> Map.take(["max_id"])
|
|
||||||
|> Map.merge(%{"whole_db" => true, "actor_id" => user.ap_id})
|
|
||||||
|> ActivityPub.fetch_public_activities()
|
|
||||||
|> Enum.reverse()
|
|
||||||
|
|
||||||
response =
|
|
||||||
user
|
|
||||||
|> FeedRepresenter.to_simple_form(activities, [user])
|
|
||||||
|> :xmerl.export_simple(:xmerl_xml)
|
|
||||||
|> to_string
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> put_resp_content_type("application/atom+xml")
|
|
||||||
|> send_resp(200, response)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp decode_or_retry(body) do
|
defp decode_or_retry(body) do
|
||||||
with {:ok, magic_key} <- Pleroma.Web.Salmon.fetch_magic_key(body),
|
with {:ok, magic_key} <- Pleroma.Web.Salmon.fetch_magic_key(body),
|
||||||
{:ok, doc} <- Pleroma.Web.Salmon.decode_and_validate(magic_key, body) do
|
{:ok, doc} <- Pleroma.Web.Salmon.decode_and_validate(magic_key, body) do
|
||||||
|
|
|
@ -9,6 +9,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do
|
||||||
only: [json_response: 3, add_link_headers: 2, assign_account_by_id: 2]
|
only: [json_response: 3, add_link_headers: 2, assign_account_by_id: 2]
|
||||||
|
|
||||||
alias Ecto.Changeset
|
alias Ecto.Changeset
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.Plugs.RateLimiter
|
alias Pleroma.Plugs.RateLimiter
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
@ -17,6 +18,30 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do
|
||||||
|
|
||||||
require Pleroma.Constants
|
require Pleroma.Constants
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["follow", "write:follows"]} when action in [:subscribe, :unsubscribe]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["write:accounts"]}
|
||||||
|
# Note: the following actions are not permission-secured in Mastodon:
|
||||||
|
when action in [
|
||||||
|
:update_avatar,
|
||||||
|
:update_banner,
|
||||||
|
:update_background
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read:favourites"]} when action == :favourites)
|
||||||
|
|
||||||
|
# An extra safety measure for possible actions not guarded by OAuth permissions specification
|
||||||
|
plug(
|
||||||
|
Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
|
||||||
|
when action != :confirmation_resend
|
||||||
|
)
|
||||||
|
|
||||||
plug(RateLimiter, :account_confirmation_resend when action == :confirmation_resend)
|
plug(RateLimiter, :account_confirmation_resend when action == :confirmation_resend)
|
||||||
plug(:assign_account_by_id when action in [:favourites, :subscribe, :unsubscribe])
|
plug(:assign_account_by_id when action in [:favourites, :subscribe, :unsubscribe])
|
||||||
plug(:put_view, Pleroma.Web.MastodonAPI.AccountView)
|
plug(:put_view, Pleroma.Web.MastodonAPI.AccountView)
|
||||||
|
|
|
@ -1,8 +1,26 @@
|
||||||
defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
|
defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["write"]}
|
||||||
|
when action in [
|
||||||
|
:create,
|
||||||
|
:delete,
|
||||||
|
:download_from,
|
||||||
|
:list_from,
|
||||||
|
:import_from_fs,
|
||||||
|
:update_file,
|
||||||
|
:update_metadata
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
def emoji_dir_path do
|
def emoji_dir_path do
|
||||||
Path.join(
|
Path.join(
|
||||||
Pleroma.Config.get!([:instance, :static_dir]),
|
Pleroma.Config.get!([:instance, :static_dir]),
|
||||||
|
|
|
@ -5,9 +5,15 @@
|
||||||
defmodule Pleroma.Web.PleromaAPI.MascotController do
|
defmodule Pleroma.Web.PleromaAPI.MascotController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read:accounts"]} when action == :show)
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action != :show)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
@doc "GET /api/v1/pleroma/mascot"
|
@doc "GET /api/v1/pleroma/mascot"
|
||||||
def show(%{assigns: %{user: user}} = conn, _params) do
|
def show(%{assigns: %{user: user}} = conn, _params) do
|
||||||
json(conn, User.get_mascot(user))
|
json(conn, User.get_mascot(user))
|
||||||
|
|
|
@ -9,11 +9,26 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
|
||||||
|
|
||||||
alias Pleroma.Conversation.Participation
|
alias Pleroma.Conversation.Participation
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.MastodonAPI.ConversationView
|
alias Pleroma.Web.MastodonAPI.ConversationView
|
||||||
alias Pleroma.Web.MastodonAPI.NotificationView
|
alias Pleroma.Web.MastodonAPI.NotificationView
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["read:statuses"]} when action in [:conversation, :conversation_statuses]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["write:conversations"]} when action == :update_conversation
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action == :read_notification)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
def conversation(%{assigns: %{user: user}} = conn, %{"id" => participation_id}) do
|
def conversation(%{assigns: %{user: user}} = conn, %{"id" => participation_id}) do
|
||||||
with %Participation{} = participation <- Participation.get(participation_id),
|
with %Participation{} = participation <- Participation.get(participation_id),
|
||||||
true <- user.id == participation.user_id do
|
true <- user.id == participation.user_id do
|
||||||
|
|
|
@ -7,11 +7,17 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleController do
|
||||||
|
|
||||||
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2, fetch_integer_param: 2]
|
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2, fetch_integer_param: 2]
|
||||||
|
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read"]} when action == :user_scrobbles)
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["write"]} when action != :user_scrobbles)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
def new_scrobble(%{assigns: %{user: user}} = conn, %{"title" => _} = params) do
|
def new_scrobble(%{assigns: %{user: user}} = conn, %{"title" => _} = params) do
|
||||||
params =
|
params =
|
||||||
if !params["length"] do
|
if !params["length"] do
|
||||||
|
|
|
@ -87,31 +87,6 @@ defmodule Pleroma.Web.Router do
|
||||||
plug(Pleroma.Plugs.EnsureUserKeyPlug)
|
plug(Pleroma.Plugs.EnsureUserKeyPlug)
|
||||||
end
|
end
|
||||||
|
|
||||||
pipeline :oauth_read_or_public do
|
|
||||||
plug(Pleroma.Plugs.OAuthScopesPlug, %{
|
|
||||||
scopes: ["read"],
|
|
||||||
fallback: :proceed_unauthenticated
|
|
||||||
})
|
|
||||||
|
|
||||||
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
|
||||||
end
|
|
||||||
|
|
||||||
pipeline :oauth_read do
|
|
||||||
plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["read"]})
|
|
||||||
end
|
|
||||||
|
|
||||||
pipeline :oauth_write do
|
|
||||||
plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["write"]})
|
|
||||||
end
|
|
||||||
|
|
||||||
pipeline :oauth_follow do
|
|
||||||
plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["follow"]})
|
|
||||||
end
|
|
||||||
|
|
||||||
pipeline :oauth_push do
|
|
||||||
plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["push"]})
|
|
||||||
end
|
|
||||||
|
|
||||||
pipeline :well_known do
|
pipeline :well_known do
|
||||||
plug(:accepts, ["json", "jrd+json", "xml", "xrd+xml"])
|
plug(:accepts, ["json", "jrd+json", "xml", "xrd+xml"])
|
||||||
end
|
end
|
||||||
|
@ -154,7 +129,7 @@ defmodule Pleroma.Web.Router do
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/api/pleroma/admin", Pleroma.Web.AdminAPI do
|
scope "/api/pleroma/admin", Pleroma.Web.AdminAPI do
|
||||||
pipe_through([:admin_api, :oauth_write])
|
pipe_through(:admin_api)
|
||||||
|
|
||||||
post("/users/follow", AdminAPIController, :user_follow)
|
post("/users/follow", AdminAPIController, :user_follow)
|
||||||
post("/users/unfollow", AdminAPIController, :user_unfollow)
|
post("/users/unfollow", AdminAPIController, :user_unfollow)
|
||||||
|
@ -213,7 +188,7 @@ defmodule Pleroma.Web.Router do
|
||||||
scope "/api/pleroma/emoji", Pleroma.Web.PleromaAPI do
|
scope "/api/pleroma/emoji", Pleroma.Web.PleromaAPI do
|
||||||
scope "/packs" do
|
scope "/packs" do
|
||||||
# Modifying packs
|
# Modifying packs
|
||||||
pipe_through([:admin_api, :oauth_write])
|
pipe_through(:admin_api)
|
||||||
|
|
||||||
post("/import_from_fs", EmojiAPIController, :import_from_fs)
|
post("/import_from_fs", EmojiAPIController, :import_from_fs)
|
||||||
|
|
||||||
|
@ -238,32 +213,21 @@ defmodule Pleroma.Web.Router do
|
||||||
post("/main/ostatus", UtilController, :remote_subscribe)
|
post("/main/ostatus", UtilController, :remote_subscribe)
|
||||||
get("/ostatus_subscribe", UtilController, :remote_follow)
|
get("/ostatus_subscribe", UtilController, :remote_follow)
|
||||||
|
|
||||||
scope [] do
|
|
||||||
pipe_through(:oauth_follow)
|
|
||||||
post("/ostatus_subscribe", UtilController, :do_remote_follow)
|
post("/ostatus_subscribe", UtilController, :do_remote_follow)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
scope "/api/pleroma", Pleroma.Web.TwitterAPI do
|
scope "/api/pleroma", Pleroma.Web.TwitterAPI do
|
||||||
pipe_through(:authenticated_api)
|
pipe_through(:authenticated_api)
|
||||||
|
|
||||||
scope [] do
|
|
||||||
pipe_through(:oauth_write)
|
|
||||||
|
|
||||||
post("/change_email", UtilController, :change_email)
|
post("/change_email", UtilController, :change_email)
|
||||||
post("/change_password", UtilController, :change_password)
|
post("/change_password", UtilController, :change_password)
|
||||||
post("/delete_account", UtilController, :delete_account)
|
post("/delete_account", UtilController, :delete_account)
|
||||||
put("/notification_settings", UtilController, :update_notificaton_settings)
|
put("/notification_settings", UtilController, :update_notificaton_settings)
|
||||||
post("/disable_account", UtilController, :disable_account)
|
post("/disable_account", UtilController, :disable_account)
|
||||||
end
|
|
||||||
|
|
||||||
scope [] do
|
|
||||||
pipe_through(:oauth_follow)
|
|
||||||
|
|
||||||
post("/blocks_import", UtilController, :blocks_import)
|
post("/blocks_import", UtilController, :blocks_import)
|
||||||
post("/follow_import", UtilController, :follow_import)
|
post("/follow_import", UtilController, :follow_import)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
scope "/oauth", Pleroma.Web.OAuth do
|
scope "/oauth", Pleroma.Web.OAuth do
|
||||||
scope [] do
|
scope [] do
|
||||||
|
@ -289,14 +253,14 @@ defmodule Pleroma.Web.Router do
|
||||||
scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
|
scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
|
||||||
scope [] do
|
scope [] do
|
||||||
pipe_through(:authenticated_api)
|
pipe_through(:authenticated_api)
|
||||||
pipe_through(:oauth_read)
|
|
||||||
get("/conversations/:id/statuses", PleromaAPIController, :conversation_statuses)
|
get("/conversations/:id/statuses", PleromaAPIController, :conversation_statuses)
|
||||||
get("/conversations/:id", PleromaAPIController, :conversation)
|
get("/conversations/:id", PleromaAPIController, :conversation)
|
||||||
end
|
end
|
||||||
|
|
||||||
scope [] do
|
scope [] do
|
||||||
pipe_through(:authenticated_api)
|
pipe_through(:authenticated_api)
|
||||||
pipe_through(:oauth_write)
|
|
||||||
patch("/conversations/:id", PleromaAPIController, :update_conversation)
|
patch("/conversations/:id", PleromaAPIController, :update_conversation)
|
||||||
post("/notifications/read", PleromaAPIController, :read_notification)
|
post("/notifications/read", PleromaAPIController, :read_notification)
|
||||||
|
|
||||||
|
@ -312,13 +276,11 @@ defmodule Pleroma.Web.Router do
|
||||||
|
|
||||||
scope [] do
|
scope [] do
|
||||||
pipe_through(:api)
|
pipe_through(:api)
|
||||||
pipe_through(:oauth_read_or_public)
|
|
||||||
get("/accounts/:id/favourites", AccountController, :favourites)
|
get("/accounts/:id/favourites", AccountController, :favourites)
|
||||||
end
|
end
|
||||||
|
|
||||||
scope [] do
|
scope [] do
|
||||||
pipe_through(:authenticated_api)
|
pipe_through(:authenticated_api)
|
||||||
pipe_through(:oauth_follow)
|
|
||||||
|
|
||||||
post("/accounts/:id/subscribe", AccountController, :subscribe)
|
post("/accounts/:id/subscribe", AccountController, :subscribe)
|
||||||
post("/accounts/:id/unsubscribe", AccountController, :unsubscribe)
|
post("/accounts/:id/unsubscribe", AccountController, :unsubscribe)
|
||||||
|
@ -328,17 +290,13 @@ defmodule Pleroma.Web.Router do
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
|
scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
|
||||||
pipe_through([:api, :oauth_read_or_public])
|
pipe_through(:api)
|
||||||
|
|
||||||
get("/accounts/:id/scrobbles", ScrobbleController, :user_scrobbles)
|
get("/accounts/:id/scrobbles", ScrobbleController, :user_scrobbles)
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/api/v1", Pleroma.Web.MastodonAPI do
|
scope "/api/v1", Pleroma.Web.MastodonAPI do
|
||||||
pipe_through(:authenticated_api)
|
pipe_through(:authenticated_api)
|
||||||
|
|
||||||
scope [] do
|
|
||||||
pipe_through(:oauth_read)
|
|
||||||
|
|
||||||
get("/accounts/verify_credentials", AccountController, :verify_credentials)
|
get("/accounts/verify_credentials", AccountController, :verify_credentials)
|
||||||
|
|
||||||
get("/accounts/relationships", AccountController, :relationships)
|
get("/accounts/relationships", AccountController, :relationships)
|
||||||
|
@ -347,14 +305,14 @@ defmodule Pleroma.Web.Router do
|
||||||
get("/accounts/:id/identity_proofs", MastodonAPIController, :empty_array)
|
get("/accounts/:id/identity_proofs", MastodonAPIController, :empty_array)
|
||||||
|
|
||||||
get("/follow_requests", FollowRequestController, :index)
|
get("/follow_requests", FollowRequestController, :index)
|
||||||
get("/blocks", MastodonAPIController, :blocks)
|
get("/blocks", AccountController, :blocks)
|
||||||
get("/mutes", MastodonAPIController, :mutes)
|
get("/mutes", AccountController, :mutes)
|
||||||
|
|
||||||
get("/timelines/home", TimelineController, :home)
|
get("/timelines/home", TimelineController, :home)
|
||||||
get("/timelines/direct", TimelineController, :direct)
|
get("/timelines/direct", TimelineController, :direct)
|
||||||
|
|
||||||
get("/favourites", MastodonAPIController, :favourites)
|
get("/favourites", StatusController, :favourites)
|
||||||
get("/bookmarks", MastodonAPIController, :bookmarks)
|
get("/bookmarks", StatusController, :bookmarks)
|
||||||
|
|
||||||
get("/notifications", NotificationController, :index)
|
get("/notifications", NotificationController, :index)
|
||||||
get("/notifications/:id", NotificationController, :show)
|
get("/notifications/:id", NotificationController, :show)
|
||||||
|
@ -378,11 +336,7 @@ defmodule Pleroma.Web.Router do
|
||||||
get("/conversations", ConversationController, :index)
|
get("/conversations", ConversationController, :index)
|
||||||
post("/conversations/:id/read", ConversationController, :read)
|
post("/conversations/:id/read", ConversationController, :read)
|
||||||
|
|
||||||
get("/endorsements", MastodonAPIController, :empty_array)
|
get("/endorsements", AccountController, :endorsements)
|
||||||
end
|
|
||||||
|
|
||||||
scope [] do
|
|
||||||
pipe_through(:oauth_write)
|
|
||||||
|
|
||||||
patch("/accounts/update_credentials", AccountController, :update_credentials)
|
patch("/accounts/update_credentials", AccountController, :update_credentials)
|
||||||
|
|
||||||
|
@ -421,12 +375,8 @@ defmodule Pleroma.Web.Router do
|
||||||
delete("/filters/:id", FilterController, :delete)
|
delete("/filters/:id", FilterController, :delete)
|
||||||
|
|
||||||
post("/reports", ReportController, :create)
|
post("/reports", ReportController, :create)
|
||||||
end
|
|
||||||
|
|
||||||
scope [] do
|
post("/follows", AccountController, :follows)
|
||||||
pipe_through(:oauth_follow)
|
|
||||||
|
|
||||||
post("/follows", MastodonAPIController, :follows)
|
|
||||||
post("/accounts/:id/follow", AccountController, :follow)
|
post("/accounts/:id/follow", AccountController, :follow)
|
||||||
post("/accounts/:id/unfollow", AccountController, :unfollow)
|
post("/accounts/:id/unfollow", AccountController, :unfollow)
|
||||||
post("/accounts/:id/block", AccountController, :block)
|
post("/accounts/:id/block", AccountController, :block)
|
||||||
|
@ -439,20 +389,15 @@ defmodule Pleroma.Web.Router do
|
||||||
|
|
||||||
post("/domain_blocks", DomainBlockController, :create)
|
post("/domain_blocks", DomainBlockController, :create)
|
||||||
delete("/domain_blocks", DomainBlockController, :delete)
|
delete("/domain_blocks", DomainBlockController, :delete)
|
||||||
end
|
|
||||||
|
|
||||||
scope [] do
|
|
||||||
pipe_through(:oauth_push)
|
|
||||||
|
|
||||||
post("/push/subscription", SubscriptionController, :create)
|
post("/push/subscription", SubscriptionController, :create)
|
||||||
get("/push/subscription", SubscriptionController, :get)
|
get("/push/subscription", SubscriptionController, :get)
|
||||||
put("/push/subscription", SubscriptionController, :update)
|
put("/push/subscription", SubscriptionController, :update)
|
||||||
delete("/push/subscription", SubscriptionController, :delete)
|
delete("/push/subscription", SubscriptionController, :delete)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
scope "/api/web", Pleroma.Web do
|
scope "/api/web", Pleroma.Web do
|
||||||
pipe_through([:authenticated_api, :oauth_write])
|
pipe_through(:authenticated_api)
|
||||||
|
|
||||||
put("/settings", MastoFEController, :put_settings)
|
put("/settings", MastoFEController, :put_settings)
|
||||||
end
|
end
|
||||||
|
@ -477,9 +422,6 @@ defmodule Pleroma.Web.Router do
|
||||||
|
|
||||||
get("/trends", MastodonAPIController, :empty_array)
|
get("/trends", MastodonAPIController, :empty_array)
|
||||||
|
|
||||||
scope [] do
|
|
||||||
pipe_through(:oauth_read_or_public)
|
|
||||||
|
|
||||||
get("/timelines/public", TimelineController, :public)
|
get("/timelines/public", TimelineController, :public)
|
||||||
get("/timelines/tag/:tag", TimelineController, :hashtag)
|
get("/timelines/tag/:tag", TimelineController, :hashtag)
|
||||||
get("/timelines/list/:list_id", TimelineController, :list)
|
get("/timelines/list/:list_id", TimelineController, :list)
|
||||||
|
@ -497,10 +439,9 @@ defmodule Pleroma.Web.Router do
|
||||||
|
|
||||||
get("/search", SearchController, :search)
|
get("/search", SearchController, :search)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
scope "/api/v2", Pleroma.Web.MastodonAPI do
|
scope "/api/v2", Pleroma.Web.MastodonAPI do
|
||||||
pipe_through([:api, :oauth_read_or_public])
|
pipe_through(:api)
|
||||||
get("/search", SearchController, :search2)
|
get("/search", SearchController, :search2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -531,12 +472,8 @@ defmodule Pleroma.Web.Router do
|
||||||
get("/oauth_tokens", TwitterAPI.Controller, :oauth_tokens)
|
get("/oauth_tokens", TwitterAPI.Controller, :oauth_tokens)
|
||||||
delete("/oauth_tokens/:id", TwitterAPI.Controller, :revoke_token)
|
delete("/oauth_tokens/:id", TwitterAPI.Controller, :revoke_token)
|
||||||
|
|
||||||
scope [] do
|
|
||||||
pipe_through(:oauth_read)
|
|
||||||
|
|
||||||
post("/qvitter/statuses/notifications/read", TwitterAPI.Controller, :notifications_read)
|
post("/qvitter/statuses/notifications/read", TwitterAPI.Controller, :notifications_read)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
pipeline :ap_service_actor do
|
pipeline :ap_service_actor do
|
||||||
plug(:accepts, ["activity+json", "json"])
|
plug(:accepts, ["activity+json", "json"])
|
||||||
|
@ -558,8 +495,9 @@ defmodule Pleroma.Web.Router do
|
||||||
get("/activities/:uuid", OStatus.OStatusController, :activity)
|
get("/activities/:uuid", OStatus.OStatusController, :activity)
|
||||||
get("/notice/:id", OStatus.OStatusController, :notice)
|
get("/notice/:id", OStatus.OStatusController, :notice)
|
||||||
get("/notice/:id/embed_player", OStatus.OStatusController, :notice_player)
|
get("/notice/:id/embed_player", OStatus.OStatusController, :notice_player)
|
||||||
get("/users/:nickname/feed", OStatus.OStatusController, :feed)
|
|
||||||
get("/users/:nickname", OStatus.OStatusController, :feed_redirect)
|
get("/users/:nickname/feed", Feed.FeedController, :feed)
|
||||||
|
get("/users/:nickname", Feed.FeedController, :feed_redirect)
|
||||||
|
|
||||||
post("/users/:nickname/salmon", OStatus.OStatusController, :salmon_incoming)
|
post("/users/:nickname/salmon", OStatus.OStatusController, :salmon_incoming)
|
||||||
post("/push/hub/:nickname", Websub.WebsubController, :websub_subscription_request)
|
post("/push/hub/:nickname", Websub.WebsubController, :websub_subscription_request)
|
||||||
|
@ -599,24 +537,15 @@ defmodule Pleroma.Web.Router do
|
||||||
scope "/", Pleroma.Web.ActivityPub do
|
scope "/", Pleroma.Web.ActivityPub do
|
||||||
pipe_through([:activitypub_client])
|
pipe_through([:activitypub_client])
|
||||||
|
|
||||||
scope [] do
|
|
||||||
pipe_through(:oauth_read)
|
|
||||||
get("/api/ap/whoami", ActivityPubController, :whoami)
|
get("/api/ap/whoami", ActivityPubController, :whoami)
|
||||||
get("/users/:nickname/inbox", ActivityPubController, :read_inbox)
|
get("/users/:nickname/inbox", ActivityPubController, :read_inbox)
|
||||||
end
|
|
||||||
|
|
||||||
scope [] do
|
|
||||||
pipe_through(:oauth_write)
|
|
||||||
post("/users/:nickname/outbox", ActivityPubController, :update_outbox)
|
post("/users/:nickname/outbox", ActivityPubController, :update_outbox)
|
||||||
post("/api/ap/upload_media", ActivityPubController, :upload_media)
|
post("/api/ap/upload_media", ActivityPubController, :upload_media)
|
||||||
end
|
|
||||||
|
|
||||||
scope [] do
|
|
||||||
pipe_through(:oauth_read_or_public)
|
|
||||||
get("/users/:nickname/followers", ActivityPubController, :followers)
|
get("/users/:nickname/followers", ActivityPubController, :followers)
|
||||||
get("/users/:nickname/following", ActivityPubController, :following)
|
get("/users/:nickname/following", ActivityPubController, :following)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
scope "/", Pleroma.Web.ActivityPub do
|
scope "/", Pleroma.Web.ActivityPub do
|
||||||
pipe_through(:activitypub)
|
pipe_through(:activitypub)
|
||||||
|
@ -665,11 +594,8 @@ defmodule Pleroma.Web.Router do
|
||||||
|
|
||||||
post("/auth/password", MastodonAPI.AuthController, :password_reset)
|
post("/auth/password", MastodonAPI.AuthController, :password_reset)
|
||||||
|
|
||||||
scope [] do
|
|
||||||
pipe_through(:oauth_read)
|
|
||||||
get("/web/*path", MastoFEController, :index)
|
get("/web/*path", MastoFEController, :index)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
pipeline :remote_media do
|
pipeline :remote_media do
|
||||||
end
|
end
|
||||||
|
|
|
@ -202,7 +202,7 @@ def is_representable?(_), do: false
|
||||||
@spec publish(User.t(), Pleroma.Activity.t()) :: none
|
@spec publish(User.t(), Pleroma.Activity.t()) :: none
|
||||||
def publish(user, activity)
|
def publish(user, activity)
|
||||||
|
|
||||||
def publish(%{info: %{keys: keys}} = user, %{data: %{"type" => type}} = activity)
|
def publish(%{keys: keys} = user, %{data: %{"type" => type}} = activity)
|
||||||
when type in @supported_activities do
|
when type in @supported_activities do
|
||||||
feed = ActivityRepresenter.to_simple_form(activity, user, true)
|
feed = ActivityRepresenter.to_simple_form(activity, user, true)
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ def publish(%{info: %{keys: keys}} = user, %{data: %{"type" => type}} = activity
|
||||||
def publish(%{id: id}, _), do: Logger.debug(fn -> "Keys missing for user #{id}" end)
|
def publish(%{id: id}, _), do: Logger.debug(fn -> "Keys missing for user #{id}" end)
|
||||||
|
|
||||||
def gather_webfinger_links(%User{} = user) do
|
def gather_webfinger_links(%User{} = user) do
|
||||||
{:ok, _private, public} = Keys.keys_from_pem(user.info.keys)
|
{:ok, _private, public} = Keys.keys_from_pem(user.keys)
|
||||||
magic_key = encode_key(public)
|
magic_key = encode_key(public)
|
||||||
|
|
||||||
[
|
[
|
||||||
|
|
48
lib/pleroma/web/templates/feed/feed/_activity.xml.eex
Normal file
48
lib/pleroma/web/templates/feed/feed/_activity.xml.eex
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<entry>
|
||||||
|
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
|
||||||
|
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||||
|
<id><%= @data["id"] %></id>
|
||||||
|
<title><%= "New note by #{@user.nickname}" %></title>
|
||||||
|
<content type="html"><%= activity_content(@activity) %></content>
|
||||||
|
<published><%= @data["published"] %></published>
|
||||||
|
<updated><%= @data["published"] %></updated>
|
||||||
|
<ostatus:conversation ref="<%= activity_context(@activity) %>"><%= activity_context(@activity) %></ostatus:conversation>
|
||||||
|
<link ref="<%= activity_context(@activity) %>" rel="ostatus:conversation"/>
|
||||||
|
|
||||||
|
<%= if @data["summary"] do %>
|
||||||
|
<summary><%= @data["summary"] %></summary>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= if @activity.local do %>
|
||||||
|
<link type="application/atom+xml" href='<%= @data["id"] %>' rel="self"/>
|
||||||
|
<link type="text/html" href='<%= @data["id"] %>' rel="alternate"/>
|
||||||
|
<% else %>
|
||||||
|
<link type="text/html" href='<%= @data["external_url"] %>' rel="alternate"/>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= for tag <- @data["tag"] || [] do %>
|
||||||
|
<category term="<%= tag %>"></category>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= for attachment <- @data["attachment"] || [] do %>
|
||||||
|
<link rel="enclosure" href="<%= attachment_href(attachment) %>" type="<%= attachment_type(attachment) %>"/>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= if @data["inReplyTo"] do %>
|
||||||
|
<thr:in-reply-to ref='<%= @data["inReplyTo"] %>' href='<%= get_href(@data["inReplyTo"]) %>'/>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= for id <- @activity.recipients do %>
|
||||||
|
<%= if id == Pleroma.Constants.as_public() do %>
|
||||||
|
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||||
|
<% else %>
|
||||||
|
<%= unless Regex.match?(~r/^#{Pleroma.Web.base_url()}.+followers$/, id) do %>
|
||||||
|
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="<%= id %>"/>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= for {emoji, file} <- @data["emoji"] || %{} do %>
|
||||||
|
<link name="<%= emoji %>" rel="emoji" href="<%= file %>"/>
|
||||||
|
<% end %>
|
||||||
|
</entry>
|
17
lib/pleroma/web/templates/feed/feed/_author.xml.eex
Normal file
17
lib/pleroma/web/templates/feed/feed/_author.xml.eex
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<author>
|
||||||
|
<id><%= @user.ap_id %></id>
|
||||||
|
<activity:object>http://activitystrea.ms/schema/1.0/person</activity:object>
|
||||||
|
<uri><%= @user.ap_id %></uri>
|
||||||
|
<poco:preferredUsername><%= @user.nickname %></poco:preferredUsername>
|
||||||
|
<poco:displayName><%= @user.name %></poco:displayName>
|
||||||
|
<poco:note><%= escape(@user.bio) %></poco:note>
|
||||||
|
<summary><%= escape(@user.bio) %></summary>
|
||||||
|
<name><%= @user.nickname %></name>
|
||||||
|
<link rel="avatar" href="<%= User.avatar_url(@user) %>"/>
|
||||||
|
<%= if User.banner_url(@user) do %>
|
||||||
|
<link rel="header" href="<%= User.banner_url(@user) %>"/>
|
||||||
|
<% end %>
|
||||||
|
<%= if @user.local do %>
|
||||||
|
<ap_enabled>true</ap_enabled>
|
||||||
|
<% end %>
|
||||||
|
</author>
|
26
lib/pleroma/web/templates/feed/feed/feed.xml.eex
Normal file
26
lib/pleroma/web/templates/feed/feed/feed.xml.eex
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<feed
|
||||||
|
xmlns="http://www.w3.org/2005/Atom"
|
||||||
|
xmlns:thr="http://purl.org/syndication/thread/1.0"
|
||||||
|
xmlns:activity="http://activitystrea.ms/spec/1.0/"
|
||||||
|
xmlns:poco="http://portablecontacts.net/spec/1.0"
|
||||||
|
xmlns:ostatus="http://ostatus.org/schema/1.0">
|
||||||
|
|
||||||
|
<id><%= feed_url(@conn, :feed, @user.nickname) <> ".atom" %></id>
|
||||||
|
<title><%= @user.nickname <> "'s timeline" %></title>
|
||||||
|
<updated><%= most_recent_update(@activities, @user) %></updated>
|
||||||
|
<logo><%= logo(@user) %></logo>
|
||||||
|
<link rel="hub" href="<%= websub_url(@conn, :websub_subscription_request, @user.nickname) %>"/>
|
||||||
|
<link rel="salmon" href="<%= o_status_url(@conn, :salmon_incoming, @user.nickname) %>"/>
|
||||||
|
<link rel="self" href="<%= '#{feed_url(@conn, :feed, @user.nickname)}.atom' %>" type="application/atom+xml"/>
|
||||||
|
|
||||||
|
<%= render @view_module, "_author.xml", assigns %>
|
||||||
|
|
||||||
|
<%= if last_activity(@activities) do %>
|
||||||
|
<link rel="next" href="<%= '#{feed_url(@conn, :feed, @user.nickname)}.atom?max_id=#{last_activity(@activities).id}' %>" type="application/atom+xml"/>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= for activity <- @activities do %>
|
||||||
|
<%= render @view_module, "_activity.xml", Map.merge(assigns, %{activity: activity, data: activity_object_data(activity)}) %>
|
||||||
|
<% end %>
|
||||||
|
</feed>
|
|
@ -13,11 +13,34 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
||||||
alias Pleroma.Healthcheck
|
alias Pleroma.Healthcheck
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
alias Pleroma.Plugs.AuthenticationPlug
|
alias Pleroma.Plugs.AuthenticationPlug
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web
|
alias Pleroma.Web
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.WebFinger
|
alias Pleroma.Web.WebFinger
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["follow", "write:follows"]}
|
||||||
|
when action in [:do_remote_follow, :follow_import]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["follow", "write:blocks"]} when action == :blocks_import)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["write:accounts"]}
|
||||||
|
when action in [
|
||||||
|
:change_email,
|
||||||
|
:change_password,
|
||||||
|
:delete_account,
|
||||||
|
:update_notificaton_settings,
|
||||||
|
:disable_account
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action == :notifications_read)
|
||||||
|
|
||||||
plug(Pleroma.Plugs.SetFormatPlug when action in [:config, :version])
|
plug(Pleroma.Plugs.SetFormatPlug when action in [:config, :version])
|
||||||
|
|
||||||
def help_test(conn, _params) do
|
def help_test(conn, _params) do
|
||||||
|
|
|
@ -6,12 +6,17 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.OAuth.Token
|
alias Pleroma.Web.OAuth.Token
|
||||||
alias Pleroma.Web.TwitterAPI.TokenView
|
alias Pleroma.Web.TwitterAPI.TokenView
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action == :notifications_read)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||||
|
|
||||||
action_fallback(:errors)
|
action_fallback(:errors)
|
||||||
|
|
||||||
def confirm_email(conn, %{"user_id" => uid, "token" => token}) do
|
def confirm_email(conn, %{"user_id" => uid, "token" => token}) do
|
||||||
|
|
|
@ -3,14 +3,13 @@ defmodule Pleroma.Repo.Migrations.CreatePleroma.User do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists table(:users) do
|
create_if_not_exists table(:users) do
|
||||||
add :email, :string
|
add(:email, :string)
|
||||||
add :password_hash, :string
|
add(:password_hash, :string)
|
||||||
add :name, :string
|
add(:name, :string)
|
||||||
add :nickname, :string
|
add(:nickname, :string)
|
||||||
add :bio, :string
|
add(:bio, :string)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,12 +3,11 @@ defmodule Pleroma.Repo.Migrations.CreatePleroma.Activity do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists table(:activities) do
|
create_if_not_exists table(:activities) do
|
||||||
add :data, :map
|
add(:data, :map)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
create_if_not_exists index(:activities, [:data], using: :gin)
|
create_if_not_exists(index(:activities, [:data], using: :gin))
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,10 +3,9 @@ defmodule Pleroma.Repo.Migrations.CreatePleroma.Object do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists table(:objects) do
|
create_if_not_exists table(:objects) do
|
||||||
add :data, :map
|
add(:data, :map)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@ defmodule Pleroma.Repo.Migrations.AddFollowingListToUsers do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
alter table(:users) do
|
alter table(:users) do
|
||||||
add :following, :map
|
add(:following, :map)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@ defmodule Pleroma.Repo.Migrations.AddApIdToUsers do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
alter table(:users) do
|
alter table(:users) do
|
||||||
add :ap_id, :string
|
add(:ap_id, :string)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.AddIndexToObjects do
|
||||||
use Ecto.Migration
|
use Ecto.Migration
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists index(:objects, [:data], using: :gin)
|
create_if_not_exists(index(:objects, [:data], using: :gin))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,7 @@ defmodule Pleroma.Repo.Migrations.AddUniqueIndexToEmailAndNickname do
|
||||||
use Ecto.Migration
|
use Ecto.Migration
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists unique_index(:users, [:email])
|
create_if_not_exists(unique_index(:users, [:email]))
|
||||||
create_if_not_exists unique_index(:users, [:nickname])
|
create_if_not_exists(unique_index(:users, [:nickname]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@ defmodule Pleroma.Repo.Migrations.AddAvatarObjectToUsers do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
alter table(:users) do
|
alter table(:users) do
|
||||||
add :avatar, :map
|
add(:avatar, :map)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,11 +3,11 @@ defmodule Pleroma.Repo.Migrations.CreateWebsubServerSubscription do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists table(:websub_server_subscriptions) do
|
create_if_not_exists table(:websub_server_subscriptions) do
|
||||||
add :topic, :string
|
add(:topic, :string)
|
||||||
add :callback, :string
|
add(:callback, :string)
|
||||||
add :secret, :string
|
add(:secret, :string)
|
||||||
add :valid_until, :naive_datetime
|
add(:valid_until, :naive_datetime)
|
||||||
add :state, :string
|
add(:state, :string)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,8 +3,8 @@ defmodule Pleroma.Repo.Migrations.AddFieldsToUsers do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
alter table(:users) do
|
alter table(:users) do
|
||||||
add :local, :boolean, default: true
|
add(:local, :boolean, default: true)
|
||||||
add :info, :map
|
add(:info, :map)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,11 +3,11 @@ defmodule Pleroma.Repo.Migrations.CreateWebsubClientSubscription do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists table(:websub_client_subscriptions) do
|
create_if_not_exists table(:websub_client_subscriptions) do
|
||||||
add :topic, :string
|
add(:topic, :string)
|
||||||
add :secret, :string
|
add(:secret, :string)
|
||||||
add :valid_until, :naive_datetime_usec
|
add(:valid_until, :naive_datetime_usec)
|
||||||
add :state, :string
|
add(:state, :string)
|
||||||
add :subscribers, :map
|
add(:subscribers, :map)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,8 +3,8 @@ defmodule Pleroma.Repo.Migrations.AddUserAndHub do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
alter table(:websub_client_subscriptions) do
|
alter table(:websub_client_subscriptions) do
|
||||||
add :hub, :string
|
add(:hub, :string)
|
||||||
add :user_id, references(:users)
|
add(:user_id, references(:users))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,10 +2,16 @@ defmodule Pleroma.Repo.Migrations.AddIdContraintsToActivitiesAndObjectsPartTwo d
|
||||||
use Ecto.Migration
|
use Ecto.Migration
|
||||||
|
|
||||||
def up do
|
def up do
|
||||||
drop_if_exists index(:objects, ["(data->>\"id\")"], name: :objects_unique_apid_index)
|
drop_if_exists(index(:objects, ["(data->>\"id\")"], name: :objects_unique_apid_index))
|
||||||
drop_if_exists index(:activities, ["(data->>\"id\")"], name: :activities_unique_apid_index)
|
drop_if_exists(index(:activities, ["(data->>\"id\")"], name: :activities_unique_apid_index))
|
||||||
create_if_not_exists unique_index(:objects, ["(data->>'id')"], name: :objects_unique_apid_index)
|
|
||||||
create_if_not_exists unique_index(:activities, ["(data->>'id')"], name: :activities_unique_apid_index)
|
create_if_not_exists(
|
||||||
|
unique_index(:objects, ["(data->>'id')"], name: :objects_unique_apid_index)
|
||||||
|
)
|
||||||
|
|
||||||
|
create_if_not_exists(
|
||||||
|
unique_index(:activities, ["(data->>'id')"], name: :activities_unique_apid_index)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def down, do: :ok
|
def down, do: :ok
|
||||||
|
|
|
@ -3,9 +3,9 @@ defmodule Pleroma.Repo.Migrations.AddLocalFieldToActivities do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
alter table(:activities) do
|
alter table(:activities) do
|
||||||
add :local, :boolean, default: true
|
add(:local, :boolean, default: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
create_if_not_exists index(:activities, [:local])
|
create_if_not_exists(index(:activities, [:local]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.AddUniqueIndexToAPID do
|
||||||
use Ecto.Migration
|
use Ecto.Migration
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists unique_index(:users, [:ap_id])
|
create_if_not_exists(unique_index(:users, [:ap_id]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,14 +3,13 @@ defmodule Pleroma.Repo.Migrations.LongerBios do
|
||||||
|
|
||||||
def up do
|
def up do
|
||||||
alter table(:users) do
|
alter table(:users) do
|
||||||
modify :bio, :text
|
modify(:bio, :text)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def down do
|
def down do
|
||||||
alter table(:users) do
|
alter table(:users) do
|
||||||
modify :bio, :string
|
modify(:bio, :string)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.RemoveActivitiesIndex do
|
||||||
use Ecto.Migration
|
use Ecto.Migration
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
drop_if_exists index(:activities, [:data])
|
drop_if_exists(index(:activities, [:data]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,16 @@ defmodule Pleroma.Repo.Migrations.AddObjectActivityIndexPartTwo do
|
||||||
use Ecto.Migration
|
use Ecto.Migration
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
drop_if_exists index(:objects, ["(data->'object'->>'id')", "(data->>'type')"], name: :activities_create_objects_index)
|
drop_if_exists(
|
||||||
create_if_not_exists index(:activities, ["(data->'object'->>'id')", "(data->>'type')"], name: :activities_create_objects_index)
|
index(:objects, ["(data->'object'->>'id')", "(data->>'type')"],
|
||||||
|
name: :activities_create_objects_index
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
create_if_not_exists(
|
||||||
|
index(:activities, ["(data->'object'->>'id')", "(data->>'type')"],
|
||||||
|
name: :activities_create_objects_index
|
||||||
|
)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,8 @@ defmodule Pleroma.Repo.Migrations.AddActorIndexToActivity do
|
||||||
use Ecto.Migration
|
use Ecto.Migration
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists index(:activities, ["(data->>'actor')", "inserted_at desc"], name: :activities_actor_index)
|
create_if_not_exists(
|
||||||
|
index(:activities, ["(data->>'actor')", "inserted_at desc"], name: :activities_actor_index)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,13 +3,13 @@ defmodule Pleroma.Repo.Migrations.AddFollowerAddressToUser do
|
||||||
|
|
||||||
def up do
|
def up do
|
||||||
alter table(:users) do
|
alter table(:users) do
|
||||||
add :follower_address, :string, unique: true
|
add(:follower_address, :string, unique: true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def down do
|
def down do
|
||||||
alter table(:users) do
|
alter table(:users) do
|
||||||
remove :follower_address
|
remove(:follower_address)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,12 +3,12 @@ defmodule Pleroma.Repo.Migrations.AddMastodonApps do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists table(:apps) do
|
create_if_not_exists table(:apps) do
|
||||||
add :client_name, :string
|
add(:client_name, :string)
|
||||||
add :redirect_uris, :string
|
add(:redirect_uris, :string)
|
||||||
add :scopes, :string
|
add(:scopes, :string)
|
||||||
add :website, :string
|
add(:website, :string)
|
||||||
add :client_id, :string
|
add(:client_id, :string)
|
||||||
add :client_secret, :string
|
add(:client_secret, :string)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,11 +3,11 @@ defmodule Pleroma.Repo.Migrations.CreateOAuthAuthorizations do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists table(:oauth_authorizations) do
|
create_if_not_exists table(:oauth_authorizations) do
|
||||||
add :app_id, references(:apps)
|
add(:app_id, references(:apps))
|
||||||
add :user_id, references(:users)
|
add(:user_id, references(:users))
|
||||||
add :token, :string
|
add(:token, :string)
|
||||||
add :valid_until, :naive_datetime_usec
|
add(:valid_until, :naive_datetime_usec)
|
||||||
add :used, :boolean, default: false
|
add(:used, :boolean, default: false)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,11 +3,11 @@ defmodule Pleroma.Repo.Migrations.CreateOAuthToken do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists table(:oauth_tokens) do
|
create_if_not_exists table(:oauth_tokens) do
|
||||||
add :app_id, references(:apps)
|
add(:app_id, references(:apps))
|
||||||
add :user_id, references(:users)
|
add(:user_id, references(:users))
|
||||||
add :token, :string
|
add(:token, :string)
|
||||||
add :refresh_token, :string
|
add(:refresh_token, :string)
|
||||||
add :valid_until, :naive_datetime_usec
|
add(:valid_until, :naive_datetime_usec)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,13 +3,13 @@ defmodule Pleroma.Repo.Migrations.CreateNotifications do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists table(:notifications) do
|
create_if_not_exists table(:notifications) do
|
||||||
add :user_id, references(:users, on_delete: :delete_all)
|
add(:user_id, references(:users, on_delete: :delete_all))
|
||||||
add :activity_id, references(:activities, on_delete: :delete_all)
|
add(:activity_id, references(:activities, on_delete: :delete_all))
|
||||||
add :seen, :boolean, default: false
|
add(:seen, :boolean, default: false)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
create_if_not_exists index(:notifications, [:user_id])
|
create_if_not_exists(index(:notifications, [:user_id]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,6 +3,11 @@ defmodule Pleroma.Repo.Migrations.AddContextIndex do
|
||||||
@disable_ddl_transaction true
|
@disable_ddl_transaction true
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create index(:activities, ["(data->>'type')", "(data->>'context')"], name: :activities_context_index, concurrently: true)
|
create(
|
||||||
|
index(:activities, ["(data->>'type')", "(data->>'context')"],
|
||||||
|
name: :activities_context_index,
|
||||||
|
concurrently: true
|
||||||
|
)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,6 +3,12 @@ defmodule Pleroma.Repo.Migrations.AddFTSIndexToActivities do
|
||||||
@disable_ddl_transaction true
|
@disable_ddl_transaction true
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create index(:activities, ["(to_tsvector('english', data->'object'->>'content'))"], concurrently: true, using: :gin, name: :activities_fts)
|
create(
|
||||||
|
index(:activities, ["(to_tsvector('english', data->'object'->>'content'))"],
|
||||||
|
concurrently: true,
|
||||||
|
using: :gin,
|
||||||
|
name: :activities_fts
|
||||||
|
)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,6 +4,12 @@ defmodule Pleroma.Repo.Migrations.AddTagIndex do
|
||||||
@disable_ddl_transaction true
|
@disable_ddl_transaction true
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create index(:activities, ["(data #> '{\"object\",\"tag\"}')"], concurrently: true, using: :gin, name: :activities_tags)
|
create(
|
||||||
|
index(:activities, ["(data #> '{\"object\",\"tag\"}')"],
|
||||||
|
concurrently: true,
|
||||||
|
using: :gin,
|
||||||
|
name: :activities_tags
|
||||||
|
)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,9 +3,9 @@ defmodule Pleroma.Repo.Migrations.CreatePasswordResetTokens do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists table(:password_reset_tokens) do
|
create_if_not_exists table(:password_reset_tokens) do
|
||||||
add :token, :string
|
add(:token, :string)
|
||||||
add :user_id, references(:users)
|
add(:user_id, references(:users))
|
||||||
add :used, :boolean, default: false
|
add(:used, :boolean, default: false)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,17 @@ defmodule Pleroma.Repo.Migrations.AddSecondObjectIndexToActivty do
|
||||||
@disable_ddl_transaction true
|
@disable_ddl_transaction true
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
drop_if_exists index(:activities, ["(data->'object'->>'id')", "(data->>'type')"], name: :activities_create_objects_index)
|
drop_if_exists(
|
||||||
create index(:activities, ["(coalesce(data->'object'->>'id', data->>'object'))"], name: :activities_create_objects_index, concurrently: true)
|
index(:activities, ["(data->'object'->>'id')", "(data->>'type')"],
|
||||||
|
name: :activities_create_objects_index
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
create(
|
||||||
|
index(:activities, ["(coalesce(data->'object'->>'id', data->>'object'))"],
|
||||||
|
name: :activities_create_objects_index,
|
||||||
|
concurrently: true
|
||||||
|
)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.DropObjectIndex do
|
||||||
use Ecto.Migration
|
use Ecto.Migration
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
drop_if_exists index(:objects, [:data], using: :gin)
|
drop_if_exists(index(:objects, [:data], using: :gin))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,6 +4,11 @@ defmodule Pleroma.Repo.Migrations.AddObjectActorIndex do
|
||||||
@disable_ddl_transaction true
|
@disable_ddl_transaction true
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create index(:objects, ["(data->>'actor')", "(data->>'type')"], concurrently: true, name: :objects_actor_type)
|
create(
|
||||||
|
index(:objects, ["(data->>'actor')", "(data->>'type')"],
|
||||||
|
concurrently: true,
|
||||||
|
name: :objects_actor_type
|
||||||
|
)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,16 +5,17 @@ defmodule Pleroma.Repo.Migrations.AddActorToActivity do
|
||||||
|
|
||||||
def up do
|
def up do
|
||||||
alter table(:activities) do
|
alter table(:activities) do
|
||||||
add :actor, :string
|
add(:actor, :string)
|
||||||
end
|
end
|
||||||
|
|
||||||
create index(:activities, [:actor, "id DESC NULLS LAST"], concurrently: true)
|
create(index(:activities, [:actor, "id DESC NULLS LAST"], concurrently: true))
|
||||||
end
|
end
|
||||||
|
|
||||||
def down do
|
def down do
|
||||||
drop_if_exists index(:activities, [:actor, "id DESC NULLS LAST"])
|
drop_if_exists(index(:activities, [:actor, "id DESC NULLS LAST"]))
|
||||||
|
|
||||||
alter table(:activities) do
|
alter table(:activities) do
|
||||||
remove :actor
|
remove(:actor)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,17 +5,19 @@ defmodule Pleroma.Repo.Migrations.FillActorField do
|
||||||
|
|
||||||
def up do
|
def up do
|
||||||
max = Repo.aggregate(Activity, :max, :id)
|
max = Repo.aggregate(Activity, :max, :id)
|
||||||
|
|
||||||
if max do
|
if max do
|
||||||
IO.puts("#{max} activities")
|
IO.puts("#{max} activities")
|
||||||
chunks = 0..(round(max / 10_000))
|
chunks = 0..round(max / 10_000)
|
||||||
|
|
||||||
Enum.each(chunks, fn (i) ->
|
Enum.each(chunks, fn i ->
|
||||||
min = i * 10_000
|
min = i * 10_000
|
||||||
max = min + 10_000
|
max = min + 10_000
|
||||||
|
|
||||||
execute("""
|
execute("""
|
||||||
update activities set actor = data->>'actor' where id > #{min} and id <= #{max};
|
update activities set actor = data->>'actor' where id > #{min} and id <= #{max};
|
||||||
""")
|
""")
|
||||||
|> IO.inspect
|
|> IO.inspect()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -23,4 +25,3 @@ def up do
|
||||||
def down do
|
def down do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,6 @@ defmodule Pleroma.Repo.Migrations.AddSortIndexToActivities do
|
||||||
@disable_ddl_transaction true
|
@disable_ddl_transaction true
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create index(:activities, ["id desc nulls last"], concurrently: true)
|
create(index(:activities, ["id desc nulls last"], concurrently: true))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.AddLocalIndexToUser do
|
||||||
use Ecto.Migration
|
use Ecto.Migration
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists index(:users, [:local])
|
create_if_not_exists(index(:users, [:local]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,9 +3,9 @@ defmodule Pleroma.Repo.Migrations.AddRecipientsToActivities do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
alter table(:activities) do
|
alter table(:activities) do
|
||||||
add :recipients, {:array, :string}
|
add(:recipients, {:array, :string})
|
||||||
end
|
end
|
||||||
|
|
||||||
create_if_not_exists index(:activities, [:recipients], using: :gin)
|
create_if_not_exists(index(:activities, [:recipients], using: :gin))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,17 +4,21 @@ defmodule Pleroma.Repo.Migrations.FillRecipientsInActivities do
|
||||||
|
|
||||||
def up do
|
def up do
|
||||||
max = Repo.aggregate(Activity, :max, :id)
|
max = Repo.aggregate(Activity, :max, :id)
|
||||||
|
|
||||||
if max do
|
if max do
|
||||||
IO.puts("#{max} activities")
|
IO.puts("#{max} activities")
|
||||||
chunks = 0..(round(max / 10_000))
|
chunks = 0..round(max / 10_000)
|
||||||
|
|
||||||
Enum.each(chunks, fn (i) ->
|
Enum.each(chunks, fn i ->
|
||||||
min = i * 10_000
|
min = i * 10_000
|
||||||
max = min + 10_000
|
max = min + 10_000
|
||||||
|
|
||||||
execute("""
|
execute("""
|
||||||
update activities set recipients = array(select jsonb_array_elements_text(data->'to')) where id > #{min} and id <= #{max};
|
update activities set recipients = array(select jsonb_array_elements_text(data->'to')) where id > #{
|
||||||
|
min
|
||||||
|
} and id <= #{max};
|
||||||
""")
|
""")
|
||||||
|> IO.inspect
|
|> IO.inspect()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,17 +3,18 @@ defmodule Pleroma.Repo.Migrations.MakeFollowingPostgresArray do
|
||||||
|
|
||||||
def up do
|
def up do
|
||||||
alter table(:users) do
|
alter table(:users) do
|
||||||
add :following_temp, {:array, :string}
|
add(:following_temp, {:array, :string})
|
||||||
end
|
end
|
||||||
|
|
||||||
execute """
|
execute("""
|
||||||
update users set following_temp = array(select jsonb_array_elements_text(following));
|
update users set following_temp = array(select jsonb_array_elements_text(following));
|
||||||
"""
|
""")
|
||||||
|
|
||||||
alter table(:users) do
|
alter table(:users) do
|
||||||
remove :following
|
remove(:following)
|
||||||
end
|
end
|
||||||
rename table(:users), :following_temp, to: :following
|
|
||||||
|
rename(table(:users), :following_temp, to: :following)
|
||||||
end
|
end
|
||||||
|
|
||||||
def down, do: :ok
|
def down, do: :ok
|
||||||
|
|
|
@ -3,7 +3,7 @@ defmodule Pleroma.Repo.Migrations.AddFollowerAddressIndexToUsers do
|
||||||
|
|
||||||
@disable_ddl_transaction true
|
@disable_ddl_transaction true
|
||||||
def change do
|
def change do
|
||||||
create index(:users, [:follower_address], concurrently: true)
|
create(index(:users, [:follower_address], concurrently: true))
|
||||||
create index(:users, [:following], concurrently: true, using: :gin)
|
create(index(:users, [:following], concurrently: true, using: :gin))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.DropLocalIndexOnActivities do
|
||||||
use Ecto.Migration
|
use Ecto.Migration
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
drop_if_exists index(:users, [:local])
|
drop_if_exists(index(:users, [:local]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,7 @@ defmodule Pleroma.Repo.Migrations.ActuallyDropLocalIndex do
|
||||||
use Ecto.Migration
|
use Ecto.Migration
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists index(:users, [:local])
|
create_if_not_exists(index(:users, [:local]))
|
||||||
drop_if_exists index("activities", :local)
|
drop_if_exists(index("activities", :local))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,13 +3,13 @@ defmodule Pleroma.Repo.Migrations.CreateLists do
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
create_if_not_exists table(:lists) do
|
create_if_not_exists table(:lists) do
|
||||||
add :user_id, references(:users, on_delete: :delete_all)
|
add(:user_id, references(:users, on_delete: :delete_all))
|
||||||
add :title, :string
|
add(:title, :string)
|
||||||
add :following, {:array, :string}
|
add(:following, {:array, :string})
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
create_if_not_exists index(:lists, [:user_id])
|
create_if_not_exists(index(:lists, [:user_id]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue