Compare commits
22 commits
8c956bc671
...
33e7ae7637
Author | SHA1 | Date | |
---|---|---|---|
33e7ae7637 | |||
fa40db6b5a | |||
ccd8cd6c59 | |||
900b9b0124 | |||
43aef8b5b1 | |||
f1611b6292 | |||
c63ae73bc0 | |||
16d2bfef80 | |||
c8904f15a2 | |||
8fe29bf5d2 | |||
452f9e14fb | |||
5fa1cfc513 | |||
2aac70d690 | |||
3fa65a5c53 | |||
210df6fe92 | |||
593ddbd796 | |||
1ae89bddcd | |||
5fe41df8aa | |||
40627a94d4 | |||
0e5f55deea | |||
f0f0c76805 | |||
b3fc098b83 |
|
@ -6,10 +6,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
- Added a new configuration option to the MediaProxy feature that allows the blocking of specific domains from using the media proxy or being explicitly allowed by the Content-Security-Policy.
|
- Added a new configuration option to the MediaProxy feature that allows the blocking of specific domains from using the media proxy or being explicitly allowed by the Content-Security-Policy.
|
||||||
- Please make sure instances you wanted to block media from are not in the MediaProxy `whitelist`, and instead use `blocklist`.
|
- Please make sure instances you wanted to block media from are not in the MediaProxy `whitelist`, and instead use `blocklist`.
|
||||||
- `OnlyMedia` Upload Filter to simplify restricting uploads to audio, image, and video types
|
- `OnlyMedia` Upload Filter to simplify restricting uploads to audio, image, and video types
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- Deactivated users can no longer show up in the emoji reaction list
|
||||||
|
- Embedded posts can no longer bypass `:restrict\_unauthenticated`
|
||||||
|
|
||||||
## 2023.05
|
## 2023.05
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|
|
@ -42,7 +42,7 @@ For a frontend configured under the `available` key, it's enough to install it b
|
||||||
|
|
||||||
This will download the latest build for the pre-configured `ref` and install it. It can then be configured as the one of the served frontends in the config file (see `primary` or `admin`).
|
This will download the latest build for the pre-configured `ref` and install it. It can then be configured as the one of the served frontends in the config file (see `primary` or `admin`).
|
||||||
|
|
||||||
You can override any of the details. To install a Pleroma-FE build from a different URL, you could do this:
|
You can override any of the details. To install an Akkoma-FE build from a different URL, you could do this:
|
||||||
|
|
||||||
=== "OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,6 @@ mix ecto.migrate
|
||||||
# Start akkoma (replace with your system service manager's equivalent if different)
|
# Start akkoma (replace with your system service manager's equivalent if different)
|
||||||
sudo systemctl start akkoma
|
sudo systemctl start akkoma
|
||||||
|
|
||||||
# Update Pleroma-FE frontend to latest stable. For other Frontends see Frontend Configuration doc for more information.
|
# Update Akkoma-FE frontend to latest stable. For other Frontends see Frontend Configuration doc for more information.
|
||||||
mix pleroma.frontend install pleroma-fe --ref stable
|
mix pleroma.frontend install pleroma-fe --ref stable
|
||||||
```
|
```
|
||||||
|
|
|
@ -2,6 +2,14 @@
|
||||||
Note: Additional clients may work, but these are known to work with Akkoma.
|
Note: Additional clients may work, but these are known to work with Akkoma.
|
||||||
Apps listed here might not support all of Akkoma's features.
|
Apps listed here might not support all of Akkoma's features.
|
||||||
|
|
||||||
|
## Multiplatform
|
||||||
|
### Kaiteki
|
||||||
|
- Homepage: <https://kaiteki.app/>
|
||||||
|
- Source Code: <https://github.com/Kaiteki-Fedi/Kaiteki>
|
||||||
|
- Contact: [@kaiteki@fedi.software](https://fedi.software/@Kaiteki)
|
||||||
|
- Platforms: Web, Windows, Linux, Android
|
||||||
|
- Features: MastoAPI, Supports multiple backends
|
||||||
|
|
||||||
## Desktop
|
## Desktop
|
||||||
### Whalebird
|
### Whalebird
|
||||||
- Homepage: <https://whalebird.social/>
|
- Homepage: <https://whalebird.social/>
|
||||||
|
|
|
@ -246,11 +246,11 @@ Notes:
|
||||||
|
|
||||||
### :frontend_configurations
|
### :frontend_configurations
|
||||||
|
|
||||||
This can be used to configure a keyword list that keeps the configuration data for any kind of frontend. By default, settings for `pleroma_fe` and `masto_fe` are configured. You can find the documentation for `pleroma_fe` configuration into [Pleroma-FE configuration and customization for instance administrators](https://docs-fe.akkoma.dev/stable/CONFIGURATION/#options).
|
This can be used to configure a keyword list that keeps the configuration data for any kind of frontend. By default, settings for `pleroma_fe` and `masto_fe` are configured. You can find the documentation for `pleroma_fe` configuration into [Akkoma-FE configuration and customization for instance administrators](https://docs-fe.akkoma.dev/stable/CONFIGURATION/#options).
|
||||||
|
|
||||||
Frontends can access these settings at `/api/v1/pleroma/frontend_configurations`
|
Frontends can access these settings at `/api/v1/pleroma/frontend_configurations`
|
||||||
|
|
||||||
To add your own configuration for Pleroma-FE, use it like this:
|
To add your own configuration for Akkoma-FE, use it like this:
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
config :pleroma, :frontend_configurations,
|
config :pleroma, :frontend_configurations,
|
||||||
|
|
|
@ -6,7 +6,7 @@ To add a custom theme to your instance, you'll first need to get a custom theme,
|
||||||
|
|
||||||
### Create your own theme
|
### Create your own theme
|
||||||
|
|
||||||
* You can create your own theme using the Pleroma FE by going to settings (gear on the top right) and choose the Theme tab. Here you have the options to create a personal theme.
|
* You can create your own theme using the Akkoma FE by going to settings (gear on the top right) and choose the Theme tab. Here you have the options to create a personal theme.
|
||||||
* To download your theme, you can do Save preset
|
* To download your theme, you can do Save preset
|
||||||
* If you want to upload a theme to customise it further, you can upload it using Load preset
|
* If you want to upload a theme to customise it further, you can upload it using Load preset
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# Introduction to Akkoma
|
# Introduction to Akkoma
|
||||||
## What is Akkoma?
|
## What is Akkoma?
|
||||||
Akkoma is a federated social networking platform, compatible with Mastodon and other ActivityPub implementations. It is free software licensed under the AGPLv3.
|
Akkoma is a federated social networking platform, compatible with Mastodon and other ActivityPub implementations. It is free software licensed under the AGPLv3.
|
||||||
It actually consists of two components: a backend, named simply Akkoma, and a user-facing frontend, named Pleroma-FE. It also includes the Mastodon frontend, if that's your thing.
|
It actually consists of two components: a backend, named simply Akkoma, and a user-facing frontend, named Akkoma-FE. It also includes the Mastodon frontend, if that's your thing.
|
||||||
It's part of what we call the fediverse, a federated network of instances which speak common protocols and can communicate with each other.
|
It's part of what we call the fediverse, a federated network of instances which speak common protocols and can communicate with each other.
|
||||||
One account on an instance is enough to talk to the entire fediverse!
|
One account on an instance is enough to talk to the entire fediverse!
|
||||||
|
|
||||||
|
@ -31,11 +31,11 @@ Installation instructions can be found in the installation section of these docs
|
||||||
## I got an account, now what?
|
## I got an account, now what?
|
||||||
Great! Now you can explore the fediverse! Open the login page for your Akkoma instance (e.g. <https://otp.akkoma.dev>) and login with your username and password. (If you don't have an account yet, click on Register)
|
Great! Now you can explore the fediverse! Open the login page for your Akkoma instance (e.g. <https://otp.akkoma.dev>) and login with your username and password. (If you don't have an account yet, click on Register)
|
||||||
|
|
||||||
### Pleroma-FE
|
### Akkoma-FE
|
||||||
The default front-end used by Akkoma is Pleroma-FE. You can find more information on what it is and how to use it in the [Introduction to Pleroma-FE](https://docs-fe.akkoma.dev/stable/).
|
The default front-end used by Akkoma is Akkoma-FE. You can find more information on what it is and how to use it in the [Introduction to Akkoma-FE](https://docs-fe.akkoma.dev/stable/).
|
||||||
|
|
||||||
### Mastodon interface
|
### Mastodon interface
|
||||||
If the Pleroma-FE interface isn't your thing, or you're just trying something new but you want to keep using the familiar Mastodon interface, we got that too!
|
If the Akkoma-FE interface isn't your thing, or you're just trying something new but you want to keep using the familiar Mastodon interface, we got that too!
|
||||||
Just add a "/web" after your instance url (e.g. <https://otp.akkoma.dev/web>) and you'll end on the Mastodon web interface, but with a Akkoma backend! MAGIC!
|
Just add a "/web" after your instance url (e.g. <https://otp.akkoma.dev/web>) and you'll end on the Mastodon web interface, but with a Akkoma backend! MAGIC!
|
||||||
The Mastodon interface is from the Glitch-soc fork. For more information on the Mastodon interface you can check the [Mastodon](https://docs.joinmastodon.org/) and [Glitch-soc](https://glitch-soc.github.io/docs/) documentation.
|
The Mastodon interface is from the Glitch-soc fork. For more information on the Mastodon interface you can check the [Mastodon](https://docs.joinmastodon.org/) and [Glitch-soc](https://glitch-soc.github.io/docs/) documentation.
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
# Optional software packages needed for specific functionality
|
# Optional software packages needed for specific functionality
|
||||||
|
|
||||||
For specific Pleroma functionality (which is disabled by default) some or all of the below packages are required:
|
For specific Akkoma functionality (which is disabled by default) some or all of the below packages are required:
|
||||||
* `ImageMagic`
|
* `ImageMagick`
|
||||||
* `ffmpeg`
|
* `ffmpeg`
|
||||||
* `exiftool`
|
* `exiftool`
|
||||||
|
|
||||||
Please refer to documentation in `docs/installation` on how to install them on specific OS.
|
Please refer to documentation in `docs/installation` on how to install them on specific OS.
|
||||||
|
|
||||||
Note: the packages are not required with the current default settings of Pleroma.
|
Note: the packages are not required with the current default settings of Akkoma.
|
||||||
|
|
||||||
## `ImageMagick`
|
## `ImageMagick`
|
||||||
|
|
||||||
`ImageMagick` is a set of tools to create, edit, compose, or convert bitmap images.
|
`ImageMagick` is a set of tools to create, edit, compose, or convert bitmap images.
|
||||||
|
|
||||||
It is required for the following Pleroma features:
|
It is required for the following Akkoma features:
|
||||||
* `Pleroma.Upload.Filters.Mogrify`, `Pleroma.Upload.Filters.Mogrifun` upload filters (related config: `Plaroma.Upload/filters` in `config/config.exs`)
|
* `Pleroma.Upload.Filters.Mogrify`, `Pleroma.Upload.Filters.Mogrifun` upload filters (related config: `Plaroma.Upload/filters` in `config/config.exs`)
|
||||||
* Media preview proxy for still images (related config: `media_preview_proxy/enabled` in `config/config.exs`)
|
* Media preview proxy for still images (related config: `media_preview_proxy/enabled` in `config/config.exs`)
|
||||||
|
|
||||||
|
@ -21,12 +21,12 @@ It is required for the following Pleroma features:
|
||||||
|
|
||||||
`ffmpeg` is software to record, convert and stream audio and video.
|
`ffmpeg` is software to record, convert and stream audio and video.
|
||||||
|
|
||||||
It is required for the following Pleroma features:
|
It is required for the following Akkoma features:
|
||||||
* Media preview proxy for videos (related config: `media_preview_proxy/enabled` in `config/config.exs`)
|
* Media preview proxy for videos (related config: `media_preview_proxy/enabled` in `config/config.exs`)
|
||||||
|
|
||||||
## `exiftool`
|
## `exiftool`
|
||||||
|
|
||||||
`exiftool` is media files metadata reader/writer.
|
`exiftool` is media files metadata reader/writer.
|
||||||
|
|
||||||
It is required for the following Pleroma features:
|
It is required for the following Akkoma features:
|
||||||
* `Pleroma.Upload.Filters.Exiftool` upload filter (related config: `Plaroma.Upload/filters` in `config/config.exs`)
|
* `Pleroma.Upload.Filters.Exiftool` upload filter (related config: `Plaroma.Upload/filters` in `config/config.exs`)
|
||||||
|
|
8
docs/theme/partials/source.html
vendored
8
docs/theme/partials/source.html
vendored
|
@ -38,11 +38,11 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if page and page.url.startswith('backend') %}
|
{% if page and page.url.startswith('backend') %}
|
||||||
{% set repo_url = "https://git.pleroma.social/pleroma/pleroma" %}
|
{% set repo_url = "https://akkoma.dev/AkkomaGang/akkoma" %}
|
||||||
{% set repo_name = "pleroma/pleroma" %}
|
{% set repo_name = "AkkomaGang/akkoma" %}
|
||||||
{% elif page and page.url.startswith('frontend') %}
|
{% elif page and page.url.startswith('frontend') %}
|
||||||
{% set repo_url = "https://git.pleroma.social/pleroma/pleroma-fe" %}
|
{% set repo_url = "https://akkoma.dev/AkkomaGang/akkoma-fe" %}
|
||||||
{% set repo_name = "pleroma/pleroma-fe" %}
|
{% set repo_name = "AkkomaGang/akkoma-fe" %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% set repo_url = config.repo_url %}
|
{% set repo_url = config.repo_url %}
|
||||||
{% set repo_name = config.repo_name %}
|
{% set repo_name = config.repo_name %}
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
# 1. Replace 'example.tld' with your instance's domain wherever it appears.
|
# 1. Replace 'example.tld' with your instance's domain wherever it appears.
|
||||||
# 2. Copy this section into your Caddyfile and restart Caddy.
|
# 2. Copy this section into your Caddyfile and restart Caddy.
|
||||||
|
|
||||||
|
# If you are able to, it's highly recommended to have your media served via a separate subdomain for improved security.
|
||||||
|
# Uncomment the relevant sectons here and modify the base_url setting for Pleroma.Upload and :media_proxy accordingly.
|
||||||
|
|
||||||
example.tld {
|
example.tld {
|
||||||
log {
|
log {
|
||||||
output file /var/log/caddy/akkoma.log
|
output file /var/log/caddy/akkoma.log
|
||||||
|
@ -14,4 +17,21 @@ example.tld {
|
||||||
# this is explicitly IPv4 since Pleroma.Web.Endpoint binds on IPv4 only
|
# this is explicitly IPv4 since Pleroma.Web.Endpoint binds on IPv4 only
|
||||||
# and `localhost.` resolves to [::0] on some systems: see issue #930
|
# and `localhost.` resolves to [::0] on some systems: see issue #930
|
||||||
reverse_proxy 127.0.0.1:4000
|
reverse_proxy 127.0.0.1:4000
|
||||||
|
|
||||||
|
# Uncomment if using a separate media subdomain
|
||||||
|
#@mediaproxy path /media/* /proxy/*
|
||||||
|
#handle @mediaproxy {
|
||||||
|
# redir https://media.example.tld{uri} permanent
|
||||||
|
#}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Uncomment if using a separate media subdomain
|
||||||
|
#media.example.tld {
|
||||||
|
# @mediaproxy path /media/* /proxy/*
|
||||||
|
# reverse_proxy @mediaproxy 127.0.0.1:4000 {
|
||||||
|
# transport http {
|
||||||
|
# response_header_timeout 10s
|
||||||
|
# read_timeout 15s
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
#}
|
||||||
|
|
|
@ -25,7 +25,7 @@ defmodule Pleroma.Constants do
|
||||||
|
|
||||||
const(static_only_files,
|
const(static_only_files,
|
||||||
do:
|
do:
|
||||||
~w(index.html robots.txt static static-fe finmoji emoji packs sounds images instance sw.js sw-pleroma.js favicon.png schemas doc embed.js embed.css)
|
~w(index.html robots.txt static static-fe finmoji emoji packs sounds images instance embed sw.js sw-pleroma.js favicon.png schemas doc)
|
||||||
)
|
)
|
||||||
|
|
||||||
const(status_updatable_fields,
|
const(status_updatable_fields,
|
||||||
|
|
|
@ -919,9 +919,13 @@ def add_attributed_to(object) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def prepare_attachments(object) do
|
def prepare_attachments(object) do
|
||||||
|
attachments = case Map.get(object, "attachment", []) do
|
||||||
|
[_ | _] = list -> list
|
||||||
|
_ -> []
|
||||||
|
end
|
||||||
|
|
||||||
attachments =
|
attachments =
|
||||||
object
|
attachments
|
||||||
|> Map.get("attachment", [])
|
|
||||||
|> Enum.map(fn data ->
|
|> Enum.map(fn data ->
|
||||||
[%{"mediaType" => media_type, "href" => href} = url | _] = data["url"]
|
[%{"mediaType" => media_type, "href" => href} = url | _] = data["url"]
|
||||||
|
|
||||||
|
|
|
@ -11,22 +11,31 @@ defmodule Pleroma.Web.EmbedController do
|
||||||
|
|
||||||
alias Pleroma.Web.ActivityPub.Visibility
|
alias Pleroma.Web.ActivityPub.Visibility
|
||||||
|
|
||||||
plug(:put_layout, :embed)
|
|
||||||
|
|
||||||
def show(conn, %{"id" => id}) do
|
def show(conn, %{"id" => id}) do
|
||||||
with %Activity{local: true} = activity <-
|
with {:activity, %Activity{} = activity} <-
|
||||||
Activity.get_by_id_with_object(id),
|
{:activity, Activity.get_by_id_with_object(id)},
|
||||||
true <- Visibility.is_public?(activity.object) do
|
{:local, true} <- {:local, activity.local},
|
||||||
|
{:visible, true} <- {:visible, Visibility.visible_for_user?(activity, nil)} do
|
||||||
{:ok, author} = User.get_or_fetch(activity.object.data["actor"])
|
{:ok, author} = User.get_or_fetch(activity.object.data["actor"])
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> delete_resp_header("x-frame-options")
|
|> delete_resp_header("x-frame-options")
|
||||||
|> delete_resp_header("content-security-policy")
|
|> delete_resp_header("content-security-policy")
|
||||||
|
|> put_view(Pleroma.Web.EmbedView)
|
||||||
|> render("show.html",
|
|> render("show.html",
|
||||||
activity: activity,
|
activity: activity,
|
||||||
author: User.sanitize_html(author),
|
author: User.sanitize_html(author),
|
||||||
counts: get_counts(activity)
|
counts: get_counts(activity)
|
||||||
)
|
)
|
||||||
|
else
|
||||||
|
{:activity, _} ->
|
||||||
|
render_error(conn, :not_found, "Post not found")
|
||||||
|
|
||||||
|
{:local, false} ->
|
||||||
|
render_error(conn, :unauthorized, "Federated posts cannot be embedded")
|
||||||
|
|
||||||
|
{:visible, false} ->
|
||||||
|
render_error(conn, :unauthorized, "Not authorized to view this post")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -84,8 +84,13 @@ def whitelisted?(url) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def blocked?(url) do
|
def blocked?(url) do
|
||||||
%{host: domain} = URI.parse(url)
|
%{scheme: scheme, host: domain} = URI.parse(url)
|
||||||
domain in Config.get([:media_proxy, :whitelist])
|
# Block either the bare domain or the scheme-domain combo
|
||||||
|
scheme_domain = "#{scheme}://#{domain}"
|
||||||
|
blocklist = Config.get([:media_proxy, :blocklist])
|
||||||
|
|
||||||
|
Enum.member?(blocklist, domain) ||
|
||||||
|
Enum.member?(blocklist, scheme_domain)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp maybe_get_domain_from_url("http" <> _ = url) do
|
defp maybe_get_domain_from_url("http" <> _ = url) do
|
||||||
|
|
|
@ -41,6 +41,17 @@ def index(%{assigns: %{user: user}} = conn, %{id: activity_id} = params) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp filter_allowed_user_by_ap_id(ap_ids, excluded_ap_ids) do
|
||||||
|
Enum.reject(ap_ids, fn ap_id ->
|
||||||
|
with false <- ap_id in excluded_ap_ids,
|
||||||
|
%{is_active: true} <- User.get_cached_by_ap_id(ap_id) do
|
||||||
|
false
|
||||||
|
else
|
||||||
|
_ -> true
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
def filter_allowed_users(reactions, user, with_muted) do
|
def filter_allowed_users(reactions, user, with_muted) do
|
||||||
exclude_ap_ids =
|
exclude_ap_ids =
|
||||||
if is_nil(user) do
|
if is_nil(user) do
|
||||||
|
@ -51,7 +62,7 @@ def filter_allowed_users(reactions, user, with_muted) do
|
||||||
end
|
end
|
||||||
|
|
||||||
filter_emoji = fn emoji, users, url ->
|
filter_emoji = fn emoji, users, url ->
|
||||||
case Enum.reject(users, &(&1 in exclude_ap_ids)) do
|
case filter_allowed_user_by_ap_id(users, exclude_ap_ids) do
|
||||||
[] -> nil
|
[] -> nil
|
||||||
users -> {emoji, users, url}
|
users -> {emoji, users, url}
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
<title><%= Pleroma.Config.get([:instance, :name]) %></title>
|
<title><%= Pleroma.Config.get([:instance, :name]) %></title>
|
||||||
<meta content='noindex' name='robots'>
|
<meta content='noindex' name='robots'>
|
||||||
<%= Phoenix.HTML.raw(assigns[:meta] || "") %>
|
<%= Phoenix.HTML.raw(assigns[:meta] || "") %>
|
||||||
<link rel="stylesheet" href="/embed.css">
|
<link rel="stylesheet" href="/embed/embed.css">
|
||||||
<base target="_parent">
|
<base target="_parent">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<%= render @view_module, @view_template, assigns %>
|
<%= render view_module(@conn), view_template(@conn), assigns %>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -15,7 +15,7 @@ defmodule Pleroma.Web.EmbedView do
|
||||||
alias Pleroma.Web.Metadata.Utils
|
alias Pleroma.Web.Metadata.Utils
|
||||||
alias Pleroma.Web.Router.Helpers
|
alias Pleroma.Web.Router.Helpers
|
||||||
|
|
||||||
use Phoenix.HTML
|
import Phoenix.HTML
|
||||||
|
|
||||||
defdelegate full_nickname(user), to: User
|
defdelegate full_nickname(user), to: User
|
||||||
|
|
||||||
|
@ -55,10 +55,13 @@ defp activity_url(%User{local: false}, %Activity{object: %Object{data: data}}) d
|
||||||
data["url"] || data["external_url"] || data["id"]
|
data["url"] || data["external_url"] || data["id"]
|
||||||
end
|
end
|
||||||
|
|
||||||
defp attachments(%Activity{object: %Object{data: %{"attachment" => attachments}}}) do
|
defp attachments(%Activity{object: %Object{data: %{"attachment" => attachments}}})
|
||||||
|
when is_list(attachments) do
|
||||||
attachments
|
attachments
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp attachments(_), do: []
|
||||||
|
|
||||||
defp sensitive?(%Activity{object: %Object{data: %{"sensitive" => sensitive}}}) do
|
defp sensitive?(%Activity{object: %Object{data: %{"sensitive" => sensitive}}}) do
|
||||||
sensitive
|
sensitive
|
||||||
end
|
end
|
||||||
|
|
115
priv/static/embed/embed.css
Normal file
115
priv/static/embed/embed.css
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
body {
|
||||||
|
background-color: #282c37;
|
||||||
|
font-family: sans-serif;
|
||||||
|
color: white;
|
||||||
|
margin: 0;
|
||||||
|
padding: 1em;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar img {
|
||||||
|
float: left;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-content {
|
||||||
|
padding-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachment {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachment img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date a,
|
||||||
|
.counts {
|
||||||
|
color: #666;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.counts dt,
|
||||||
|
.counts dd {
|
||||||
|
float: left;
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-card {
|
||||||
|
min-height: 48px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-card a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-card a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display-name {
|
||||||
|
padding-top: 4px;
|
||||||
|
display: block;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* keep emoji from being hilariously huge */
|
||||||
|
.display-name img {
|
||||||
|
max-height: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display-name .nickname {
|
||||||
|
padding-top: 4px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nickname:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pull-right {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapse {
|
||||||
|
margin: 0;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.button {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: inline-block;
|
||||||
|
color: white;
|
||||||
|
background-color: #419bdd;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
padding: 10px;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.button:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: #61a6d9;
|
||||||
|
}
|
43
priv/static/embed/embed.js
Normal file
43
priv/static/embed/embed.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
(function () {
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
var ready = function (loaded) {
|
||||||
|
if (['interactive', 'complete'].indexOf(document.readyState) !== -1) {
|
||||||
|
loaded()
|
||||||
|
} else {
|
||||||
|
document.addEventListener('DOMContentLoaded', loaded)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ready(function () {
|
||||||
|
var iframes = []
|
||||||
|
|
||||||
|
window.addEventListener('message', function (e) {
|
||||||
|
var data = e.data || {}
|
||||||
|
|
||||||
|
if (data.type !== 'setHeightPleromaEmbed' || !iframes[data.id]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
iframes[data.id].height = data.height
|
||||||
|
});
|
||||||
|
|
||||||
|
[].forEach.call(document.querySelectorAll('iframe.pleroma-embed'), function (iframe) {
|
||||||
|
iframe.scrolling = 'no'
|
||||||
|
iframe.style.overflow = 'hidden'
|
||||||
|
|
||||||
|
iframes.push(iframe)
|
||||||
|
|
||||||
|
var id = iframes.length - 1
|
||||||
|
|
||||||
|
iframe.onload = function () {
|
||||||
|
iframe.contentWindow.postMessage({
|
||||||
|
type: 'setHeightPleromaEmbed',
|
||||||
|
id: id
|
||||||
|
}, '*')
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe.onload()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})()
|
44
test/pleroma/web/embed_controller_test.exs
Normal file
44
test/pleroma/web/embed_controller_test.exs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.EmbedControllerTest do
|
||||||
|
use Pleroma.Web.ConnCase, async: true
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
test "/embed", %{conn: conn} do
|
||||||
|
activity = insert(:note_activity)
|
||||||
|
|
||||||
|
resp =
|
||||||
|
conn
|
||||||
|
|> get("/embed/#{activity.id}")
|
||||||
|
|> response(200)
|
||||||
|
|
||||||
|
object = Pleroma.Object.get_by_ap_id(activity.data["object"])
|
||||||
|
|
||||||
|
assert String.contains?(resp, object.data["content"])
|
||||||
|
end
|
||||||
|
|
||||||
|
test "/embed with a restricted post", %{conn: conn} do
|
||||||
|
activity = insert(:note_activity)
|
||||||
|
clear_config([:restrict_unauthenticated, :activities, :local], true)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> get("/embed/#{activity.id}")
|
||||||
|
|> response(401)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "/embed with a private post", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, activity} =
|
||||||
|
Pleroma.Web.CommonAPI.post(user, %{
|
||||||
|
status: "Mega ultra chicken status: #fried",
|
||||||
|
visibility: "private"
|
||||||
|
})
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> get("/embed/#{activity.id}")
|
||||||
|
|> response(401)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1960,6 +1960,10 @@ test "index" do
|
||||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
|
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
|
||||||
User.mute(user, other_user)
|
User.mute(user, other_user)
|
||||||
|
|
||||||
|
deactivated_user = insert(:user)
|
||||||
|
{:ok, _} = CommonAPI.react_with_emoji(activity.id, deactivated_user, "🎅")
|
||||||
|
User.set_activation(deactivated_user, false)
|
||||||
|
|
||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/statuses/?ids[]=#{activity.id}")
|
|> get("/api/v1/statuses/?ids[]=#{activity.id}")
|
||||||
|
@ -1967,6 +1971,7 @@ test "index" do
|
||||||
|
|
||||||
assert [
|
assert [
|
||||||
%{
|
%{
|
||||||
|
"emoji_reactions" => [],
|
||||||
"pleroma" => %{
|
"pleroma" => %{
|
||||||
"emoji_reactions" => []
|
"emoji_reactions" => []
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue