Merge remote-tracking branch 'origin/develop' into shigusegubu
This commit is contained in:
commit
8d82808d7a
632 changed files with 7519 additions and 1314 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
image: git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.14.5-otp-25
|
image: git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.15.8-otp-26
|
||||||
|
|
||||||
variables: &global_variables
|
variables: &global_variables
|
||||||
# Only used for the release
|
# Only used for the release
|
||||||
|
|
@ -16,9 +16,15 @@ workflow:
|
||||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||||
- if: $CI_COMMIT_BRANCH == "develop"
|
- if: $CI_COMMIT_BRANCH == "develop"
|
||||||
- if: $CI_COMMIT_BRANCH == "stable"
|
- if: $CI_COMMIT_BRANCH == "stable"
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "web"
|
||||||
|
- if: $CI_COMMIT_TAG
|
||||||
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
|
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
|
||||||
when: never
|
when: never
|
||||||
|
|
||||||
|
# Default artifacts configuration
|
||||||
|
.default_artifacts: &default_artifacts
|
||||||
|
expire_in: 30 days
|
||||||
|
|
||||||
cache: &global_cache_policy
|
cache: &global_cache_policy
|
||||||
key: $CI_JOB_IMAGE-$CI_COMMIT_SHORT_SHA
|
key: $CI_JOB_IMAGE-$CI_COMMIT_SHORT_SHA
|
||||||
paths:
|
paths:
|
||||||
|
|
@ -56,6 +62,7 @@ check-changelog:
|
||||||
before_script: ''
|
before_script: ''
|
||||||
after_script: ''
|
after_script: ''
|
||||||
cache: {}
|
cache: {}
|
||||||
|
artifacts: *default_artifacts
|
||||||
script:
|
script:
|
||||||
- apk add git
|
- apk add git
|
||||||
- sh ./tools/check-changelog
|
- sh ./tools/check-changelog
|
||||||
|
|
@ -71,8 +78,9 @@ check-changelog:
|
||||||
.using-ci-base:
|
.using-ci-base:
|
||||||
tags:
|
tags:
|
||||||
- amd64
|
- amd64
|
||||||
|
artifacts: *default_artifacts
|
||||||
|
|
||||||
build-1.14.5-otp-25:
|
build-1.15.8-otp-26:
|
||||||
extends:
|
extends:
|
||||||
- .build_changes_policy
|
- .build_changes_policy
|
||||||
- .using-ci-base
|
- .using-ci-base
|
||||||
|
|
@ -101,8 +109,12 @@ spec-build:
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- spec.json
|
- spec.json
|
||||||
|
reports:
|
||||||
|
dotenv: build.env
|
||||||
|
expire_in: 42 years
|
||||||
script:
|
script:
|
||||||
- mix pleroma.openapi_spec spec.json
|
- mix pleroma.openapi_spec spec.json
|
||||||
|
- echo "SPEC_BUILD_JOB_ID=$CI_JOB_ID" >> build.env
|
||||||
|
|
||||||
benchmark:
|
benchmark:
|
||||||
extends:
|
extends:
|
||||||
|
|
@ -120,7 +132,7 @@ benchmark:
|
||||||
- mix ecto.migrate
|
- mix ecto.migrate
|
||||||
- mix pleroma.load_testing
|
- mix pleroma.load_testing
|
||||||
|
|
||||||
unit-testing-1.14.5-otp-25:
|
unit-testing-1.15.8-otp-26:
|
||||||
extends:
|
extends:
|
||||||
- .build_changes_policy
|
- .build_changes_policy
|
||||||
- .using-ci-base
|
- .using-ci-base
|
||||||
|
|
@ -153,6 +165,7 @@ unit-testing-1.14.5-otp-25:
|
||||||
- su testuser -c "HOME=/home/testuser mix pleroma.test_runner --cover --preload-modules"
|
- su testuser -c "HOME=/home/testuser mix pleroma.test_runner --cover --preload-modules"
|
||||||
coverage: '/^Line total: ([^ ]*%)$/'
|
coverage: '/^Line total: ([^ ]*%)$/'
|
||||||
artifacts:
|
artifacts:
|
||||||
|
expire_in: 30 days
|
||||||
reports:
|
reports:
|
||||||
coverage_report:
|
coverage_report:
|
||||||
coverage_format: cobertura
|
coverage_format: cobertura
|
||||||
|
|
@ -171,6 +184,7 @@ unit-testing-1.18.3-otp-27:
|
||||||
|
|
||||||
formatting-1.15:
|
formatting-1.15:
|
||||||
extends: .build_changes_policy
|
extends: .build_changes_policy
|
||||||
|
artifacts: *default_artifacts
|
||||||
image: &formatting_elixir elixir:1.15-alpine
|
image: &formatting_elixir elixir:1.15-alpine
|
||||||
stage: lint
|
stage: lint
|
||||||
cache: *testing_cache_policy
|
cache: *testing_cache_policy
|
||||||
|
|
@ -185,6 +199,7 @@ formatting-1.15:
|
||||||
|
|
||||||
cycles-1.15:
|
cycles-1.15:
|
||||||
extends: .build_changes_policy
|
extends: .build_changes_policy
|
||||||
|
artifacts: *default_artifacts
|
||||||
image: *formatting_elixir
|
image: *formatting_elixir
|
||||||
stage: lint
|
stage: lint
|
||||||
cache: {}
|
cache: {}
|
||||||
|
|
@ -208,7 +223,7 @@ dialyzer:
|
||||||
- .using-ci-base
|
- .using-ci-base
|
||||||
stage: lint
|
stage: lint
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
when: manual
|
when: manual
|
||||||
cache: *testing_cache_policy
|
cache: *testing_cache_policy
|
||||||
tags:
|
tags:
|
||||||
- feld
|
- feld
|
||||||
|
|
@ -217,15 +232,14 @@ dialyzer:
|
||||||
|
|
||||||
docs-deploy:
|
docs-deploy:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
cache: *testing_cache_policy
|
trigger:
|
||||||
image: alpine:latest
|
project: pleroma/docs
|
||||||
|
branch: master
|
||||||
|
strategy: depend
|
||||||
only:
|
only:
|
||||||
- stable@pleroma/pleroma
|
- stable@pleroma/pleroma
|
||||||
- develop@pleroma/pleroma
|
- develop@pleroma/pleroma
|
||||||
before_script:
|
|
||||||
- apk add curl
|
|
||||||
script:
|
|
||||||
- curl --fail-with-body -X POST -F"token=$DOCS_PIPELINE_TRIGGER" -F'ref=master' -F"variables[BRANCH]=$CI_COMMIT_REF_NAME" https://git.pleroma.social/api/v4/projects/673/trigger/pipeline
|
|
||||||
review_app:
|
review_app:
|
||||||
image: alpine:3.9
|
image: alpine:3.9
|
||||||
stage: deploy
|
stage: deploy
|
||||||
|
|
@ -241,6 +255,7 @@ review_app:
|
||||||
except:
|
except:
|
||||||
- master
|
- master
|
||||||
- develop
|
- develop
|
||||||
|
artifacts: *default_artifacts
|
||||||
script:
|
script:
|
||||||
- echo "$CI_ENVIRONMENT_SLUG"
|
- echo "$CI_ENVIRONMENT_SLUG"
|
||||||
- mkdir -p ~/.ssh
|
- mkdir -p ~/.ssh
|
||||||
|
|
@ -257,21 +272,19 @@ review_app:
|
||||||
|
|
||||||
spec-deploy:
|
spec-deploy:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
artifacts:
|
trigger:
|
||||||
paths:
|
project: pleroma/api-docs
|
||||||
- spec.json
|
branch: master
|
||||||
|
strategy: depend
|
||||||
only:
|
only:
|
||||||
- develop@pleroma/pleroma
|
- develop@pleroma/pleroma
|
||||||
image: alpine:latest
|
variables:
|
||||||
before_script:
|
SPEC_BUILD_JOB_ID: $SPEC_BUILD_JOB_ID
|
||||||
- apk add curl
|
|
||||||
script:
|
|
||||||
- curl --fail-with-body -X POST -F"token=$API_DOCS_PIPELINE_TRIGGER" -F'ref=master' -F"variables[BRANCH]=$CI_COMMIT_REF_NAME" -F"variables[JOB_REF]=$CI_JOB_ID" https://git.pleroma.social/api/v4/projects/1130/trigger/pipeline
|
|
||||||
|
|
||||||
|
|
||||||
stop_review_app:
|
stop_review_app:
|
||||||
image: alpine:3.9
|
image: alpine:3.9
|
||||||
stage: deploy
|
stage: deploy
|
||||||
|
artifacts: *default_artifacts
|
||||||
before_script:
|
before_script:
|
||||||
- apk update && apk add openssh-client git
|
- apk update && apk add openssh-client git
|
||||||
when: manual
|
when: manual
|
||||||
|
|
@ -290,7 +303,7 @@ stop_review_app:
|
||||||
amd64:
|
amd64:
|
||||||
stage: release
|
stage: release
|
||||||
image:
|
image:
|
||||||
name: hexpm/elixir-amd64:1.17.3-erlang-26.2.5.6-ubuntu-focal-20241011
|
name: hexpm/elixir-amd64:1.17.3-erlang-27.3.4.2-ubuntu-noble-20250716
|
||||||
only: &release-only
|
only: &release-only
|
||||||
- stable@pleroma/pleroma
|
- stable@pleroma/pleroma
|
||||||
- develop@pleroma/pleroma
|
- develop@pleroma/pleroma
|
||||||
|
|
@ -317,7 +330,7 @@ amd64:
|
||||||
VIX_COMPILATION_MODE: PLATFORM_PROVIDED_LIBVIPS
|
VIX_COMPILATION_MODE: PLATFORM_PROVIDED_LIBVIPS
|
||||||
DEBIAN_FRONTEND: noninteractive
|
DEBIAN_FRONTEND: noninteractive
|
||||||
before_script: &before-release
|
before_script: &before-release
|
||||||
- apt-get update && apt-get install -y cmake libmagic-dev libvips-dev erlang-dev git
|
- apt-get update && apt-get install -y cmake libmagic-dev libvips-dev erlang-dev git build-essential
|
||||||
- echo "import Config" > config/prod.secret.exs
|
- echo "import Config" > config/prod.secret.exs
|
||||||
- mix local.hex --force
|
- mix local.hex --force
|
||||||
- mix local.rebar --force
|
- mix local.rebar --force
|
||||||
|
|
@ -333,7 +346,7 @@ amd64-musl:
|
||||||
artifacts: *release-artifacts
|
artifacts: *release-artifacts
|
||||||
only: *release-only
|
only: *release-only
|
||||||
image:
|
image:
|
||||||
name: hexpm/elixir-amd64:1.17.3-erlang-26.2.5.6-alpine-3.17.9
|
name: hexpm/elixir-amd64:1.17.3-erlang-27.3.4.2-alpine-3.22.1
|
||||||
tags:
|
tags:
|
||||||
- amd64
|
- amd64
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
|
|
@ -377,7 +390,7 @@ arm64:
|
||||||
tags:
|
tags:
|
||||||
- arm
|
- arm
|
||||||
image:
|
image:
|
||||||
name: hexpm/elixir-arm64:1.17.3-erlang-26.2.5.6-ubuntu-focal-20241011
|
name: hexpm/elixir-arm64:1.17.3-erlang-27.3.4.2-ubuntu-noble-20250716
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
variables: *release-variables
|
variables: *release-variables
|
||||||
before_script: *before-release
|
before_script: *before-release
|
||||||
|
|
@ -390,7 +403,7 @@ arm64-musl:
|
||||||
tags:
|
tags:
|
||||||
- arm
|
- arm
|
||||||
image:
|
image:
|
||||||
name: hexpm/elixir-arm64:1.17.3-erlang-26.2.5.6-alpine-3.17.9
|
name: hexpm/elixir-arm64:1.17.3-erlang-27.3.4.2-alpine-3.22.1
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
variables: *release-variables
|
variables: *release-variables
|
||||||
before_script: *before-release-musl
|
before_script: *before-release-musl
|
||||||
|
|
|
||||||
311
CHANGELOG.md
311
CHANGELOG.md
|
|
@ -4,9 +4,113 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
|
## 2.10
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Admin API: Fixed self-revocation vulnerability where admins could accidentally revoke their own admin status via the single-user permission endpoint
|
||||||
|
- Fix bypass of the restrict unauthenticated setting by requesting local Activities
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Add new activity actor/type index. Greatly speeds up retrieval of rare types (like "Listen")
|
||||||
|
- Use separate schemas for muted/blocked accounts lists
|
||||||
|
- Docs: Restore DB schema before data to avoid long restore times
|
||||||
|
- Return 404 with a better error message instead of 400 when receiving an activity for a deactivated user
|
||||||
|
- Deleting an instance queues individual jobs for each user that needs to be deleted from the server.
|
||||||
|
- Update Dockerfile to use Elixir 1.17.3, Erlang 26.2.5.6, and Alpine 3.17.9 to match CI release builds
|
||||||
|
- Docs RUM index: Add OTP install command, update index size expectation and recommend VACUUM FULL
|
||||||
|
- Support new Mastodon API for endorsed accounts
|
||||||
|
- Allow FediIndex crawler bot by default
|
||||||
|
- Update Cowboy, Gun, and Plug family of dependencies
|
||||||
|
- Hashtag searches return real results based on words in your query
|
||||||
|
- Support `quoted_status_id` parameter in post creation request
|
||||||
|
- Use Mastodon-compatible route for quotes list and param for quotes count
|
||||||
|
- Updated the example Nginx configuration
|
||||||
|
- Oban Notifier was changed to Oban.Notifiers.PG for performance and scalability benefits
|
||||||
|
- Updated relayd/httpd config files to be on par with nginx
|
||||||
|
- Order favourites and reblogs list from newest to oldest
|
||||||
|
- Update Pleroma-FE to 2.9.2
|
||||||
|
- Updated Postgrex library to 0.20.0
|
||||||
|
- Improved the logic of how we determine if a server is unreachable.
|
||||||
|
- Relax alsoKnownAs requirements to just URI, not necessarily HTTP(S)
|
||||||
|
- Redirect /users/:nickname.rss to /users/:nickname/feed.rss instead of .atom
|
||||||
|
- Add `write:scrobbles` and `read:scrobbles` scope for scrobbling
|
||||||
|
- Change scrobble external link param name to use snake case
|
||||||
|
- Allow "invisible" and "ellipsis" classes for span tags to match Mastodon behavior
|
||||||
|
- Change SMTP example to use the Mua adapter that works with OTP>25
|
||||||
|
- Updated Tesla to 1.15.3
|
||||||
|
- Truncate the length of Rich Media title and description fields
|
||||||
|
- Don't require an Accept header for WebFinger queries and default to JSON.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Support Dislike activity, as sent by Mitra and Friendica, by changing it into a thumbs-down EmojiReact
|
||||||
|
- Support Mitra-style emoji likes.
|
||||||
|
- Added a way to upload new packs from a URL or ZIP file via Admin API
|
||||||
|
- Add `duration` to the block endpoint, which makes block expire
|
||||||
|
- Expose markup configuration in InstanceView
|
||||||
|
- Allow filtering users with `accepts_chat_messages` capability
|
||||||
|
- Add `timelines_access` to InstanceView
|
||||||
|
- Implement language detection with fastText
|
||||||
|
- Added MRF.QuietReply which prevents replies to public posts from being published to the timelines
|
||||||
|
- Oban.Plugins.Lazarus to help recover stuck jobs from an unclean shutdown of Pleroma
|
||||||
|
- Add /api/v1/pleroma/outgoing_follow_requests
|
||||||
|
- Allow users to select preferred frontend
|
||||||
|
- Provide full replies collection in ActivityPub objects
|
||||||
|
- Allow anonymizing reports sent to remote servers
|
||||||
|
- Add only_reblogs parameter to account statuses API for filtering to show only reblogs/reposts
|
||||||
|
- Allow setting custom user-agent for fetching rich media content
|
||||||
|
- Scrubber: Allow `quote-inline` class in <p> tags used by Mastodon quotes
|
||||||
|
- Add `base_urls` to the /api/v1/instance pleroma metadata which provides information about the base URLs for media_proxy and uploads when configured
|
||||||
|
- Stream marker updates
|
||||||
|
- Allow Terms of Service panel behaviour to be configurable
|
||||||
|
- Support translation providers (DeepL, LibreTranslate)
|
||||||
|
- Support Mozhi translation provider
|
||||||
|
- Support translateLocally translation provider
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- AP C2S: Reject interactions with statuses not visible to Actor
|
||||||
|
- Fix AssignAppUser migration OOM
|
||||||
|
- Fix fetching public keys with authorized fetch enabled
|
||||||
|
- Fix building "captcha" library with OpenBSD make
|
||||||
|
- Use JSON for DeepL API requests
|
||||||
|
- Elixir 1.18: Fixed warnings and new deprecations
|
||||||
|
- Fix endorsement state display in relationship view
|
||||||
|
- Fix publisher when publishing to a list of users
|
||||||
|
- Fix reports being rejected when the activity had an empty CC or TO field (instead of not having them at all)
|
||||||
|
- Set PATH in the FreeBSD rc script to avoid failures starting the service
|
||||||
|
- Improved performance of status search queries using the default GIN index
|
||||||
|
- Use end-of-string in regex for local `get_by_nickname`
|
||||||
|
- Respect restrict_unauthenticated in /api/v1/accounts/lookup
|
||||||
|
- MastodonAPI: Reject interactions with statuses not visible to user
|
||||||
|
- Fix ModerationLog FunctionClauseError for unknown actions
|
||||||
|
- MRF InlineQuotePolicy: Don't inline quoted post URL in Mastodon quote posts
|
||||||
|
- Fix NodeInfo content-type
|
||||||
|
- Add Actor images normalization from array of urls to string
|
||||||
|
- Add `update` to @notification_types
|
||||||
|
- replaced depracated flags and functions, renamed service to fit other service files
|
||||||
|
- Allow to pin/unpip chats
|
||||||
|
- Fix federation issue where Public visibility information in cc field was lost when sent to remote servers, causing posts to appear with inconsistent visibility across instances
|
||||||
|
- OpenBSD relayd: Fix IPv6 example
|
||||||
|
- Fix release builds
|
||||||
|
- `remote_url` links to unproxied URL
|
||||||
|
- Send push notifications for statuses from subscribed accounts
|
||||||
|
- Backport [Elixir PR 14242](https://github.com/elixir-lang/elixir/pull/14242) fixing racy mkdir and lack of error handling of parent directory creation
|
||||||
|
- Transmogrifier: convert "as:Public" to full w3 URL
|
||||||
|
- Update voters count in remote polls when refreshing
|
||||||
|
- Fix sometimes incorrect URI percent encoding
|
||||||
|
- Fix HTTP client making invalid requests due to no percent encoding processing or validation.
|
||||||
|
- ObjectView: Do not leak unsanitized internal representation of non-Create/non-Undo Activities on fetches
|
||||||
|
- Fix WebFinger for split-domain setups
|
||||||
|
- Enforce an exact domain match for WebFinger resolution
|
||||||
|
- MastodonAPI: Fix misattribution of statuses when fetched via non-Announce Activity ID
|
||||||
|
|
||||||
## 2.9.1
|
## 2.9.1
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Fix authorization checks for C2S Update activities to prevent unauthorized modifications of other users' content.
|
- Fix authorization checks for C2S Update activities to prevent unauthorized modifications of other users' content.
|
||||||
- Fix content-type spoofing vulnerability that could allow users to upload ActivityPub objects as attachments
|
- Fix content-type spoofing vulnerability that could allow users to upload ActivityPub objects as attachments
|
||||||
- Reject cross-domain redirects when fetching ActivityPub objects to prevent bypassing domain-based security controls.
|
- Reject cross-domain redirects when fetching ActivityPub objects to prevent bypassing domain-based security controls.
|
||||||
|
|
@ -16,27 +120,33 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Validate Content-Type headers when fetching remote ActivityPub objects to prevent spoofing attacks.
|
- Validate Content-Type headers when fetching remote ActivityPub objects to prevent spoofing attacks.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Include `pl-fe` in available frontends
|
- Include `pl-fe` in available frontends
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Remove trailing ` from end of line 75 which caused issues copy-pasting
|
- Remove trailing ` from end of line 75 which caused issues copy-pasting
|
||||||
|
|
||||||
## 2.9.0
|
## 2.9.0
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Require HTTP signatures (if enabled) for routes used by both C2S and S2S AP API
|
- Require HTTP signatures (if enabled) for routes used by both C2S and S2S AP API
|
||||||
- Fix several spoofing vectors
|
- Fix several spoofing vectors
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Performance: Use 301 (permanent) redirect instead of 302 (temporary) when redirecting small images in media proxy. This allows browsers to cache the redirect response.
|
|
||||||
|
- Performance: Use 301 (permanent) redirect instead of 302 (temporary) when redirecting small images in media proxy. This allows browsers to cache the redirect response.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Include "published" in actor view
|
- Include "published" in actor view
|
||||||
- Link to exported outbox/followers/following collections in backup actor.json
|
- Link to exported outbox/followers/following collections in backup actor.json
|
||||||
- Hashtag following
|
- Hashtag following
|
||||||
- Allow to specify post language
|
- Allow to specify post language
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Verify a local Update sent through AP C2S so users can only update their own objects
|
- Verify a local Update sent through AP C2S so users can only update their own objects
|
||||||
- Fix Mastodon incoming edits with inlined "likes"
|
- Fix Mastodon incoming edits with inlined "likes"
|
||||||
- Allow incoming "Listen" activities
|
- Allow incoming "Listen" activities
|
||||||
|
|
@ -46,11 +156,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Fix blurhash generation crashes
|
- Fix blurhash generation crashes
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- Retire MRFs DNSRBL, FODirectReply, and QuietReply
|
- Retire MRFs DNSRBL, FODirectReply, and QuietReply
|
||||||
|
|
||||||
## 2.8.0
|
## 2.8.0
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Metadata: Do not include .atom feed links for remote accounts
|
- Metadata: Do not include .atom feed links for remote accounts
|
||||||
- Bumped `fast_html` to v2.3.0, which notably allows to use system-installed lexbor with passing `WITH_SYSTEM_LEXBOR=1` environment variable at build-time
|
- Bumped `fast_html` to v2.3.0, which notably allows to use system-installed lexbor with passing `WITH_SYSTEM_LEXBOR=1` environment variable at build-time
|
||||||
- Dedupe upload filter now uses a three-level sharding directory structure
|
- Dedupe upload filter now uses a three-level sharding directory structure
|
||||||
|
|
@ -71,6 +183,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Worker configuration is no longer available. This only affects custom max_retries values for a couple Oban queues.
|
- Worker configuration is no longer available. This only affects custom max_retries values for a couple Oban queues.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Add metadata provider for ActivityPub alternate links
|
- Add metadata provider for ActivityPub alternate links
|
||||||
- Added support for argon2 passwords and their conversion for migration from Akkoma fork to upstream.
|
- Added support for argon2 passwords and their conversion for migration from Akkoma fork to upstream.
|
||||||
- Respect :restrict_unauthenticated for hashtag rss/atom feeds
|
- Respect :restrict_unauthenticated for hashtag rss/atom feeds
|
||||||
|
|
@ -88,6 +201,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Include session scopes in TokenView
|
- Include session scopes in TokenView
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Verify a local Update sent through AP C2S so users can only update their own objects
|
- Verify a local Update sent through AP C2S so users can only update their own objects
|
||||||
- Fixed malformed follow requests that cause them to appear stuck pending due to the recipient being unable to process them.
|
- Fixed malformed follow requests that cause them to appear stuck pending due to the recipient being unable to process them.
|
||||||
- Fix incoming Block activities being rejected
|
- Fix incoming Block activities being rejected
|
||||||
|
|
@ -105,14 +219,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Make vapid_config return empty array, fixing preloading for instances without push notifications configured
|
- Make vapid_config return empty array, fixing preloading for instances without push notifications configured
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- Remove stub for /api/v1/accounts/:id/identity_proofs (deprecated by Mastodon 3.5.0)
|
- Remove stub for /api/v1/accounts/:id/identity_proofs (deprecated by Mastodon 3.5.0)
|
||||||
|
|
||||||
## 2.7.1
|
## 2.7.1
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Accept `application/activity+json` for requests to `/.well-known/nodeinfo`
|
- Accept `application/activity+json` for requests to `/.well-known/nodeinfo`
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Truncate remote user fields, avoids them getting rejected
|
- Truncate remote user fields, avoids them getting rejected
|
||||||
- Improve the `FollowValidator` to successfully incoming activities with an errant `cc` field.
|
- Improve the `FollowValidator` to successfully incoming activities with an errant `cc` field.
|
||||||
- Resolved edge case where the API can report you are following a user but the relationship is not fully established.
|
- Resolved edge case where the API can report you are following a user but the relationship is not fully established.
|
||||||
|
|
@ -122,16 +239,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
## 2.7.0
|
## 2.7.0
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- HTTP Security: By default, don't allow unsafe-eval. The setting needs to be changed to allow Flash emulation.
|
- HTTP Security: By default, don't allow unsafe-eval. The setting needs to be changed to allow Flash emulation.
|
||||||
- Fix webfinger spoofing.
|
- Fix webfinger spoofing.
|
||||||
- Use proper workers for fetching pins instead of an ad-hoc task, fixing a potential fetch loop
|
- Use proper workers for fetching pins instead of an ad-hoc task, fixing a potential fetch loop
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Update to Phoenix 1.7
|
- Update to Phoenix 1.7
|
||||||
- Elixir Logger configuration is now longer permitted through AdminFE and ConfigDB
|
- Elixir Logger configuration is now longer permitted through AdminFE and ConfigDB
|
||||||
- Refactor the user backups code and improve test coverage
|
- Refactor the user backups code and improve test coverage
|
||||||
- Invalid activities delivered to the inbox will be rejected with a 400 Bad Request
|
- Invalid activities delivered to the inbox will be rejected with a 400 Bad Request
|
||||||
- Support Bandit as an alternative to Cowboy for the HTTP server.
|
- Support Bandit as an alternative to Cowboy for the HTTP server.
|
||||||
- Update Bandit to 1.5.2
|
- Update Bandit to 1.5.2
|
||||||
- Replace eblurhash with rinpatch_blurhash. This also removes a dependency on ImageMagick.
|
- Replace eblurhash with rinpatch_blurhash. This also removes a dependency on ImageMagick.
|
||||||
- Elixir 1.13 is the minimum required version.
|
- Elixir 1.13 is the minimum required version.
|
||||||
|
|
@ -170,6 +289,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Refactor the Mastodon /api/v1/streaming websocket handler to use Phoenix.Socket.Transport
|
- Refactor the Mastodon /api/v1/streaming websocket handler to use Phoenix.Socket.Transport
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Uploader: Add support for uploading attachments using IPFS
|
- Uploader: Add support for uploading attachments using IPFS
|
||||||
- Add NSFW-detecting MRF
|
- Add NSFW-detecting MRF
|
||||||
- Add DNSRBL MRF
|
- Add DNSRBL MRF
|
||||||
|
|
@ -215,6 +335,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Support honk-style attachment summaries as alt-text.
|
- Support honk-style attachment summaries as alt-text.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fix Emoji object IDs not always being valid
|
- Fix Emoji object IDs not always being valid
|
||||||
- Remove checking ImageMagick's commands for Pleroma.Upload.Filter.AnalyzeMetadata
|
- Remove checking ImageMagick's commands for Pleroma.Upload.Filter.AnalyzeMetadata
|
||||||
- Ensure that StripLocation actually removes everything resembling GPS data from PNGs
|
- Ensure that StripLocation actually removes everything resembling GPS data from PNGs
|
||||||
|
|
@ -257,7 +378,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Fix Optimistic Inbox for failed signatures
|
- Fix Optimistic Inbox for failed signatures
|
||||||
- MediaProxy Preview failures prevented when encountering certain video files
|
- MediaProxy Preview failures prevented when encountering certain video files
|
||||||
- pleroma_ctl: Use realpath(1) instead of readlink(1)
|
- pleroma_ctl: Use realpath(1) instead of readlink(1)
|
||||||
- ReceiverWorker: Make sure non-{:ok, _} is returned as {:error, …}
|
- ReceiverWorker: Make sure non-{:ok, \_} is returned as {:error, …}
|
||||||
- Harden Rich Media parsing against very slow or malicious URLs
|
- Harden Rich Media parsing against very slow or malicious URLs
|
||||||
- Rich Media Preview cache eviction when the activity is updated.
|
- Rich Media Preview cache eviction when the activity is updated.
|
||||||
- Parsing of RichMedia TTLs for Amazon URLs when query parameters are nil
|
- Parsing of RichMedia TTLs for Amazon URLs when query parameters are nil
|
||||||
|
|
@ -269,32 +390,41 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Fix validate_webfinger when running a different domain for Webfinger
|
- Fix validate_webfinger when running a different domain for Webfinger
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- Mastodon API: Remove deprecated GET /api/v1/statuses/:id/card endpoint https://github.com/mastodon/mastodon/pull/11213
|
- Mastodon API: Remove deprecated GET /api/v1/statuses/:id/card endpoint https://github.com/mastodon/mastodon/pull/11213
|
||||||
- Removed support for multiple federator modules as we only support ActivityPub
|
- Removed support for multiple federator modules as we only support ActivityPub
|
||||||
|
|
||||||
## 2.6.2
|
## 2.6.2
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- MRF StealEmojiPolicy: Sanitize shortcodes (thanks to Hazel K for the report
|
- MRF StealEmojiPolicy: Sanitize shortcodes (thanks to Hazel K for the report
|
||||||
|
|
||||||
## 2.6.1
|
## 2.6.1
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- - Document maximum supported version of Erlang & Elixir
|
- - Document maximum supported version of Erlang & Elixir
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- [docs] add frontends management documentation
|
- [docs] add frontends management documentation
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- TwitterAPI: Return proper error when healthcheck is disabled
|
- TwitterAPI: Return proper error when healthcheck is disabled
|
||||||
- Fix eblurhash and elixir-captcha not using system cflags
|
- Fix eblurhash and elixir-captcha not using system cflags
|
||||||
|
|
||||||
## 2.6.0
|
## 2.6.0
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Preload: Make generated JSON html-safe. It already was html safe because it only consists of config data that is base64 encoded, but this will keep it safe it that ever changes.
|
- Preload: Make generated JSON html-safe. It already was html safe because it only consists of config data that is base64 encoded, but this will keep it safe it that ever changes.
|
||||||
- CommonAPI: Prevent users from accessing media of other users by creating a status with reused attachment ID
|
- CommonAPI: Prevent users from accessing media of other users by creating a status with reused attachment ID
|
||||||
- Disable XML entity resolution completely to fix a dos vulnerability
|
- Disable XML entity resolution completely to fix a dos vulnerability
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Support for Image activities, namely from Hubzilla
|
- Support for Image activities, namely from Hubzilla
|
||||||
- Add OAuth scope descriptions
|
- Add OAuth scope descriptions
|
||||||
- Allow lang attribute in status text
|
- Allow lang attribute in status text
|
||||||
|
|
@ -305,6 +435,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Add unified streaming endpoint
|
- Add unified streaming endpoint
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- rel="me" was missing its cache
|
- rel="me" was missing its cache
|
||||||
- MediaProxy responses now return a sandbox CSP header
|
- MediaProxy responses now return a sandbox CSP header
|
||||||
- Filter context activities using Visibility.visible_for_user?
|
- Filter context activities using Visibility.visible_for_user?
|
||||||
|
|
@ -326,6 +457,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Show more informative errors when profile exceeds char limits
|
- Show more informative errors when profile exceeds char limits
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- BREAKING: Support for passwords generated with `crypt(3)` (Gnu Social migration artifact)
|
- BREAKING: Support for passwords generated with `crypt(3)` (Gnu Social migration artifact)
|
||||||
- remove BBS/SSH feature, replaced by an external bridge.
|
- remove BBS/SSH feature, replaced by an external bridge.
|
||||||
- Remove a few unused indexes.
|
- Remove a few unused indexes.
|
||||||
|
|
@ -335,56 +467,67 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
## 2.5.4
|
## 2.5.4
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitrary files from the server's filesystem
|
- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitrary files from the server's filesystem
|
||||||
|
|
||||||
## 2.5.3
|
## 2.5.3
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Emoji pack loader sanitizes pack names
|
- Emoji pack loader sanitizes pack names
|
||||||
- Reduced permissions of config files and directories, distros requiring greater permissions like group-read need to pre-create the directories
|
- Reduced permissions of config files and directories, distros requiring greater permissions like group-read need to pre-create the directories
|
||||||
|
|
||||||
## 2.5.5
|
## 2.5.5
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
- Prevent users from accessing media of other users by creating a status with reused attachment ID
|
- Prevent users from accessing media of other users by creating a status with reused attachment ID
|
||||||
|
|
||||||
## 2.5.4
|
## 2.5.4
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitrary files from the server's filesystem
|
- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitrary files from the server's filesystem
|
||||||
|
|
||||||
## 2.5.3
|
## 2.5.3
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Emoji pack loader sanitizes pack names
|
- Emoji pack loader sanitizes pack names
|
||||||
- Reduced permissions of config files and directories, distros requiring greater permissions like group-read need to pre-create the directories
|
- Reduced permissions of config files and directories, distros requiring greater permissions like group-read need to pre-create the directories
|
||||||
|
|
||||||
## 2.5.2
|
## 2.5.2
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- `/proxy` endpoint now sets a Content-Security-Policy (sandbox)
|
- `/proxy` endpoint now sets a Content-Security-Policy (sandbox)
|
||||||
- WebSocket endpoint now respects unauthenticated restrictions for streams of public posts
|
- WebSocket endpoint now respects unauthenticated restrictions for streams of public posts
|
||||||
- OEmbed HTML tags are now filtered
|
- OEmbed HTML tags are now filtered
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- docs: Be more explicit about the level of compatibility of OTP releases
|
- docs: Be more explicit about the level of compatibility of OTP releases
|
||||||
- Set default background worker timeout to 15 minutes
|
- Set default background worker timeout to 15 minutes
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Atom/RSS formatting (HTML truncation, published, missing summary)
|
- Atom/RSS formatting (HTML truncation, published, missing summary)
|
||||||
- Remove `static_fe` pipeline for `/users/:nickname/feed`
|
- Remove `static_fe` pipeline for `/users/:nickname/feed`
|
||||||
- Stop oban from retrying if validating errors occur when processing incoming data
|
- Stop oban from retrying if validating errors occur when processing incoming data
|
||||||
- Make sure object refetching as used by already received polls follows MRF rules
|
- Make sure object refetching as used by already received polls follows MRF rules
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- BREAKING: Support for passwords generated with `crypt(3)` (Gnu Social migration artifact)
|
- BREAKING: Support for passwords generated with `crypt(3)` (Gnu Social migration artifact)
|
||||||
|
|
||||||
## 2.5.1
|
## 2.5.1
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Allow customizing instance languages
|
- Allow customizing instance languages
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Security: uploading HTTP endpoint can no longer create directories in the upload dir (internal APIs, like backup, still can do it.)
|
- Security: uploading HTTP endpoint can no longer create directories in the upload dir (internal APIs, like backup, still can do it.)
|
||||||
- ~ character in urls in Markdown posts are handled properly
|
- ~ character in urls in Markdown posts are handled properly
|
||||||
- Exiftool upload filter will now ignore SVG files
|
- Exiftool upload filter will now ignore SVG files
|
||||||
|
|
@ -405,6 +548,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Quack, the logging backend that pushes to Slack channels
|
- Quack, the logging backend that pushes to Slack channels
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **Breaking:** Elixir >=1.11 is now required (was >= 1.9)
|
- **Breaking:** Elixir >=1.11 is now required (was >= 1.9)
|
||||||
- Allow users to remove their emails if instance does not need email to register
|
- Allow users to remove their emails if instance does not need email to register
|
||||||
- Uploadfilter `Pleroma.Upload.Filter.Exiftool` has been renamed to `Pleroma.Upload.Filter.Exiftool.StripLocation`
|
- Uploadfilter `Pleroma.Upload.Filter.Exiftool` has been renamed to `Pleroma.Upload.Filter.Exiftool.StripLocation`
|
||||||
|
|
@ -415,6 +559,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- CSP now includes wasm-unsafe-eval
|
- CSP now includes wasm-unsafe-eval
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `activeMonth` and `activeHalfyear` fields in NodeInfo usage.users object
|
- `activeMonth` and `activeHalfyear` fields in NodeInfo usage.users object
|
||||||
- Experimental support for Finch. Put `config :tesla, :adapter, {Tesla.Adapter.Finch, name: MyFinch}` in your secrets file to use it. Reverse Proxy will still use Hackney.
|
- Experimental support for Finch. Put `config :tesla, :adapter, {Tesla.Adapter.Finch, name: MyFinch}` in your secrets file to use it. Reverse Proxy will still use Hackney.
|
||||||
- `ForceMentionsInPostContent` MRF policy
|
- `ForceMentionsInPostContent` MRF policy
|
||||||
|
|
@ -436,6 +581,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Possibility to discover users like `user@example.org`, while Pleroma is working on `pleroma.example.org`. Additional configuration required.
|
- Possibility to discover users like `user@example.org`, while Pleroma is working on `pleroma.example.org`. Additional configuration required.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Subscription(Bell) Notifications: Don't create from Pipeline Ingested replies
|
- Subscription(Bell) Notifications: Don't create from Pipeline Ingested replies
|
||||||
- Handle Reject for already-accepted Follows properly
|
- Handle Reject for already-accepted Follows properly
|
||||||
- Display OpenGraph data on alternative notice routes.
|
- Display OpenGraph data on alternative notice routes.
|
||||||
|
|
@ -458,6 +604,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
## 2.4.5 - 2022-11-27
|
## 2.4.5 - 2022-11-27
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
- Image `class` attributes not being scrubbed, allowing to exploit frontend special classes [!3792](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3792)
|
- Image `class` attributes not being scrubbed, allowing to exploit frontend special classes [!3792](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3792)
|
||||||
- Delete report notifs when demoting from superuser [!3642](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3642)
|
- Delete report notifs when demoting from superuser [!3642](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3642)
|
||||||
- Validate `mediaType` only by it's format rather than using a list [!3597](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3597)
|
- Validate `mediaType` only by it's format rather than using a list [!3597](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3597)
|
||||||
|
|
@ -472,17 +619,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
## 2.4.4 - 2022-08-19
|
## 2.4.4 - 2022-08-19
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Streaming API sessions will now properly disconnect if the corresponding token is revoked
|
- Streaming API sessions will now properly disconnect if the corresponding token is revoked
|
||||||
|
|
||||||
## 2.4.3 - 2022-05-06
|
## 2.4.3 - 2022-05-06
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Private `/objects/` and `/activities/` leaking if cached by authenticated user
|
- Private `/objects/` and `/activities/` leaking if cached by authenticated user
|
||||||
- SweetXML library DTD bomb
|
- SweetXML library DTD bomb
|
||||||
|
|
||||||
## 2.4.2 - 2022-01-10
|
## 2.4.2 - 2022-01-10
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Federation issues caused by HTTP pool checkout timeouts
|
- Federation issues caused by HTTP pool checkout timeouts
|
||||||
- Compatibility with Elixir 1.13
|
- Compatibility with Elixir 1.13
|
||||||
|
|
||||||
|
|
@ -493,12 +643,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
## 2.4.1 - 2021-08-29
|
## 2.4.1 - 2021-08-29
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Make `mix pleroma.database set_text_search_config` run concurrently and indefinitely
|
- Make `mix pleroma.database set_text_search_config` run concurrently and indefinitely
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- AdminAPI: Missing configuration description for StealEmojiPolicy
|
- AdminAPI: Missing configuration description for StealEmojiPolicy
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- MastodonAPI: Stream out Create activities
|
- MastodonAPI: Stream out Create activities
|
||||||
- MRF ObjectAgePolicy: Fix pattern matching on "published"
|
- MRF ObjectAgePolicy: Fix pattern matching on "published"
|
||||||
- TwitterAPI: Make `change_password` and `change_email` require params on body instead of query
|
- TwitterAPI: Make `change_password` and `change_email` require params on body instead of query
|
||||||
|
|
@ -537,6 +690,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Pinned posts federation
|
- Pinned posts federation
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Don't crash so hard when email settings are invalid.
|
- Don't crash so hard when email settings are invalid.
|
||||||
- Checking activated Upload Filters for required commands.
|
- Checking activated Upload Filters for required commands.
|
||||||
- Remote users can no longer reappear after being deleted.
|
- Remote users can no longer reappear after being deleted.
|
||||||
|
|
@ -554,6 +708,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Fixed some Markdown issues, including trailing slash in links.
|
- Fixed some Markdown issues, including trailing slash in links.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- **Breaking**: Remove deprecated `/api/qvitter/statuses/notifications/read` (replaced by `/api/v1/pleroma/notifications/read`)
|
- **Breaking**: Remove deprecated `/api/qvitter/statuses/notifications/read` (replaced by `/api/v1/pleroma/notifications/read`)
|
||||||
|
|
||||||
## [2.3.0] - 2021-03-01
|
## [2.3.0] - 2021-03-01
|
||||||
|
|
@ -672,6 +827,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
## [2.2.1] - 2020-12-22
|
## [2.2.1] - 2020-12-22
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Updated Pleroma FE
|
- Updated Pleroma FE
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
@ -724,7 +880,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- **Breaking:** `Pleroma.Workers.Cron.ClearOauthTokenWorker` setting from Oban `:crontab` (moved to scheduled jobs).
|
- **Breaking:** `Pleroma.Workers.Cron.ClearOauthTokenWorker` setting from Oban `:crontab` (moved to scheduled jobs).
|
||||||
- **Breaking:** `Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker` setting from Oban `:crontab` (moved to scheduled jobs).
|
- **Breaking:** `Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker` setting from Oban `:crontab` (moved to scheduled jobs).
|
||||||
- Removed `:managed_config` option. In practice, it was accidentally removed with 2.0.0 release when frontends were
|
- Removed `:managed_config` option. In practice, it was accidentally removed with 2.0.0 release when frontends were
|
||||||
switched to a new configuration mechanism, however it was not officially removed until now.
|
switched to a new configuration mechanism, however it was not officially removed until now.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|
@ -755,8 +911,10 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
|
|
||||||
1. Install libmagic and development headers (`libmagic-dev` on Ubuntu/Debian, `file-dev` on Alpine Linux)
|
1. Install libmagic and development headers (`libmagic-dev` on Ubuntu/Debian, `file-dev` on Alpine Linux)
|
||||||
2. Run database migrations (inside Pleroma directory):
|
2. Run database migrations (inside Pleroma directory):
|
||||||
- OTP: `./bin/pleroma_ctl migrate`
|
|
||||||
- From Source: `mix ecto.migrate`
|
- OTP: `./bin/pleroma_ctl migrate`
|
||||||
|
- From Source: `mix ecto.migrate`
|
||||||
|
|
||||||
3. Restart Pleroma
|
3. Restart Pleroma
|
||||||
|
|
||||||
## [2.1.2] - 2020-09-17
|
## [2.1.2] - 2020-09-17
|
||||||
|
|
@ -784,6 +942,7 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
## [2.1.1] - 2020-09-08
|
## [2.1.1] - 2020-09-08
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Fix possible DoS in Mastodon API user search due to an error in match clauses, leading to an infinite recursion and subsequent OOM with certain inputs.
|
- Fix possible DoS in Mastodon API user search due to an error in match clauses, leading to an infinite recursion and subsequent OOM with certain inputs.
|
||||||
- Fix metadata leak for accounts and statuses on private instances.
|
- Fix metadata leak for accounts and statuses on private instances.
|
||||||
- Fix possible DoS in Admin API search using an atom leak vulnerability. Authentication with admin rights was required to exploit.
|
- Fix possible DoS in Admin API search using an atom leak vulnerability. Authentication with admin rights was required to exploit.
|
||||||
|
|
@ -794,6 +953,7 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
- Improved error message when cmake is not available at build stage.
|
- Improved error message when cmake is not available at build stage.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Rich media failure tracking (along with `:failure_backoff` option).
|
- Rich media failure tracking (along with `:failure_backoff` option).
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
|
@ -803,6 +963,7 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Default HTTP adapter not respecting pool setting, leading to possible OOM.
|
- Default HTTP adapter not respecting pool setting, leading to possible OOM.
|
||||||
- Fixed uploading webp images when the Exiftool Upload Filter is enabled by skipping them
|
- Fixed uploading webp images when the Exiftool Upload Filter is enabled by skipping them
|
||||||
- Mastodon API: Search parameter `following` now correctly returns the followings rather than the followers
|
- Mastodon API: Search parameter `following` now correctly returns the followings rather than the followers
|
||||||
|
|
@ -908,6 +1069,7 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fix list pagination and other list issues.
|
- Fix list pagination and other list issues.
|
||||||
- Support pagination in conversations API
|
- Support pagination in conversations API
|
||||||
- **Breaking**: SimplePolicy `:reject` and `:accept` allow deletions again
|
- **Breaking**: SimplePolicy `:reject` and `:accept` allow deletions again
|
||||||
|
|
@ -928,9 +1090,11 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
## [2.0.7] - 2020-06-13
|
## [2.0.7] - 2020-06-13
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Fix potential DoSes exploiting atom leaks in rich media parser and the `UserAllowListPolicy` MRF policy
|
- Fix potential DoSes exploiting atom leaks in rich media parser and the `UserAllowListPolicy` MRF policy
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- CSP: not allowing images/media from every host when mediaproxy is disabled
|
- CSP: not allowing images/media from every host when mediaproxy is disabled
|
||||||
- CSP: not adding mediaproxy base url to image/media hosts
|
- CSP: not adding mediaproxy base url to image/media hosts
|
||||||
- StaticFE missing the CSS file
|
- StaticFE missing the CSS file
|
||||||
|
|
@ -942,28 +1106,36 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
## [2.0.6] - 2020-06-09
|
## [2.0.6] - 2020-06-09
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- CSP: harden `image-src` and `media-src` when MediaProxy is used
|
- CSP: harden `image-src` and `media-src` when MediaProxy is used
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- AP C2S: Fix pagination in inbox/outbox
|
- AP C2S: Fix pagination in inbox/outbox
|
||||||
- Various compilation errors on OTP 23
|
- Various compilation errors on OTP 23
|
||||||
- Mastodon API streaming: Repeats from muted threads not being filtered
|
- Mastodon API streaming: Repeats from muted threads not being filtered
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Various database performance improvements
|
- Various database performance improvements
|
||||||
|
|
||||||
### Upgrade notes
|
### Upgrade notes
|
||||||
|
|
||||||
1. Run database migrations (inside Pleroma directory):
|
1. Run database migrations (inside Pleroma directory):
|
||||||
- OTP: `./bin/pleroma_ctl migrate`
|
|
||||||
- From Source: `mix ecto.migrate`
|
- OTP: `./bin/pleroma_ctl migrate`
|
||||||
|
- From Source: `mix ecto.migrate`
|
||||||
|
|
||||||
2. Restart Pleroma
|
2. Restart Pleroma
|
||||||
|
|
||||||
## [2.0.5] - 2020-05-13
|
## [2.0.5] - 2020-05-13
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Fix possible private status leaks in Mastodon Streaming API
|
- Fix possible private status leaks in Mastodon Streaming API
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Crashes when trying to block a user if block federation is disabled
|
- Crashes when trying to block a user if block federation is disabled
|
||||||
- Not being able to start the instance without `erlang-eldap` installed
|
- Not being able to start the instance without `erlang-eldap` installed
|
||||||
- Users with bios over the limit getting rejected
|
- Users with bios over the limit getting rejected
|
||||||
|
|
@ -976,9 +1148,11 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
## [2.0.4] - 2020-05-10
|
## [2.0.4] - 2020-05-10
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- AP C2S: Fix a potential DoS by creating nonsensical objects that break timelines
|
- AP C2S: Fix a potential DoS by creating nonsensical objects that break timelines
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Peertube user lookups not working
|
- Peertube user lookups not working
|
||||||
- `InsertSkeletonsForDeletedUsers` migration failing on some instances
|
- `InsertSkeletonsForDeletedUsers` migration failing on some instances
|
||||||
- Healthcheck reporting the number of memory currently used, rather than allocated in total
|
- Healthcheck reporting the number of memory currently used, rather than allocated in total
|
||||||
|
|
@ -990,6 +1164,7 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
#### Apache only
|
#### Apache only
|
||||||
|
|
||||||
1. Remove the following line from your config:
|
1. Remove the following line from your config:
|
||||||
|
|
||||||
```
|
```
|
||||||
SSLCertificateFile /etc/letsencrypt/live/${servername}/cert.pem
|
SSLCertificateFile /etc/letsencrypt/live/${servername}/cert.pem
|
||||||
```
|
```
|
||||||
|
|
@ -1001,11 +1176,13 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
## [2.0.3] - 2020-05-02
|
## [2.0.3] - 2020-05-02
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Disallow re-registration of previously deleted users, which allowed viewing direct messages addressed to them
|
- Disallow re-registration of previously deleted users, which allowed viewing direct messages addressed to them
|
||||||
- Mastodon API: Fix `POST /api/v1/follow_requests/:id/authorize` allowing to force a follow from a local user even if they didn't request to follow
|
- Mastodon API: Fix `POST /api/v1/follow_requests/:id/authorize` allowing to force a follow from a local user even if they didn't request to follow
|
||||||
- CSP: Sandbox uploads
|
- CSP: Sandbox uploads
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Notifications from blocked domains
|
- Notifications from blocked domains
|
||||||
- Potential federation issues with Mastodon versions before 3.0.0
|
- Potential federation issues with Mastodon versions before 3.0.0
|
||||||
- HTTP Basic Authentication permissions issue
|
- HTTP Basic Authentication permissions issue
|
||||||
|
|
@ -1016,6 +1193,7 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
- `blob:` urls not being allowed by CSP
|
- `blob:` urls not being allowed by CSP
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- NodeInfo: ObjectAgePolicy settings to the `federation` list.
|
- NodeInfo: ObjectAgePolicy settings to the `federation` list.
|
||||||
- Follow request notifications
|
- Follow request notifications
|
||||||
<details>
|
<details>
|
||||||
|
|
@ -1027,19 +1205,24 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
|
|
||||||
1. Restart Pleroma
|
1. Restart Pleroma
|
||||||
2. Run database migrations (inside Pleroma directory):
|
2. Run database migrations (inside Pleroma directory):
|
||||||
- OTP: `./bin/pleroma_ctl migrate`
|
|
||||||
- From Source: `mix ecto.migrate`
|
|
||||||
3. Reset status visibility counters (inside Pleroma directory):
|
|
||||||
- OTP: `./bin/pleroma_ctl refresh_counter_cache`
|
|
||||||
- From Source: `mix pleroma.refresh_counter_cache`
|
|
||||||
|
|
||||||
|
- OTP: `./bin/pleroma_ctl migrate`
|
||||||
|
- From Source: `mix ecto.migrate`
|
||||||
|
|
||||||
|
3. Reset status visibility counters (inside Pleroma directory):
|
||||||
|
|
||||||
|
- OTP: `./bin/pleroma_ctl refresh_counter_cache`
|
||||||
|
- From Source: `mix pleroma.refresh_counter_cache`
|
||||||
|
|
||||||
## [2.0.2] - 2020-04-08
|
## [2.0.2] - 2020-04-08
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Support for Funkwhale's `Audio` activity
|
- Support for Funkwhale's `Audio` activity
|
||||||
- Admin API: `PATCH /api/pleroma/admin/users/:nickname/update_credentials`
|
- Admin API: `PATCH /api/pleroma/admin/users/:nickname/update_credentials`
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Blocked/muted users still generating push notifications
|
- Blocked/muted users still generating push notifications
|
||||||
- Input textbox for bio ignoring newlines
|
- Input textbox for bio ignoring newlines
|
||||||
- OTP: Inability to use PostgreSQL databases with SSL
|
- OTP: Inability to use PostgreSQL databases with SSL
|
||||||
|
|
@ -1047,13 +1230,17 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
- Incorrect URL for Funkwhale channels
|
- Incorrect URL for Funkwhale channels
|
||||||
|
|
||||||
### Upgrade notes
|
### Upgrade notes
|
||||||
|
|
||||||
1. Restart Pleroma
|
1. Restart Pleroma
|
||||||
|
|
||||||
## [2.0.1] - 2020-03-15
|
## [2.0.1] - 2020-03-15
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Static-FE: Fix remote posts not being sanitized
|
- Static-FE: Fix remote posts not being sanitized
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Rate limiter crashes when there is no explicitly specified ip in the config
|
- Rate limiter crashes when there is no explicitly specified ip in the config
|
||||||
- 500 errors when no `Accept` header is present if Static-FE is enabled
|
- 500 errors when no `Accept` header is present if Static-FE is enabled
|
||||||
- Instance panel not being updated immediately due to wrong `Cache-Control` headers
|
- Instance panel not being updated immediately due to wrong `Cache-Control` headers
|
||||||
|
|
@ -1064,24 +1251,33 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
- Mastodon Streaming API: hashtag timelines not working
|
- Mastodon Streaming API: hashtag timelines not working
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- BBCode and Markdown formatters will no longer return any `\n` and only use `<br/>` for newlines
|
- BBCode and Markdown formatters will no longer return any `\n` and only use `<br/>` for newlines
|
||||||
- Mastodon API: Allow registration without email if email verification is not enabled
|
- Mastodon API: Allow registration without email if email verification is not enabled
|
||||||
|
|
||||||
### Upgrade notes
|
### Upgrade notes
|
||||||
|
|
||||||
#### Nginx only
|
#### Nginx only
|
||||||
|
|
||||||
1. Remove `proxy_ignore_headers Cache-Control;` and `proxy_hide_header Cache-Control;` from your config.
|
1. Remove `proxy_ignore_headers Cache-Control;` and `proxy_hide_header Cache-Control;` from your config.
|
||||||
|
|
||||||
#### Everyone
|
#### Everyone
|
||||||
|
|
||||||
1. Run database migrations (inside Pleroma directory):
|
1. Run database migrations (inside Pleroma directory):
|
||||||
- OTP: `./bin/pleroma_ctl migrate`
|
|
||||||
- From Source: `mix ecto.migrate`
|
- OTP: `./bin/pleroma_ctl migrate`
|
||||||
|
- From Source: `mix ecto.migrate`
|
||||||
|
|
||||||
2. Restart Pleroma
|
2. Restart Pleroma
|
||||||
|
|
||||||
## [2.0.0] - 2019-03-08
|
## [2.0.0] - 2019-03-08
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Mastodon API: Fix being able to request enormous amount of statuses in timelines leading to DoS. Now limited to 40 per request.
|
- Mastodon API: Fix being able to request enormous amount of statuses in timelines leading to DoS. Now limited to 40 per request.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- **Breaking**: Removed 1.0+ deprecated configurations `Pleroma.Upload, :strip_exif` and `:instance, :dedupe_media`
|
- **Breaking**: Removed 1.0+ deprecated configurations `Pleroma.Upload, :strip_exif` and `:instance, :dedupe_media`
|
||||||
- **Breaking**: OStatus protocol support
|
- **Breaking**: OStatus protocol support
|
||||||
- **Breaking**: MDII uploader
|
- **Breaking**: MDII uploader
|
||||||
|
|
@ -1093,6 +1289,7 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **Breaking:** Pleroma won't start if it detects unapplied migrations
|
- **Breaking:** Pleroma won't start if it detects unapplied migrations
|
||||||
- **Breaking:** Elixir >=1.8 is now required (was >= 1.7)
|
- **Breaking:** Elixir >=1.8 is now required (was >= 1.7)
|
||||||
- **Breaking:** `Pleroma.Plugs.RemoteIp` and `:rate_limiter` enabled by default. Please ensure your reverse proxy forwards the real IP!
|
- **Breaking:** `Pleroma.Plugs.RemoteIp` and `:rate_limiter` enabled by default. Please ensure your reverse proxy forwards the real IP!
|
||||||
|
|
@ -1142,6 +1339,7 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `:chat_limit` option to limit chat characters.
|
- `:chat_limit` option to limit chat characters.
|
||||||
- `cleanup_attachments` option to remove attachments along with statuses. Does not affect duplicate files and attachments without status. Enabling this will increase load to database when deleting statuses on larger instances.
|
- `cleanup_attachments` option to remove attachments along with statuses. Does not affect duplicate files and attachments without status. Enabling this will increase load to database when deleting statuses on larger instances.
|
||||||
- Refreshing poll results for remote polls
|
- Refreshing poll results for remote polls
|
||||||
|
|
@ -1209,6 +1407,7 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Report emails now include functional links to profiles of remote user accounts
|
- Report emails now include functional links to profiles of remote user accounts
|
||||||
- Not being able to log in to some third-party apps when logged in to MastoFE
|
- Not being able to log in to some third-party apps when logged in to MastoFE
|
||||||
- MRF: `Delete` activities being exempt from MRF policies
|
- MRF: `Delete` activities being exempt from MRF policies
|
||||||
|
|
@ -1228,7 +1427,9 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## [1.1.9] - 2020-02-10
|
## [1.1.9] - 2020-02-10
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- OTP: Inability to set the upload limit (again)
|
- OTP: Inability to set the upload limit (again)
|
||||||
- Not being able to pin polls
|
- Not being able to pin polls
|
||||||
- Streaming API: incorrect handling of reblog mutes
|
- Streaming API: incorrect handling of reblog mutes
|
||||||
|
|
@ -1236,98 +1437,132 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
- OpenGraph provider: html entities in descriptions
|
- OpenGraph provider: html entities in descriptions
|
||||||
|
|
||||||
## [1.1.8] - 2020-01-10
|
## [1.1.8] - 2020-01-10
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Captcha generation issues
|
- Captcha generation issues
|
||||||
- Returned Kocaptcha endpoint to configuration
|
- Returned Kocaptcha endpoint to configuration
|
||||||
- Captcha validity is now 5 minutes
|
- Captcha validity is now 5 minutes
|
||||||
|
|
||||||
## [1.1.7] - 2019-12-13
|
## [1.1.7] - 2019-12-13
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- OTP: Inability to set the upload limit
|
- OTP: Inability to set the upload limit
|
||||||
- OTP: Inability to override node name/distribution type to run 2 Pleroma instances on the same machine
|
- OTP: Inability to override node name/distribution type to run 2 Pleroma instances on the same machine
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Integrated captcha provider
|
- Integrated captcha provider
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Captcha enabled by default
|
- Captcha enabled by default
|
||||||
- Default Captcha provider changed from `Pleroma.Captcha.Kocaptcha` to `Pleroma.Captcha.Native`
|
- Default Captcha provider changed from `Pleroma.Captcha.Kocaptcha` to `Pleroma.Captcha.Native`
|
||||||
- Better `Cache-Control` header for static content
|
- Better `Cache-Control` header for static content
|
||||||
|
|
||||||
### Bundled Pleroma-FE Changes
|
### Bundled Pleroma-FE Changes
|
||||||
|
|
||||||
#### Added
|
#### Added
|
||||||
|
|
||||||
- Icons in the navigation panel
|
- Icons in the navigation panel
|
||||||
|
|
||||||
#### Fixed
|
#### Fixed
|
||||||
|
|
||||||
- Improved support unauthenticated view of private instances
|
- Improved support unauthenticated view of private instances
|
||||||
|
|
||||||
#### Removed
|
#### Removed
|
||||||
|
|
||||||
- Whitespace hack on empty post content
|
- Whitespace hack on empty post content
|
||||||
|
|
||||||
## [1.1.6] - 2019-11-19
|
## [1.1.6] - 2019-11-19
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Not being able to log into to third party apps when the browser is logged into mastofe
|
- Not being able to log into to third party apps when the browser is logged into mastofe
|
||||||
- Email confirmation not being required even when enabled
|
- Email confirmation not being required even when enabled
|
||||||
- Mastodon API: conversations API crashing when one status is malformed
|
- Mastodon API: conversations API crashing when one status is malformed
|
||||||
|
|
||||||
### Bundled Pleroma-FE Changes
|
### Bundled Pleroma-FE Changes
|
||||||
|
|
||||||
#### Added
|
#### Added
|
||||||
|
|
||||||
- About page
|
- About page
|
||||||
- Meme arrows
|
- Meme arrows
|
||||||
|
|
||||||
#### Fixed
|
#### Fixed
|
||||||
|
|
||||||
- Image modal not closing unless clicked outside of image
|
- Image modal not closing unless clicked outside of image
|
||||||
- Attachment upload spinner not being centered
|
- Attachment upload spinner not being centered
|
||||||
- Showing follow counters being 0 when they are actually hidden
|
- Showing follow counters being 0 when they are actually hidden
|
||||||
|
|
||||||
## [1.1.5] - 2019-11-09
|
## [1.1.5] - 2019-11-09
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Polls having different numbers in timelines/notifications/poll api endpoints due to cache desyncronization
|
- Polls having different numbers in timelines/notifications/poll api endpoints due to cache desyncronization
|
||||||
- Pleroma API: OAuth token endpoint not being found when ".json" suffix is appended
|
- Pleroma API: OAuth token endpoint not being found when ".json" suffix is appended
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Frontend bundle updated to [044c9ad0](https://git.pleroma.social/pleroma/pleroma-fe/commit/044c9ad0562af059dd961d50961a3880fca9c642)
|
- Frontend bundle updated to [044c9ad0](https://git.pleroma.social/pleroma/pleroma-fe/commit/044c9ad0562af059dd961d50961a3880fca9c642)
|
||||||
|
|
||||||
## [1.1.4] - 2019-11-01
|
## [1.1.4] - 2019-11-01
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Added a migration that fills up empty user.info fields to prevent breakage after previous unsafe migrations.
|
- Added a migration that fills up empty user.info fields to prevent breakage after previous unsafe migrations.
|
||||||
- Failure to migrate from pre-1.0.0 versions
|
- Failure to migrate from pre-1.0.0 versions
|
||||||
- Mastodon API: Notification stream not including follow notifications
|
- Mastodon API: Notification stream not including follow notifications
|
||||||
|
|
||||||
## [1.1.3] - 2019-10-25
|
## [1.1.3] - 2019-10-25
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Blocked users showing up in notifications collapsed as if they were muted
|
- Blocked users showing up in notifications collapsed as if they were muted
|
||||||
- `pleroma_ctl` not working on Debian's default shell
|
- `pleroma_ctl` not working on Debian's default shell
|
||||||
|
|
||||||
## [1.1.2] - 2019-10-18
|
## [1.1.2] - 2019-10-18
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- `pleroma_ctl` trying to connect to a running instance when generating the config, which of course doesn't exist.
|
- `pleroma_ctl` trying to connect to a running instance when generating the config, which of course doesn't exist.
|
||||||
|
|
||||||
## [1.1.1] - 2019-10-18
|
## [1.1.1] - 2019-10-18
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- One of the migrations between 1.0.0 and 1.1.0 wiping user info of the relay user because of unexpected behavior of postgresql's `jsonb_set`, resulting in inability to post in the default configuration. If you were affected, please run the following query in postgres console, the relay user will be recreated automatically:
|
- One of the migrations between 1.0.0 and 1.1.0 wiping user info of the relay user because of unexpected behavior of postgresql's `jsonb_set`, resulting in inability to post in the default configuration. If you were affected, please run the following query in postgres console, the relay user will be recreated automatically:
|
||||||
|
|
||||||
```
|
```
|
||||||
delete from users where ap_id = 'https://your.instance.hostname/relay';
|
delete from users where ap_id = 'https://your.instance.hostname/relay';
|
||||||
```
|
```
|
||||||
|
|
||||||
- Bad user search matches
|
- Bad user search matches
|
||||||
|
|
||||||
## [1.1.0] - 2019-10-14
|
## [1.1.0] - 2019-10-14
|
||||||
|
|
||||||
**Breaking:** The stable branch has been changed from `master` to `stable`. If you want to keep using 1.0, the `release/1.0` branch will receive security updates for 6 months after 1.1 release.
|
**Breaking:** The stable branch has been changed from `master` to `stable`. If you want to keep using 1.0, the `release/1.0` branch will receive security updates for 6 months after 1.1 release.
|
||||||
|
|
||||||
**OTP Note:** `pleroma_ctl` in 1.0 defaults to `master` and doesn't support specifying arbitrary branches, making `./pleroma_ctl update` fail. To fix this, fetch a version of `pleroma_ctl` from 1.1 using the command below and proceed with the update normally:
|
**OTP Note:** `pleroma_ctl` in 1.0 defaults to `master` and doesn't support specifying arbitrary branches, making `./pleroma_ctl update` fail. To fix this, fetch a version of `pleroma_ctl` from 1.1 using the command below and proceed with the update normally:
|
||||||
|
|
||||||
```
|
```
|
||||||
curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/develop/rel/files/bin/pleroma_ctl'
|
curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/develop/rel/files/bin/pleroma_ctl'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Mastodon API: respect post privacy in `/api/v1/statuses/:id/{favourited,reblogged}_by`
|
- Mastodon API: respect post privacy in `/api/v1/statuses/:id/{favourited,reblogged}_by`
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- **Breaking:** GNU Social API with Qvitter extensions support
|
- **Breaking:** GNU Social API with Qvitter extensions support
|
||||||
- Emoji: Remove longfox emojis.
|
- Emoji: Remove longfox emojis.
|
||||||
- Remove `Reply-To` header from report emails for admins.
|
- Remove `Reply-To` header from report emails for admins.
|
||||||
- ActivityPub: The `/objects/:uuid/likes` endpoint.
|
- ActivityPub: The `/objects/:uuid/likes` endpoint.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **Breaking:** Configuration: A setting to explicitly disable the mailer was added, defaulting to true, if you are using a mailer add `config :pleroma, Pleroma.Emails.Mailer, enabled: true` to your config
|
- **Breaking:** Configuration: A setting to explicitly disable the mailer was added, defaulting to true, if you are using a mailer add `config :pleroma, Pleroma.Emails.Mailer, enabled: true` to your config
|
||||||
- **Breaking:** Configuration: `/media/` is now removed when `base_url` is configured, append `/media/` to your `base_url` config to keep the old behaviour if desired
|
- **Breaking:** Configuration: `/media/` is now removed when `base_url` is configured, append `/media/` to your `base_url` config to keep the old behaviour if desired
|
||||||
- **Breaking:** `/api/pleroma/notifications/read` is moved to `/api/v1/pleroma/notifications/read` and now supports `max_id` and responds with Mastodon API entities.
|
- **Breaking:** `/api/pleroma/notifications/read` is moved to `/api/v1/pleroma/notifications/read` and now supports `max_id` and responds with Mastodon API entities.
|
||||||
|
|
@ -1341,10 +1576,11 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
|
||||||
- Mastodon API: `pleroma.thread_muted` key in the Status entity
|
- Mastodon API: `pleroma.thread_muted` key in the Status entity
|
||||||
- AdminAPI: Add "godmode" while fetching user statuses (i.e. admin can see private statuses)
|
- AdminAPI: Add "godmode" while fetching user statuses (i.e. admin can see private statuses)
|
||||||
- Improve digest email template
|
- Improve digest email template
|
||||||
– Pagination: (optional) return `total` alongside with `items` when paginating
|
– Pagination: (optional) return `total` alongside with `items` when paginating
|
||||||
- The `Pleroma.FlakeId` module has been replaced with the `flake_id` library.
|
- The `Pleroma.FlakeId` module has been replaced with the `flake_id` library.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Following from Osada
|
- Following from Osada
|
||||||
- Favorites timeline doing database-intensive queries
|
- Favorites timeline doing database-intensive queries
|
||||||
- Metadata rendering errors resulting in the entire page being inaccessible
|
- Metadata rendering errors resulting in the entire page being inaccessible
|
||||||
|
|
@ -1377,6 +1613,7 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
|
||||||
- Reverse Proxy limiting `max_body_length` was incorrectly defined and only checked `Content-Length` headers which may not be sufficient in some circumstances
|
- Reverse Proxy limiting `max_body_length` was incorrectly defined and only checked `Content-Length` headers which may not be sufficient in some circumstances
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Expiring/ephemeral activities. All activities can have expires_at value set, which controls when they should be deleted automatically.
|
- Expiring/ephemeral activities. All activities can have expires_at value set, which controls when they should be deleted automatically.
|
||||||
- Mastodon API: in post_status, the expires_in parameter lets you set the number of seconds until an activity expires. It must be at least one hour.
|
- Mastodon API: in post_status, the expires_in parameter lets you set the number of seconds until an activity expires. It must be at least one hour.
|
||||||
- Mastodon API: all status JSON responses contain a `pleroma.expires_at` item which states when an activity will expire. The value is only shown to the user who created the activity. To everyone else it's empty.
|
- Mastodon API: all status JSON responses contain a `pleroma.expires_at` item which states when an activity will expire. The value is only shown to the user who created the activity. To everyone else it's empty.
|
||||||
|
|
@ -1420,24 +1657,33 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
|
||||||
- Reverse Proxy: Do not retry failed requests to limit pressure on the peer
|
- Reverse Proxy: Do not retry failed requests to limit pressure on the peer
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Configuration: Filter.AnonymizeFilename added ability to retain file extension with custom text
|
- Configuration: Filter.AnonymizeFilename added ability to retain file extension with custom text
|
||||||
- Admin API: changed json structure for saving config settings.
|
- Admin API: changed json structure for saving config settings.
|
||||||
- RichMedia: parsers and their order are configured in `rich_media` config.
|
- RichMedia: parsers and their order are configured in `rich_media` config.
|
||||||
- RichMedia: add the rich media ttl based on image expiration time.
|
- RichMedia: add the rich media ttl based on image expiration time.
|
||||||
|
|
||||||
## [1.0.7] - 2019-09-26
|
## [1.0.7] - 2019-09-26
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Broken federation on Erlang 22 (previous versions of hackney http client were using an option that got deprecated)
|
- Broken federation on Erlang 22 (previous versions of hackney http client were using an option that got deprecated)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- ActivityPub: The first page in inboxes/outboxes is no longer embedded.
|
- ActivityPub: The first page in inboxes/outboxes is no longer embedded.
|
||||||
|
|
||||||
## [1.0.6] - 2019-08-14
|
## [1.0.6] - 2019-08-14
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- MRF: fix use of unserializable keyword lists in describe() implementations
|
- MRF: fix use of unserializable keyword lists in describe() implementations
|
||||||
- ActivityPub S2S: POST requests are now signed with `(request-target)` pseudo-header.
|
- ActivityPub S2S: POST requests are now signed with `(request-target)` pseudo-header.
|
||||||
|
|
||||||
## [1.0.5] - 2019-08-13
|
## [1.0.5] - 2019-08-13
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Mastodon API: follower/following counters not being nullified, when `hide_follows`/`hide_followers` is set
|
- Mastodon API: follower/following counters not being nullified, when `hide_follows`/`hide_followers` is set
|
||||||
- Mastodon API: `muted` in the Status entity, using author's account to determine if the thread was muted
|
- Mastodon API: `muted` in the Status entity, using author's account to determine if the thread was muted
|
||||||
- Mastodon API: return the actual profile URL in the Account entity's `url` property when appropriate
|
- Mastodon API: return the actual profile URL in the Account entity's `url` property when appropriate
|
||||||
|
|
@ -1448,6 +1694,7 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
|
||||||
- Fix internal server error when using the healthcheck API.
|
- Fix internal server error when using the healthcheck API.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- **Breaking:** MRF describe API, which adds support for exposing configuration information about MRF policies to NodeInfo.
|
- **Breaking:** MRF describe API, which adds support for exposing configuration information about MRF policies to NodeInfo.
|
||||||
Custom modules will need to be updated by adding, at the very least, `def describe, do: {:ok, %{}}` to the MRF policy modules.
|
Custom modules will need to be updated by adding, at the very least, `def describe, do: {:ok, %{}}` to the MRF policy modules.
|
||||||
- Relays: Added a task to list relay subscriptions.
|
- Relays: Added a task to list relay subscriptions.
|
||||||
|
|
@ -1459,21 +1706,28 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
|
||||||
- Configuration: `federation_incoming_replies_max_depth` option
|
- Configuration: `federation_incoming_replies_max_depth` option
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- Federation: Remove `likes` from objects.
|
- Federation: Remove `likes` from objects.
|
||||||
- **Breaking:** ActivityPub: The `accept_blocks` configuration setting.
|
- **Breaking:** ActivityPub: The `accept_blocks` configuration setting.
|
||||||
|
|
||||||
## [1.0.4] - 2019-08-01
|
## [1.0.4] - 2019-08-01
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Invalid SemVer version generation, when the current branch does not have commits ahead of tag/checked out on a tag
|
- Invalid SemVer version generation, when the current branch does not have commits ahead of tag/checked out on a tag
|
||||||
|
|
||||||
## [1.0.3] - 2019-07-31
|
## [1.0.3] - 2019-07-31
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- OStatus: eliminate the possibility of a protocol downgrade attack.
|
- OStatus: eliminate the possibility of a protocol downgrade attack.
|
||||||
- OStatus: prevent following locked accounts, bypassing the approval process.
|
- OStatus: prevent following locked accounts, bypassing the approval process.
|
||||||
- TwitterAPI: use CommonAPI to handle remote follows instead of OStatus.
|
- TwitterAPI: use CommonAPI to handle remote follows instead of OStatus.
|
||||||
|
|
||||||
## [1.0.2] - 2019-07-28
|
## [1.0.2] - 2019-07-28
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Not being able to pin unlisted posts
|
- Not being able to pin unlisted posts
|
||||||
- Mastodon API: represent poll IDs as strings
|
- Mastodon API: represent poll IDs as strings
|
||||||
- MediaProxy: fix matching filenames
|
- MediaProxy: fix matching filenames
|
||||||
|
|
@ -1484,19 +1738,25 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
|
||||||
- ActivityPub S2S: remote user deletions now work the same as local user deletions.
|
- ActivityPub S2S: remote user deletions now work the same as local user deletions.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Configuration: OpenGraph and TwitterCard providers enabled by default
|
- Configuration: OpenGraph and TwitterCard providers enabled by default
|
||||||
- Configuration: Filter.AnonymizeFilename added ability to retain file extension with custom text
|
- Configuration: Filter.AnonymizeFilename added ability to retain file extension with custom text
|
||||||
|
|
||||||
## [1.0.1] - 2019-07-14
|
## [1.0.1] - 2019-07-14
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- OStatus: fix an object spoofing vulnerability.
|
- OStatus: fix an object spoofing vulnerability.
|
||||||
|
|
||||||
## [1.0.0] - 2019-06-29
|
## [1.0.0] - 2019-06-29
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Mastodon API: Fix display names not being sanitized
|
- Mastodon API: Fix display names not being sanitized
|
||||||
- Rich media: Do not crawl private IP ranges
|
- Rich media: Do not crawl private IP ranges
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Digest email for inactive users
|
- Digest email for inactive users
|
||||||
- Add a generic settings store for frontends / clients to use.
|
- Add a generic settings store for frontends / clients to use.
|
||||||
- Explicit addressing option for posting.
|
- Explicit addressing option for posting.
|
||||||
|
|
@ -1561,6 +1821,7 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
|
||||||
- Configuration: default syslog tag "Pleroma" is now lowercased to "pleroma"
|
- Configuration: default syslog tag "Pleroma" is now lowercased to "pleroma"
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **Breaking:** bind to 127.0.0.1 instead of 0.0.0.0 by default
|
- **Breaking:** bind to 127.0.0.1 instead of 0.0.0.0 by default
|
||||||
- **Breaking:** Configuration: move from Pleroma.Mailer to Pleroma.Emails.Mailer
|
- **Breaking:** Configuration: move from Pleroma.Mailer to Pleroma.Emails.Mailer
|
||||||
- Thread containment / test for complete visibility will be skipped by default.
|
- Thread containment / test for complete visibility will be skipped by default.
|
||||||
|
|
@ -1602,6 +1863,7 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
|
||||||
- Rich Media: crawl only https URLs.
|
- Rich Media: crawl only https URLs.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Follow requests don't get 'stuck' anymore.
|
- Follow requests don't get 'stuck' anymore.
|
||||||
- Added an FTS index on objects. Running `vacuum analyze` and setting a larger `work_mem` is recommended.
|
- Added an FTS index on objects. Running `vacuum analyze` and setting a larger `work_mem` is recommended.
|
||||||
- Followers counter not being updated when a follower is blocked
|
- Followers counter not being updated when a follower is blocked
|
||||||
|
|
@ -1637,31 +1899,48 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
|
||||||
- MRF: Simple policy now properly delists imported or relayed statuses
|
- MRF: Simple policy now properly delists imported or relayed statuses
|
||||||
|
|
||||||
## Removed
|
## Removed
|
||||||
|
|
||||||
- Configuration: `config :pleroma, :fe` in favor of the more flexible `config :pleroma, :frontend_configurations`
|
- Configuration: `config :pleroma, :fe` in favor of the more flexible `config :pleroma, :frontend_configurations`
|
||||||
|
|
||||||
## [0.9.99999] - 2019-05-31
|
## [0.9.99999] - 2019-05-31
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Mastodon API: Fix lists leaking private posts
|
- Mastodon API: Fix lists leaking private posts
|
||||||
|
|
||||||
## [0.9.9999] - 2019-04-05
|
## [0.9.9999] - 2019-04-05
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Mastodon API: Fix content warnings skipping HTML sanitization
|
- Mastodon API: Fix content warnings skipping HTML sanitization
|
||||||
|
|
||||||
## [0.9.999] - 2019-03-13
|
## [0.9.999] - 2019-03-13
|
||||||
|
|
||||||
Frontend changes only.
|
Frontend changes only.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added floating action button for posting status on mobile
|
- Added floating action button for posting status on mobile
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Changed user-settings icon to a pencil
|
- Changed user-settings icon to a pencil
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Keyboard shortcuts activating when typing a message
|
- Keyboard shortcuts activating when typing a message
|
||||||
- Gaps when scrolling down on a timeline after showing new
|
- Gaps when scrolling down on a timeline after showing new
|
||||||
|
|
||||||
## [0.9.99] - 2019-03-08
|
## [0.9.99] - 2019-03-08
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Update the frontend to the 0.9.99 tag
|
- Update the frontend to the 0.9.99 tag
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Sign the date header in federation to fix Mastodon federation.
|
- Sign the date header in federation to fix Mastodon federation.
|
||||||
|
|
||||||
## [0.9.9] - 2019-02-22
|
## [0.9.9] - 2019-02-22
|
||||||
|
|
||||||
This is our first stable release.
|
This is our first stable release.
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
# https://hub.docker.com/r/hexpm/elixir/tags
|
# https://hub.docker.com/r/hexpm/elixir/tags
|
||||||
ARG ELIXIR_IMG=hexpm/elixir
|
ARG ELIXIR_IMG=hexpm/elixir
|
||||||
ARG ELIXIR_VER=1.14.5
|
ARG ELIXIR_VER=1.17.3
|
||||||
ARG ERLANG_VER=25.3.2.14
|
ARG ERLANG_VER=26.2.5.6
|
||||||
ARG ALPINE_VER=3.17.9
|
ARG ALPINE_VER=3.17.9
|
||||||
|
|
||||||
FROM ${ELIXIR_IMG}:${ELIXIR_VER}-erlang-${ERLANG_VER}-alpine-${ALPINE_VER} as build
|
FROM ${ELIXIR_IMG}:${ELIXIR_VER}-erlang-${ERLANG_VER}-alpine-${ALPINE_VER} AS build
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
|
|
@ -15,6 +15,7 @@ RUN apk add git gcc g++ musl-dev make cmake file-dev vips-dev &&\
|
||||||
echo "import Config" > config/prod.secret.exs &&\
|
echo "import Config" > config/prod.secret.exs &&\
|
||||||
mix local.hex --force &&\
|
mix local.hex --force &&\
|
||||||
mix local.rebar --force &&\
|
mix local.rebar --force &&\
|
||||||
|
mix deps.clean --all &&\
|
||||||
mix deps.get --only prod &&\
|
mix deps.get --only prod &&\
|
||||||
mkdir release &&\
|
mkdir release &&\
|
||||||
mix release --path release
|
mix release --path release
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add new activity actor/type index. Greatly speeds up retrieval of rare types (like "Listen")
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix 'Create a user' description in admin api docs
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix AssignAppUser migration OOM
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
- Fix building "captcha" library with OpenBSD make
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Docs: Restore DB schema before data to avoid long restore times
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Return 404 with a better error message instead of 400 when receiving an activity for a deactivated user
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Use JSON for DeepL API requests
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Deleting an instance queues individual jobs for each user that needs to be deleted from the server.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Support Dislike activity, as sent by Mitra and Friendica, by changing it into a thumbs-down EmojiReact
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Elixir 1.18: Fixed warnings and new deprecations
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Added a way to upload new packs from a URL or ZIP file via Admin API
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Support Mitra-style emoji likes.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix endorsement state display in relationship view
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add `duration` to the block endpoint, which makes block expire
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Expose markup configuration in InstanceView
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Set PATH in the FreeBSD rc script to avoid failures starting the service
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Improved performance of status search queries using the default GIN index
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Update Cowboy, Gun, and Plug family of dependencies
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Hashtag searches return real results based on words in your query
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Implement language detection with fastText
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Added MRF.QuietReply which prevents replies to public posts from being published to the timelines
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Oban Notifier was changed to Oban.Notifiers.PG for performance and scalability benefits
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Updated relayd/httpd config files to be on par with nginx
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
replaced depracated flags and functions, renamed service to fit other service files
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Updated Postgrex library to 0.20.0
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix federation issue where Public visibility information in cc field was lost when sent to remote servers, causing posts to appear with inconsistent visibility across instances
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Improved the logic of how we determine if a server is unreachable.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Relax alsoKnownAs requirements to just URI, not necessarily HTTP(S)
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix release builds
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Change scrobble external link param name to use snake case
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add `base_urls` to the /api/v1/instance pleroma metadata which provides information about the base URLs for media_proxy and uploads when configured
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Change SMTP example to use the Mua adapter that works with OTP>25
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Updated Tesla to 1.15.3
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Backport [Elixir PR 14242](https://github.com/elixir-lang/elixir/pull/14242) fixing racy mkdir and lack of error handling of parent directory creation
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Allow Terms of Service panel behaviour to be configurable
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Support translation providers (DeepL, LibreTranslate)
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Truncate the length of Rich Media title and description fields
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix HTTP client making invalid requests due to no percent encoding processing or validation.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Enforce an exact domain match for WebFinger resolution
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Don't require an Accept header for WebFinger queries and default to JSON.
|
|
||||||
|
|
@ -362,7 +362,9 @@ config :pleroma, :activitypub,
|
||||||
note_replies_output_limit: 5,
|
note_replies_output_limit: 5,
|
||||||
sign_object_fetches: true,
|
sign_object_fetches: true,
|
||||||
authorized_fetch_mode: false,
|
authorized_fetch_mode: false,
|
||||||
client_api_enabled: false
|
client_api_enabled: false,
|
||||||
|
anonymize_reporter: false,
|
||||||
|
anonymize_reporter_local_nickname: ""
|
||||||
|
|
||||||
config :pleroma, :streamer,
|
config :pleroma, :streamer,
|
||||||
workers: 3,
|
workers: 3,
|
||||||
|
|
@ -613,7 +615,7 @@ config :pleroma, Oban,
|
||||||
search_indexing: [limit: 10, paused: true],
|
search_indexing: [limit: 10, paused: true],
|
||||||
slow: 5
|
slow: 5
|
||||||
],
|
],
|
||||||
plugins: [{Oban.Plugins.Pruner, max_age: 900}],
|
plugins: [Oban.Plugins.Lazarus, {Oban.Plugins.Pruner, max_age: 900}],
|
||||||
crontab: [
|
crontab: [
|
||||||
{"0 0 * * 0", Pleroma.Workers.Cron.DigestEmailsWorker},
|
{"0 0 * * 0", Pleroma.Workers.Cron.DigestEmailsWorker},
|
||||||
{"0 0 * * *", Pleroma.Workers.Cron.NewUsersDigestWorker},
|
{"0 0 * * *", Pleroma.Workers.Cron.NewUsersDigestWorker},
|
||||||
|
|
|
||||||
|
|
@ -1797,6 +1797,23 @@ config :pleroma, :config_description, [
|
||||||
key: :client_api_enabled,
|
key: :client_api_enabled,
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Allow client to server ActivityPub interactions"
|
description: "Allow client to server ActivityPub interactions"
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :anonymize_reporter,
|
||||||
|
type: :boolean,
|
||||||
|
label: "Anonymize local reports",
|
||||||
|
description:
|
||||||
|
"If true, replace local reporters with the designated local user for the copy to be sent to remote servers"
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :anonymize_reporter_local_nickname,
|
||||||
|
type: :string,
|
||||||
|
label: "Anonymized reporter",
|
||||||
|
description:
|
||||||
|
"The nickname of the designated local user that replaces the actual reporter in the copy to be sent to remote servers",
|
||||||
|
suggestions: [
|
||||||
|
"lain"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -2114,6 +2131,11 @@ config :pleroma, :config_description, [
|
||||||
description:
|
description:
|
||||||
"Amount of milliseconds after which the HTTP request is forcibly terminated.",
|
"Amount of milliseconds after which the HTTP request is forcibly terminated.",
|
||||||
suggestions: [5_000]
|
suggestions: [5_000]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :user_agent,
|
||||||
|
type: :string,
|
||||||
|
description: "Custom User-Agent header to be used when fetching rich media content."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -3311,6 +3333,12 @@ config :pleroma, :config_description, [
|
||||||
description:
|
description:
|
||||||
"A map containing available frontends and parameters for their installation.",
|
"A map containing available frontends and parameters for their installation.",
|
||||||
children: frontend_options
|
children: frontend_options
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :pickable,
|
||||||
|
type: {:list, :string},
|
||||||
|
description:
|
||||||
|
"A list containing all frontends users can pick as their preference, format is :name/:ref, e.g pleroma-fe/stable."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -3517,9 +3545,7 @@ config :pleroma, :config_description, [
|
||||||
%{
|
%{
|
||||||
key: :provider,
|
key: :provider,
|
||||||
type: :module,
|
type: :module,
|
||||||
suggestions: [
|
suggestions: {:list_behaviour_implementations, Pleroma.Language.LanguageDetector.Provider}
|
||||||
Pleroma.Language.LanguageDetector.Fasttext
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
group: {:subgroup, Pleroma.Language.LanguageDetector.Fasttext},
|
group: {:subgroup, Pleroma.Language.LanguageDetector.Fasttext},
|
||||||
|
|
@ -3539,10 +3565,7 @@ config :pleroma, :config_description, [
|
||||||
%{
|
%{
|
||||||
key: :provider,
|
key: :provider,
|
||||||
type: :module,
|
type: :module,
|
||||||
suggestions: [
|
suggestions: {:list_behaviour_implementations, Pleroma.Language.Translation.Provider}
|
||||||
Pleroma.Language.Translation.Deepl,
|
|
||||||
Pleroma.Language.Translation.Libretranslate
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
group: {:subgroup, Pleroma.Language.Translation.Deepl},
|
group: {:subgroup, Pleroma.Language.Translation.Deepl},
|
||||||
|
|
@ -3571,6 +3594,27 @@ config :pleroma, :config_description, [
|
||||||
label: "LibreTranslate API Key",
|
label: "LibreTranslate API Key",
|
||||||
type: :string,
|
type: :string,
|
||||||
suggestions: ["YOUR_API_KEY"]
|
suggestions: ["YOUR_API_KEY"]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
group: {:subgroup, Pleroma.Language.Translation.TranslateLocally},
|
||||||
|
key: :intermediary_language,
|
||||||
|
label:
|
||||||
|
"translateLocally intermediary language (used when direct source->target model is not available)",
|
||||||
|
type: :string,
|
||||||
|
suggestions: ["en"]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
group: {:subgroup, Pleroma.Language.Translation.Mozhi},
|
||||||
|
key: :base_url,
|
||||||
|
label: "Mozhi instance URL",
|
||||||
|
type: :string
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
group: {:subgroup, Pleroma.Language.Translation.Mozhi},
|
||||||
|
key: :engine,
|
||||||
|
label: "Engine used for Mozhi",
|
||||||
|
type: :string,
|
||||||
|
suggestions: ["libretranslate"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,10 @@ config :pleroma, Pleroma.Upload.Filter.Mogrify, config_impl: Pleroma.StaticStubb
|
||||||
config :pleroma, Pleroma.Upload.Filter.Mogrify, mogrify_impl: Pleroma.MogrifyMock
|
config :pleroma, Pleroma.Upload.Filter.Mogrify, mogrify_impl: Pleroma.MogrifyMock
|
||||||
|
|
||||||
config :pleroma, Pleroma.Signature, http_signatures_impl: Pleroma.StubbedHTTPSignaturesMock
|
config :pleroma, Pleroma.Signature, http_signatures_impl: Pleroma.StubbedHTTPSignaturesMock
|
||||||
|
config :pleroma, Pleroma.Web.ActivityPub.Publisher, signature_impl: Pleroma.SignatureMock
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Web.ActivityPub.Publisher,
|
||||||
|
transmogrifier_impl: Pleroma.Web.ActivityPub.TransmogrifierMock
|
||||||
|
|
||||||
peer_module =
|
peer_module =
|
||||||
if String.to_integer(System.otp_release()) >= 25 do
|
if String.to_integer(System.otp_release()) >= 25 do
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ Feel free to contact us to be added to this list!
|
||||||
### AndStatus
|
### AndStatus
|
||||||
- Homepage: <http://andstatus.org/>
|
- Homepage: <http://andstatus.org/>
|
||||||
- Source Code: <https://github.com/andstatus/andstatus/>
|
- Source Code: <https://github.com/andstatus/andstatus/>
|
||||||
|
- Contact: [@AndStatus@mastodon.social](https://mastodon.social/@AndStatus)
|
||||||
- Platforms: Android
|
- Platforms: Android
|
||||||
- Features: MastoAPI, ActivityPub (Client-to-Server)
|
- Features: MastoAPI, ActivityPub (Client-to-Server)
|
||||||
|
|
||||||
|
|
@ -40,8 +41,8 @@ Feel free to contact us to be added to this list!
|
||||||
|
|
||||||
### Fedilab
|
### Fedilab
|
||||||
- Homepage: <https://fedilab.app/>
|
- Homepage: <https://fedilab.app/>
|
||||||
- Source Code: <https://framagit.org/tom79/fedilab/>
|
- Source Code: <https://codeberg.org/tom79/Fedilab>
|
||||||
- Contact: [@fedilab@framapiaf.org](https://framapiaf.org/users/fedilab)
|
- Contact: [@apps@toot.fedilab.app](https://toot.fedilab.app/@apps)
|
||||||
- Platforms: Android
|
- Platforms: Android
|
||||||
- Features: MastoAPI, Streaming Ready, Moderation, Text Formatting
|
- Features: MastoAPI, Streaming Ready, Moderation, Text Formatting
|
||||||
|
|
||||||
|
|
@ -51,8 +52,8 @@ Feel free to contact us to be added to this list!
|
||||||
- Features: MastoAPI, No Streaming
|
- Features: MastoAPI, No Streaming
|
||||||
|
|
||||||
### Husky
|
### Husky
|
||||||
- Source code: <https://git.mentality.rip/FWGS/Husky>
|
- Source code: <https://github.com/captainepoch/husky>
|
||||||
- Contact: [@Husky@enigmatic.observer](https://enigmatic.observer/users/Husky)
|
- Contact: [@husky@stereophonic.space](https://stereophonic.space/users/husky)
|
||||||
- Platforms: Android
|
- Platforms: Android
|
||||||
- Features: MastoAPI, No Streaming, Emoji Reactions, Text Formatting, FE Stickers
|
- Features: MastoAPI, No Streaming, Emoji Reactions, Text Formatting, FE Stickers
|
||||||
|
|
||||||
|
|
@ -65,7 +66,7 @@ Feel free to contact us to be added to this list!
|
||||||
### Tusky
|
### Tusky
|
||||||
- Homepage: <https://tuskyapp.github.io/>
|
- Homepage: <https://tuskyapp.github.io/>
|
||||||
- Source Code: <https://github.com/tuskyapp/Tusky>
|
- Source Code: <https://github.com/tuskyapp/Tusky>
|
||||||
- Contact: [@ConnyDuck@mastodon.social](https://mastodon.social/users/ConnyDuck)
|
- Contact: [@Tusky@mastodon.social](https://mastodon.social/@Tusky)
|
||||||
- Platforms: Android
|
- Platforms: Android
|
||||||
- Features: MastoAPI, No Streaming
|
- Features: MastoAPI, No Streaming
|
||||||
|
|
||||||
|
|
@ -76,10 +77,10 @@ Feel free to contact us to be added to this list!
|
||||||
- Platform: Android
|
- Platform: Android
|
||||||
- Features: MastoAPI, No Streaming
|
- Features: MastoAPI, No Streaming
|
||||||
|
|
||||||
### Indigenous
|
### IndiePass
|
||||||
- Homepage: <https://indigenous.realize.be/>
|
- Homepage: <https://indiepass.app/>
|
||||||
- Source Code: <https://github.com/swentel/indigenous-android/>
|
- Source Code: <https://github.com/IndiePass/indiepass-android>
|
||||||
- Contact: [@swentel@realize.be](https://realize.be)
|
- Contact: [@marksuth@mastodon.social](https://mastodon.social/@marksuth)
|
||||||
- Platforms: Android
|
- Platforms: Android
|
||||||
- Features: MastoAPI, No Streaming
|
- Features: MastoAPI, No Streaming
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -904,21 +904,31 @@ config :logger, :console,
|
||||||
|
|
||||||
### RUM indexing for full text search
|
### RUM indexing for full text search
|
||||||
|
|
||||||
!!! warning
|
|
||||||
It is recommended to use PostgreSQL v11 or newer. We have seen some minor issues with lower PostgreSQL versions.
|
|
||||||
|
|
||||||
* `rum_enabled`: If RUM indexes should be used. Defaults to `false`.
|
* `rum_enabled`: If RUM indexes should be used. Defaults to `false`.
|
||||||
|
|
||||||
RUM indexes are an alternative indexing scheme that is not included in PostgreSQL by default. While they may eventually be mainlined, for now they have to be installed as a PostgreSQL extension from https://github.com/postgrespro/rum.
|
RUM indexes are an alternative indexing scheme that is not included in PostgreSQL by default. While they may eventually be mainlined, for now they have to be installed as a PostgreSQL extension from [https://github.com/postgrespro/rum](https://github.com/postgrespro/rum).
|
||||||
|
|
||||||
Their advantage over the standard GIN indexes is that they allow efficient ordering of search results by timestamp, which makes search queries a lot faster on larger servers, by one or two orders of magnitude. They take up around 3 times as much space as GIN indexes.
|
Their advantage over the standard GIN indexes is that they allow efficient ordering of search results by timestamp, which makes search queries a lot faster on larger servers, by one or two orders of magnitude. They take up around 3-4 times as much space as GIN indexes.
|
||||||
|
|
||||||
To enable them, both the `rum_enabled` flag has to be set and the following special migration has to be run:
|
To enable them, both the `rum_enabled` flag has to be set and the following special migration has to be run:
|
||||||
|
|
||||||
`mix ecto.migrate --migrations-path priv/repo/optional_migrations/rum_indexing/`
|
* Source install:
|
||||||
|
- Stop Pleroma
|
||||||
|
- `mix ecto.migrate --migrations-path priv/repo/optional_migrations/rum_indexing/`
|
||||||
|
* OTP install:
|
||||||
|
- Stop Pleroma
|
||||||
|
- `pleroma_ctl migrate --migrations-path priv/repo/optional_migrations/rum_indexing/`
|
||||||
|
|
||||||
This will probably take a long time.
|
This will probably take a long time.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
It is recommended to `VACUUM FULL` the objects table after the migration has completed, to do that run:
|
||||||
|
```
|
||||||
|
# sudo -Hu postgres vacuumdb --full --analyze -t objects <pleroma DB name>
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can start Pleroma back up.
|
||||||
|
|
||||||
## Alternative client protocols
|
## Alternative client protocols
|
||||||
|
|
||||||
### BBS / SSH access
|
### BBS / SSH access
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,9 @@ location /proxy {
|
||||||
```
|
```
|
||||||
Also add the following on top of the configuration, outside of the `server` block:
|
Also add the following on top of the configuration, outside of the `server` block:
|
||||||
```
|
```
|
||||||
proxy_cache_path /tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g inactive=720m use_temp_path=off;
|
# Note: The cache directory must exist and be writable by nginx.
|
||||||
|
# If nginx runs in a chroot, create it inside the chroot.
|
||||||
|
proxy_cache_path /var/tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g inactive=720m use_temp_path=off;
|
||||||
```
|
```
|
||||||
If you came here from one of the installation guides, take a look at the example configuration `/installation/pleroma.nginx`, where this part is already included.
|
If you came here from one of the installation guides, take a look at the example configuration `/installation/pleroma.nginx`, where this part is already included.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,9 +66,9 @@ Returned data:
|
||||||
"username": "somenick",
|
"username": "somenick",
|
||||||
...
|
...
|
||||||
},
|
},
|
||||||
"id" : "1",
|
"id": "1",
|
||||||
"unread" : 2,
|
"unread": 2,
|
||||||
"last_message" : {...}, // The last message in that chat
|
"last_message": {...}, // The last message in that chat
|
||||||
"updated_at": "2020-04-21T15:11:46.000Z"
|
"updated_at": "2020-04-21T15:11:46.000Z"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -93,8 +93,8 @@ Returned data:
|
||||||
"username": "somenick",
|
"username": "somenick",
|
||||||
...
|
...
|
||||||
},
|
},
|
||||||
"id" : "1",
|
"id": "1",
|
||||||
"unread" : 0,
|
"unread": 0,
|
||||||
"updated_at": "2020-04-21T15:11:46.000Z"
|
"updated_at": "2020-04-21T15:11:46.000Z"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -111,7 +111,7 @@ The modified chat message
|
||||||
|
|
||||||
### Getting a list of Chats
|
### Getting a list of Chats
|
||||||
|
|
||||||
`GET /api/v1/pleroma/chats`
|
`GET /api/v2/pleroma/chats`
|
||||||
|
|
||||||
This will return a list of chats that you have been involved in, sorted by their
|
This will return a list of chats that you have been involved in, sorted by their
|
||||||
last update (so new chats will be at the top).
|
last update (so new chats will be at the top).
|
||||||
|
|
@ -119,6 +119,7 @@ last update (so new chats will be at the top).
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
- with_muted: Include chats from muted users (boolean).
|
- with_muted: Include chats from muted users (boolean).
|
||||||
|
- pinned: Include only pinned chats (boolean).
|
||||||
|
|
||||||
Returned data:
|
Returned data:
|
||||||
|
|
||||||
|
|
@ -130,16 +131,16 @@ Returned data:
|
||||||
"username": "somenick",
|
"username": "somenick",
|
||||||
...
|
...
|
||||||
},
|
},
|
||||||
"id" : "1",
|
"id": "1",
|
||||||
"unread" : 2,
|
"unread": 2,
|
||||||
"last_message" : {...}, // The last message in that chat
|
"last_message": {...}, // The last message in that chat
|
||||||
"updated_at": "2020-04-21T15:11:46.000Z"
|
"updated_at": "2020-04-21T15:11:46.000Z"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
The recipient of messages that are sent to this chat is given by their AP ID.
|
The recipient of messages that are sent to this chat is given by their AP ID.
|
||||||
No pagination is implemented for now.
|
The usual pagination options are implemented.
|
||||||
|
|
||||||
### Getting the messages for a Chat
|
### Getting the messages for a Chat
|
||||||
|
|
||||||
|
|
@ -226,6 +227,32 @@ Deleting a chat message for given Chat id works like this:
|
||||||
|
|
||||||
Returned data is the deleted message.
|
Returned data is the deleted message.
|
||||||
|
|
||||||
|
### Pinning a chat
|
||||||
|
|
||||||
|
Pinning a chat works like this:
|
||||||
|
|
||||||
|
`POST /api/v1/pleroma/chats/:id/pin`
|
||||||
|
|
||||||
|
Returned data:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"id": "someflakeid",
|
||||||
|
"username": "somenick",
|
||||||
|
...
|
||||||
|
},
|
||||||
|
"id": "1",
|
||||||
|
"unread": 0,
|
||||||
|
"updated_at": "2020-04-21T15:11:46.000Z",
|
||||||
|
"pinned": true,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To unpin a pinned chat, use:
|
||||||
|
|
||||||
|
`POST /api/v1/pleroma/chats/:id/unpin`
|
||||||
|
|
||||||
### Notifications
|
### Notifications
|
||||||
|
|
||||||
There's a new `pleroma:chat_mention` notification, which has this form. It is not given out in the notifications endpoint by default, you need to explicitly request it with `include_types[]=pleroma:chat_mention`:
|
There's a new `pleroma:chat_mention` notification, which has this form. It is not given out in the notifications endpoint by default, you need to explicitly request it with `include_types[]=pleroma:chat_mention`:
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,13 @@ Has these additional fields under the `pleroma` object:
|
||||||
- `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 1, me: true}`. Contains no information about the reacting users, for that use the `/statuses/:id/reactions` endpoint.
|
- `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 1, me: true}`. Contains no information about the reacting users, for that use the `/statuses/:id/reactions` endpoint.
|
||||||
- `parent_visible`: If the parent of this post is visible to the user or not.
|
- `parent_visible`: If the parent of this post is visible to the user or not.
|
||||||
- `pinned_at`: a datetime (iso8601) when status was pinned, `null` otherwise.
|
- `pinned_at`: a datetime (iso8601) when status was pinned, `null` otherwise.
|
||||||
- `quotes_count`: the count of status quotes.
|
|
||||||
- `non_anonymous`: true if the source post specifies the poll results are not anonymous. Currently only implemented by Smithereen.
|
|
||||||
- `bookmark_folder`: the ID of the folder bookmark is stored within (if any).
|
- `bookmark_folder`: the ID of the folder bookmark is stored within (if any).
|
||||||
- `list_id`: the ID of the list the post is addressed to (if any, only returned to author).
|
- `list_id`: the ID of the list the post is addressed to (if any, only returned to author).
|
||||||
|
|
||||||
|
Has these additional fields under the `poll.pleroma` object:
|
||||||
|
|
||||||
|
- `non_anonymous`: true if the source post specifies the poll results are not anonymous. Currently only implemented by Smithereen.
|
||||||
|
|
||||||
The `GET /api/v1/statuses/:id/source` endpoint additionally has the following attributes:
|
The `GET /api/v1/statuses/:id/source` endpoint additionally has the following attributes:
|
||||||
|
|
||||||
- `content_type`: The content type of the status source.
|
- `content_type`: The content type of the status source.
|
||||||
|
|
@ -88,6 +90,7 @@ The `id` parameter can also be the `nickname` of the user. This only works in th
|
||||||
- `only_media`: include only statuses with media attached
|
- `only_media`: include only statuses with media attached
|
||||||
- `with_muted`: include statuses/reactions from muted accounts
|
- `with_muted`: include statuses/reactions from muted accounts
|
||||||
- `exclude_reblogs`: exclude reblogs
|
- `exclude_reblogs`: exclude reblogs
|
||||||
|
- `only_reblogs`: include only reblogs
|
||||||
- `exclude_replies`: exclude replies
|
- `exclude_replies`: exclude replies
|
||||||
- `exclude_visibilities`: exclude visibilities
|
- `exclude_visibilities`: exclude visibilities
|
||||||
|
|
||||||
|
|
@ -97,6 +100,9 @@ Endpoints which accept `with_relationships` parameter:
|
||||||
- `/api/v1/accounts/:id/followers`
|
- `/api/v1/accounts/:id/followers`
|
||||||
- `/api/v1/accounts/:id/following`
|
- `/api/v1/accounts/:id/following`
|
||||||
- `/api/v1/mutes`
|
- `/api/v1/mutes`
|
||||||
|
- `/api/v1/blocks`
|
||||||
|
- `/api/v1/search`
|
||||||
|
- `/api/v2/search`
|
||||||
|
|
||||||
Has these additional fields under the `pleroma` object:
|
Has these additional fields under the `pleroma` object:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -684,6 +684,7 @@ Audio scrobbling in Pleroma is **deprecated**.
|
||||||
### Creates a new Listen activity for an account
|
### Creates a new Listen activity for an account
|
||||||
* Method `POST`
|
* Method `POST`
|
||||||
* Authentication: required
|
* Authentication: required
|
||||||
|
* OAuth scope: `write:scrobbles`
|
||||||
* Params:
|
* Params:
|
||||||
* `title`: the title of the media playing
|
* `title`: the title of the media playing
|
||||||
* `album`: the album of the media playing [optional]
|
* `album`: the album of the media playing [optional]
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ Note: This article is potentially outdated because at this time we may not have
|
||||||
|
|
||||||
- PostgreSQL 11.0以上 (Ubuntu16.04では9.5しか提供されていないので,[](https://www.postgresql.org/download/linux/ubuntu/)こちらから新しいバージョンを入手してください)
|
- PostgreSQL 11.0以上 (Ubuntu16.04では9.5しか提供されていないので,[](https://www.postgresql.org/download/linux/ubuntu/)こちらから新しいバージョンを入手してください)
|
||||||
- `postgresql-contrib` 11.0以上 (同上)
|
- `postgresql-contrib` 11.0以上 (同上)
|
||||||
- Elixir 1.14 以上 ([Debianのリポジトリからインストールしないこと!!! ここからインストールすること!](https://elixir-lang.org/install.html#unix-and-unix-like)。または [asdf](https://github.com/asdf-vm/asdf) をpleromaユーザーでインストールしてください)
|
- Elixir 1.15 以上 ([Debianのリポジトリからインストールしないこと!!! ここからインストールすること!](https://elixir-lang.org/install.html#unix-and-unix-like)。または [asdf](https://github.com/asdf-vm/asdf) をpleromaユーザーでインストールしてください)
|
||||||
- `erlang-dev`
|
- `erlang-dev`
|
||||||
- `erlang-nox`
|
- `erlang-nox`
|
||||||
- `git`
|
- `git`
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
## Required dependencies
|
## Required dependencies
|
||||||
|
|
||||||
* PostgreSQL >=11.0
|
* PostgreSQL >=11.0
|
||||||
* Elixir >=1.14.0 <1.19
|
* Elixir >=1.15.0 <1.19
|
||||||
* Erlang OTP >=23.0.0 (supported: <28)
|
* Erlang OTP >=23.0.0 (supported: <28)
|
||||||
* git
|
* git
|
||||||
* file / libmagic
|
* file / libmagic
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ Note: the packages are not required with the current default settings of Pleroma
|
||||||
|
|
||||||
It is required for the following Pleroma features:
|
It is required for the following Pleroma 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: `Pleroma.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`)
|
||||||
|
|
||||||
## `ffmpeg`
|
## `ffmpeg`
|
||||||
|
|
@ -33,5 +33,5 @@ It is required for the following Pleroma features:
|
||||||
|
|
||||||
It is required for the following Pleroma features:
|
It is required for the following Pleroma features:
|
||||||
|
|
||||||
* `Pleroma.Upload.Filters.Exiftool.StripLocation` upload filter (related config: `Plaroma.Upload/filters` in `config/config.exs`)
|
* `Pleroma.Upload.Filters.Exiftool.StripLocation` upload filter (related config: `Pleroma.Upload/filters` in `config/config.exs`)
|
||||||
* `Pleroma.Upload.Filters.Exiftool.ReadDescription` upload filter (related config: `Plaroma.Upload/filters` in `config/config.exs`)
|
* `Pleroma.Upload.Filters.Exiftool.ReadDescription` upload filter (related config: `Pleroma.Upload/filters` in `config/config.exs`)
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,6 @@ http protocol pleroma { # Protocol for upstream Pleroma server
|
||||||
|
|
||||||
relay wwwtls {
|
relay wwwtls {
|
||||||
listen on $ext_inet port https tls # Comment to disable listening on IPv4
|
listen on $ext_inet port https tls # Comment to disable listening on IPv4
|
||||||
#listen on $ext_inet6 port https tls # Comment to disable listening on IPv6
|
|
||||||
|
|
||||||
protocol pleroma
|
protocol pleroma
|
||||||
|
|
||||||
|
|
@ -66,3 +65,16 @@ relay wwwtls {
|
||||||
# Example:
|
# Example:
|
||||||
#forward to <httpd_server> port 8080
|
#forward to <httpd_server> port 8080
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Uncomment relay block to enable IPv6
|
||||||
|
#relay wwwtls6 {
|
||||||
|
# listen on $ext_inet6 port https tls
|
||||||
|
|
||||||
|
# protocol pleroma
|
||||||
|
|
||||||
|
# forward to <pleroma_server> port 4000 check tcp timeout 500 # Adjust timeout accordingly when relayd returns 502 while Pleroma is running without problems.
|
||||||
|
|
||||||
|
# # When serving multiple services, add the forwards here.
|
||||||
|
# # Example:
|
||||||
|
# #forward to <httpd_server> port 8080
|
||||||
|
#}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@
|
||||||
# 3. Copy this file to /etc/nginx/sites-available/ and then add a symlink to it
|
# 3. Copy this file to /etc/nginx/sites-available/ and then add a symlink to it
|
||||||
# in /etc/nginx/sites-enabled/ and run 'nginx -s reload' or restart nginx.
|
# in /etc/nginx/sites-enabled/ and run 'nginx -s reload' or restart nginx.
|
||||||
|
|
||||||
proxy_cache_path /tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g
|
# Note: The cache directory must exist and be writable by nginx.
|
||||||
|
# If nginx runs in a chroot, create it inside the chroot.
|
||||||
|
proxy_cache_path /var/tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g
|
||||||
inactive=720m use_temp_path=off;
|
inactive=720m use_temp_path=off;
|
||||||
|
|
||||||
# this is explicitly IPv4 since Pleroma.Web.Endpoint binds on IPv4 only
|
# this is explicitly IPv4 since Pleroma.Web.Endpoint binds on IPv4 only
|
||||||
|
|
@ -41,8 +43,21 @@ ssl_session_cache shared:ssl_session_cache:10m;
|
||||||
server {
|
server {
|
||||||
server_name example.tld;
|
server_name example.tld;
|
||||||
|
|
||||||
listen 443 ssl http2;
|
listen 443 ssl;
|
||||||
listen [::]:443 ssl http2;
|
listen [::]:443 ssl;
|
||||||
|
http2 on;
|
||||||
|
|
||||||
|
# Optional HTTP/3 support
|
||||||
|
# Note: requires you open UDP port 443
|
||||||
|
#
|
||||||
|
# listen 443 quic reuseport;
|
||||||
|
# listen [::]:443 quic reuseport;
|
||||||
|
# http3 on;
|
||||||
|
# quic_retry on;
|
||||||
|
# ssl_early_data on;
|
||||||
|
# quic_gso on;
|
||||||
|
# add_header Alt-Svc 'h3=":443"; ma=86400';
|
||||||
|
|
||||||
ssl_session_timeout 1d;
|
ssl_session_timeout 1d;
|
||||||
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
|
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
|
||||||
ssl_session_tickets off;
|
ssl_session_tickets off;
|
||||||
|
|
@ -67,8 +82,14 @@ server {
|
||||||
gzip_http_version 1.1;
|
gzip_http_version 1.1;
|
||||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/activity+json application/atom+xml;
|
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/activity+json application/atom+xml;
|
||||||
|
|
||||||
# the nginx default is 1m, not enough for large media uploads
|
# Nginx media upload limitation
|
||||||
|
# Ensure that this value matches or exceeds your Pleroma upload limit:
|
||||||
|
#
|
||||||
|
# config :pleroma, :instance,
|
||||||
|
# upload_limit: 16_000_000
|
||||||
|
#
|
||||||
client_max_body_size 16m;
|
client_max_body_size 16m;
|
||||||
|
|
||||||
ignore_invalid_headers off;
|
ignore_invalid_headers off;
|
||||||
|
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
|
|
@ -94,7 +115,9 @@ server {
|
||||||
# proxy_pass http://phoenix/notice/$1;
|
# proxy_pass http://phoenix/notice/$1;
|
||||||
# }
|
# }
|
||||||
|
|
||||||
location ~ ^/(media|proxy) {
|
# Remove this location if you choose to use a dedicated subdomain
|
||||||
|
# for mediaproxy
|
||||||
|
location /proxy {
|
||||||
proxy_cache pleroma_media_cache;
|
proxy_cache pleroma_media_cache;
|
||||||
slice 1m;
|
slice 1m;
|
||||||
proxy_cache_key $host$uri$is_args$args$slice_range;
|
proxy_cache_key $host$uri$is_args$args$slice_range;
|
||||||
|
|
@ -106,4 +129,95 @@ server {
|
||||||
chunked_transfer_encoding on;
|
chunked_transfer_encoding on;
|
||||||
proxy_pass http://phoenix;
|
proxy_pass http://phoenix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Nginx can serve the local file uploads directly reducing work for
|
||||||
|
# the backend. Make sure to change this to a "deny all" if you use
|
||||||
|
# a dedicated subdomain. It will break access to uploads that have already
|
||||||
|
# federated if you are converting an existing installation, so weigh the risks
|
||||||
|
# carefully.
|
||||||
|
#
|
||||||
|
# location /media/ {
|
||||||
|
# alias /var/lib/pleroma/uploads/; # <-- make sure this is correct for your deployment
|
||||||
|
# allow all;
|
||||||
|
# add_header X-Content-Type-Options "nosniff";
|
||||||
|
# add_header Content-Security-Policy "sandbox";
|
||||||
|
# }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# It is strongly recommended that you host your media and the mediaproxy on a dedicated subdomain for security reasons.
|
||||||
|
# The following Pleroma settings will be required to enable this capability:
|
||||||
|
#
|
||||||
|
# config :pleroma, :media_proxy,
|
||||||
|
# base_url: "https://media.example.tld/"
|
||||||
|
#
|
||||||
|
# # Assuming default media upload deployment (e.g., not S3 which will require a different domain anyway) --
|
||||||
|
# config :pleroma, Pleroma.Upload,
|
||||||
|
# base_url: "https://media.example.tld/media/",
|
||||||
|
#
|
||||||
|
# config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads"
|
||||||
|
#
|
||||||
|
# And then uncomment and configure the following server.
|
||||||
|
# Make sure your certificate was issued to support both domains or use a dedicated certificate:
|
||||||
|
#
|
||||||
|
# server {
|
||||||
|
# server_name media.example.tld;
|
||||||
|
#
|
||||||
|
# listen 443 ssl;
|
||||||
|
# listen [::]:443 ssl;
|
||||||
|
# http2 on;
|
||||||
|
#
|
||||||
|
# # Optional HTTP/3 support
|
||||||
|
# # Note: requires you open UDP port 443
|
||||||
|
# #
|
||||||
|
# # listen 443 quic reuseport;
|
||||||
|
# # listen [::]:443 quic reuseport;
|
||||||
|
# # http3 on;
|
||||||
|
# # quic_retry on;
|
||||||
|
# # ssl_early_data on;
|
||||||
|
# # quic_gso on;
|
||||||
|
# # add_header Alt-Svc 'h3=":443"; ma=86400';
|
||||||
|
#
|
||||||
|
# ssl_session_timeout 1d;
|
||||||
|
# ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
|
||||||
|
# ssl_session_tickets off;
|
||||||
|
#
|
||||||
|
# ssl_trusted_certificate /etc/letsencrypt/live/example.tld/chain.pem;
|
||||||
|
# ssl_certificate /etc/letsencrypt/live/example.tld/fullchain.pem;
|
||||||
|
# ssl_certificate_key /etc/letsencrypt/live/example.tld/privkey.pem;
|
||||||
|
#
|
||||||
|
# ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
# ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
|
||||||
|
# ssl_prefer_server_ciphers off;
|
||||||
|
# # In case of an old server with an OpenSSL version of 1.0.2 or below,
|
||||||
|
# # leave only prime256v1 or comment out the following line.
|
||||||
|
# ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1;
|
||||||
|
# ssl_stapling on;
|
||||||
|
# ssl_stapling_verify on;
|
||||||
|
#
|
||||||
|
# proxy_http_version 1.1;
|
||||||
|
# proxy_set_header Upgrade $http_upgrade;
|
||||||
|
# proxy_set_header Connection "upgrade";
|
||||||
|
# proxy_set_header Host $http_host;
|
||||||
|
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
#
|
||||||
|
# location /media/ { # <-- make sure this path matches your Pleroma.Upload :base_url
|
||||||
|
# alias /var/lib/pleroma/uploads/; # <-- make sure this is correct for your deployment
|
||||||
|
# allow all;
|
||||||
|
# add_header X-Content-Type-Options "nosniff";
|
||||||
|
# add_header Content-Security-Policy "sandbox";
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# location /proxy {
|
||||||
|
# proxy_cache pleroma_media_cache;
|
||||||
|
# slice 1m;
|
||||||
|
# proxy_cache_key $host$uri$is_args$args$slice_range;
|
||||||
|
# proxy_set_header Range $slice_range;
|
||||||
|
# proxy_cache_valid 200 206 301 304 1h;
|
||||||
|
# proxy_cache_lock on;
|
||||||
|
# proxy_ignore_client_abort on;
|
||||||
|
# proxy_buffering on;
|
||||||
|
# chunked_transfer_encoding on;
|
||||||
|
# proxy_pass http://phoenix;
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ defmodule Pleroma.Activity.Queries do
|
||||||
Contains queries for Activity.
|
Contains queries for Activity.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import Ecto.Query, only: [from: 2, where: 3]
|
import Ecto.Query, only: [from: 2]
|
||||||
|
|
||||||
@type query :: Ecto.Queryable.t() | Pleroma.Activity.t()
|
@type query :: Ecto.Queryable.t() | Pleroma.Activity.t()
|
||||||
|
|
||||||
|
|
@ -70,22 +70,6 @@ defmodule Pleroma.Activity.Queries do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec by_object_in_reply_to_id(query, String.t(), keyword()) :: query
|
|
||||||
def by_object_in_reply_to_id(query, in_reply_to_id, opts \\ []) do
|
|
||||||
query =
|
|
||||||
if opts[:skip_preloading] do
|
|
||||||
Activity.with_joined_object(query)
|
|
||||||
else
|
|
||||||
Activity.with_preloaded_object(query)
|
|
||||||
end
|
|
||||||
|
|
||||||
where(
|
|
||||||
query,
|
|
||||||
[activity, object: o],
|
|
||||||
fragment("(?)->>'inReplyTo' = ?", o.data, ^to_string(in_reply_to_id))
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
@spec by_type(query, String.t()) :: query
|
@spec by_type(query, String.t()) :: query
|
||||||
def by_type(query \\ Activity, activity_type) do
|
def by_type(query \\ Activity, activity_type) do
|
||||||
from(
|
from(
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ defmodule Pleroma.Chat do
|
||||||
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
|
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
|
||||||
field(:recipient, :string)
|
field(:recipient, :string)
|
||||||
|
|
||||||
|
field(:pinned, :boolean)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -94,4 +96,16 @@ defmodule Pleroma.Chat do
|
||||||
order_by: [desc: c.updated_at]
|
order_by: [desc: c.updated_at]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pin(%__MODULE__{} = chat) do
|
||||||
|
chat
|
||||||
|
|> cast(%{pinned: true}, [:pinned])
|
||||||
|
|> Repo.update()
|
||||||
|
end
|
||||||
|
|
||||||
|
def unpin(%__MODULE__{} = chat) do
|
||||||
|
chat
|
||||||
|
|> cast(%{pinned: false}, [:pinned])
|
||||||
|
|> Repo.update()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,8 @@ defmodule Pleroma.Constants do
|
||||||
"pleroma_internal",
|
"pleroma_internal",
|
||||||
"generator",
|
"generator",
|
||||||
"rules",
|
"rules",
|
||||||
"language"
|
"language",
|
||||||
|
"voters"
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,16 @@ defmodule Pleroma.FollowingRelationship do
|
||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_outgoing_follow_requests(%User{id: id}) do
|
||||||
|
__MODULE__
|
||||||
|
|> join(:inner, [r], f in assoc(r, :following))
|
||||||
|
|> where([r], r.state == ^:follow_pending)
|
||||||
|
|> where([r], r.follower_id == ^id)
|
||||||
|
|> where([r, f], f.is_active == true)
|
||||||
|
|> select([r, f], f)
|
||||||
|
|> Repo.all()
|
||||||
|
end
|
||||||
|
|
||||||
def following?(%User{id: follower_id}, %User{id: followed_id}) do
|
def following?(%User{id: follower_id}, %User{id: followed_id}) do
|
||||||
__MODULE__
|
__MODULE__
|
||||||
|> where(follower_id: ^follower_id, following_id: ^followed_id, state: ^:follow_accept)
|
|> where(follower_id: ^follower_id, following_id: ^followed_id, state: ^:follow_accept)
|
||||||
|
|
|
||||||
|
|
@ -131,31 +131,4 @@ defmodule Pleroma.HTTP do
|
||||||
|
|
||||||
defp default_middleware,
|
defp default_middleware,
|
||||||
do: [Tesla.Middleware.FollowRedirects, Pleroma.Tesla.Middleware.EncodeUrl]
|
do: [Tesla.Middleware.FollowRedirects, Pleroma.Tesla.Middleware.EncodeUrl]
|
||||||
|
|
||||||
def encode_url(url) when is_binary(url) do
|
|
||||||
URI.parse(url)
|
|
||||||
|> then(fn parsed ->
|
|
||||||
path = encode_path(parsed.path)
|
|
||||||
query = encode_query(parsed.query)
|
|
||||||
|
|
||||||
%{parsed | path: path, query: query}
|
|
||||||
end)
|
|
||||||
|> URI.to_string()
|
|
||||||
end
|
|
||||||
|
|
||||||
defp encode_path(nil), do: nil
|
|
||||||
|
|
||||||
defp encode_path(path) when is_binary(path) do
|
|
||||||
path
|
|
||||||
|> URI.decode()
|
|
||||||
|> URI.encode()
|
|
||||||
end
|
|
||||||
|
|
||||||
defp encode_query(nil), do: nil
|
|
||||||
|
|
||||||
defp encode_query(query) when is_binary(query) do
|
|
||||||
query
|
|
||||||
|> URI.decode_query()
|
|
||||||
|> URI.encode_query()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,12 @@ defmodule Pleroma.HTTP.AdapterHelper.Hackney do
|
||||||
|
|
||||||
config_opts = Pleroma.Config.get([:http, :adapter], [])
|
config_opts = Pleroma.Config.get([:http, :adapter], [])
|
||||||
|
|
||||||
|
url_encoding =
|
||||||
|
Keyword.new()
|
||||||
|
|> Keyword.put(:path_encode_fun, fn path -> path end)
|
||||||
|
|
||||||
@defaults
|
@defaults
|
||||||
|
|> Keyword.merge(url_encoding)
|
||||||
|> Keyword.merge(config_opts)
|
|> Keyword.merge(config_opts)
|
||||||
|> Keyword.merge(connection_opts)
|
|> Keyword.merge(connection_opts)
|
||||||
|> add_scheme_opts(uri)
|
|> add_scheme_opts(uri)
|
||||||
|
|
|
||||||
109
lib/pleroma/language/translation/mozhi.ex
Normal file
109
lib/pleroma/language/translation/mozhi.ex
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Language.Translation.Mozhi do
|
||||||
|
import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1]
|
||||||
|
|
||||||
|
alias Pleroma.Language.Translation.Provider
|
||||||
|
|
||||||
|
use Provider
|
||||||
|
|
||||||
|
@behaviour Provider
|
||||||
|
|
||||||
|
@name "Mozhi"
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def configured?, do: not_empty_string(base_url()) and not_empty_string(engine())
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def translate(content, source_language, target_language) do
|
||||||
|
endpoint =
|
||||||
|
base_url()
|
||||||
|
|> URI.merge("/api/translate")
|
||||||
|
|> URI.to_string()
|
||||||
|
|
||||||
|
case Pleroma.HTTP.get(
|
||||||
|
endpoint <>
|
||||||
|
"?" <>
|
||||||
|
URI.encode_query(%{
|
||||||
|
engine: engine(),
|
||||||
|
text: content,
|
||||||
|
from: source_language,
|
||||||
|
to: target_language
|
||||||
|
}),
|
||||||
|
[{"Accept", "application/json"}]
|
||||||
|
) do
|
||||||
|
{:ok, %{status: 200} = res} ->
|
||||||
|
%{
|
||||||
|
"translated-text" => content,
|
||||||
|
"source_language" => source_language
|
||||||
|
} = Jason.decode!(res.body)
|
||||||
|
|
||||||
|
{:ok,
|
||||||
|
%{
|
||||||
|
content: content,
|
||||||
|
detected_source_language: source_language,
|
||||||
|
provider: @name
|
||||||
|
}}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
{:error, :internal_server_error}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def supported_languages(type) when type in [:source, :target] do
|
||||||
|
path =
|
||||||
|
case type do
|
||||||
|
:source -> "/api/source_languages"
|
||||||
|
:target -> "/api/target_languages"
|
||||||
|
end
|
||||||
|
|
||||||
|
endpoint =
|
||||||
|
base_url()
|
||||||
|
|> URI.merge(path)
|
||||||
|
|> URI.to_string()
|
||||||
|
|
||||||
|
case Pleroma.HTTP.get(
|
||||||
|
endpoint <>
|
||||||
|
"?" <>
|
||||||
|
URI.encode_query(%{
|
||||||
|
engine: engine()
|
||||||
|
}),
|
||||||
|
[{"Accept", "application/json"}]
|
||||||
|
) do
|
||||||
|
{:ok, %{status: 200} = res} ->
|
||||||
|
languages =
|
||||||
|
Jason.decode!(res.body)
|
||||||
|
|> Enum.map(fn %{"Id" => language} -> language end)
|
||||||
|
|
||||||
|
{:ok, languages}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
{:error, :internal_server_error}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def languages_matrix do
|
||||||
|
with {:ok, source_languages} <- supported_languages(:source),
|
||||||
|
{:ok, target_languages} <- supported_languages(:target) do
|
||||||
|
{:ok,
|
||||||
|
Map.new(source_languages, fn language -> {language, target_languages -- [language]} end)}
|
||||||
|
else
|
||||||
|
{:error, error} -> {:error, error}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def name, do: @name
|
||||||
|
|
||||||
|
defp base_url do
|
||||||
|
Pleroma.Config.get([__MODULE__, :base_url])
|
||||||
|
end
|
||||||
|
|
||||||
|
defp engine do
|
||||||
|
Pleroma.Config.get([__MODULE__, :engine])
|
||||||
|
end
|
||||||
|
end
|
||||||
129
lib/pleroma/language/translation/translate_locally.ex
Normal file
129
lib/pleroma/language/translation/translate_locally.ex
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Language.Translation.TranslateLocally do
|
||||||
|
alias Pleroma.Language.Translation.Provider
|
||||||
|
|
||||||
|
use Provider
|
||||||
|
|
||||||
|
@behaviour Provider
|
||||||
|
|
||||||
|
@name "translateLocally"
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def missing_dependencies do
|
||||||
|
if Pleroma.Utils.command_available?("translateLocally") do
|
||||||
|
[]
|
||||||
|
else
|
||||||
|
["translateLocally"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def configured?, do: is_map(models())
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def translate(content, source_language, target_language) do
|
||||||
|
model =
|
||||||
|
models()
|
||||||
|
|> Map.get(source_language, %{})
|
||||||
|
|> Map.get(target_language)
|
||||||
|
|
||||||
|
models =
|
||||||
|
if model do
|
||||||
|
[model]
|
||||||
|
else
|
||||||
|
[
|
||||||
|
models()
|
||||||
|
|> Map.get(source_language, %{})
|
||||||
|
|> Map.get(intermediary_language()),
|
||||||
|
models()
|
||||||
|
|> Map.get(intermediary_language(), %{})
|
||||||
|
|> Map.get(target_language)
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
translated_content =
|
||||||
|
Enum.reduce(models, content, fn model, content ->
|
||||||
|
text_path = Path.join(System.tmp_dir!(), "translateLocally-#{Ecto.UUID.generate()}")
|
||||||
|
|
||||||
|
File.write(text_path, content)
|
||||||
|
|
||||||
|
translated_content =
|
||||||
|
case System.cmd("translateLocally", ["-m", model, "-i", text_path, "--html"]) do
|
||||||
|
{content, _} -> content
|
||||||
|
_ -> nil
|
||||||
|
end
|
||||||
|
|
||||||
|
File.rm(text_path)
|
||||||
|
|
||||||
|
translated_content
|
||||||
|
end)
|
||||||
|
|
||||||
|
{:ok,
|
||||||
|
%{
|
||||||
|
content: translated_content,
|
||||||
|
detected_source_language: source_language,
|
||||||
|
provider: @name
|
||||||
|
}}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def supported_languages(:source) do
|
||||||
|
languages =
|
||||||
|
languages_matrix()
|
||||||
|
|> elem(1)
|
||||||
|
|> Map.keys()
|
||||||
|
|
||||||
|
{:ok, languages}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def supported_languages(:target) do
|
||||||
|
languages =
|
||||||
|
languages_matrix()
|
||||||
|
|> elem(1)
|
||||||
|
|> Map.values()
|
||||||
|
|> List.flatten()
|
||||||
|
|> Enum.uniq()
|
||||||
|
|
||||||
|
{:ok, languages}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def languages_matrix do
|
||||||
|
languages =
|
||||||
|
models()
|
||||||
|
|> Map.to_list()
|
||||||
|
|> Enum.map(fn {key, value} -> {key, Map.keys(value)} end)
|
||||||
|
|> Enum.into(%{})
|
||||||
|
|
||||||
|
matrix =
|
||||||
|
if intermediary_language() do
|
||||||
|
languages
|
||||||
|
|> Map.to_list()
|
||||||
|
|> Enum.map(fn {key, value} ->
|
||||||
|
with_intermediary =
|
||||||
|
(((value ++ languages[intermediary_language()])
|
||||||
|
|> Enum.uniq()) --
|
||||||
|
[key])
|
||||||
|
|> Enum.sort()
|
||||||
|
|
||||||
|
{key, with_intermediary}
|
||||||
|
end)
|
||||||
|
|> Enum.into(%{})
|
||||||
|
else
|
||||||
|
languages
|
||||||
|
end
|
||||||
|
|
||||||
|
{:ok, matrix}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def name, do: @name
|
||||||
|
|
||||||
|
defp models, do: Pleroma.Config.get([__MODULE__, :models])
|
||||||
|
|
||||||
|
defp intermediary_language, do: Pleroma.Config.get([__MODULE__, :intermediary_language])
|
||||||
|
end
|
||||||
|
|
@ -575,6 +575,12 @@ defmodule Pleroma.ModerationLog do
|
||||||
"@#{actor_nickname} requested account backup for @#{user_nickname}"
|
"@#{actor_nickname} requested account backup for @#{user_nickname}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_log_entry_message(%ModerationLog{data: data}) do
|
||||||
|
actor_name = get_in(data, ["actor", "nickname"]) || "unknown"
|
||||||
|
action = data["action"] || "unknown"
|
||||||
|
"@#{actor_name} performed action #{action}"
|
||||||
|
end
|
||||||
|
|
||||||
defp nicknames_to_string(nicknames) do
|
defp nicknames_to_string(nicknames) do
|
||||||
nicknames
|
nicknames
|
||||||
|> Enum.map(&"@#{&1}")
|
|> Enum.map(&"@#{&1}")
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ defmodule Pleroma.Notification do
|
||||||
reblog
|
reblog
|
||||||
poll
|
poll
|
||||||
status
|
status
|
||||||
|
update
|
||||||
}
|
}
|
||||||
|
|
||||||
def changeset(%Notification{} = notification, attrs) do
|
def changeset(%Notification{} = notification, attrs) do
|
||||||
|
|
@ -281,10 +282,15 @@ defmodule Pleroma.Notification do
|
||||||
select: n.id
|
select: n.id
|
||||||
)
|
)
|
||||||
|
|
||||||
Multi.new()
|
{:ok, %{marker: marker}} =
|
||||||
|> Multi.update_all(:ids, query, set: [seen: true, updated_at: NaiveDateTime.utc_now()])
|
Multi.new()
|
||||||
|> Marker.multi_set_last_read_id(user, "notifications")
|
|> Multi.update_all(:ids, query, set: [seen: true, updated_at: NaiveDateTime.utc_now()])
|
||||||
|> Repo.transaction()
|
|> Marker.multi_set_last_read_id(user, "notifications")
|
||||||
|
|> Repo.transaction()
|
||||||
|
|
||||||
|
Streamer.stream(["user", "user:notification"], marker)
|
||||||
|
|
||||||
|
{:ok, %{marker: marker}}
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec read_one(User.t(), String.t()) ::
|
@spec read_one(User.t(), String.t()) ::
|
||||||
|
|
@ -525,9 +531,7 @@ defmodule Pleroma.Notification do
|
||||||
%Activity{data: %{"type" => "Create"}} = activity,
|
%Activity{data: %{"type" => "Create"}} = activity,
|
||||||
local_only
|
local_only
|
||||||
) do
|
) do
|
||||||
notification_enabled_ap_ids =
|
notification_enabled_ap_ids = Utils.get_notified_subscribers(activity)
|
||||||
[]
|
|
||||||
|> Utils.maybe_notify_subscribers(activity)
|
|
||||||
|
|
||||||
potential_receivers =
|
potential_receivers =
|
||||||
User.get_users_from_set(notification_enabled_ap_ids, local_only: local_only)
|
User.get_users_from_set(notification_enabled_ap_ids, local_only: local_only)
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ defmodule Pleroma.Object do
|
||||||
Logger.debug("Backtrace: #{inspect(Process.info(:erlang.self(), :current_stacktrace))}")
|
Logger.debug("Backtrace: #{inspect(Process.info(:erlang.self(), :current_stacktrace))}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def normalize(_, options \\ [fetch: false, id_only: false])
|
def normalize(_, options \\ [fetch: false])
|
||||||
|
|
||||||
# If we pass an Activity to Object.normalize(), we can try to use the preloaded object.
|
# If we pass an Activity to Object.normalize(), we can try to use the preloaded object.
|
||||||
# Use this whenever possible, especially when walking graphs in an O(N) loop!
|
# Use this whenever possible, especially when walking graphs in an O(N) loop!
|
||||||
|
|
@ -155,9 +155,6 @@ defmodule Pleroma.Object do
|
||||||
|
|
||||||
def normalize(ap_id, options) when is_binary(ap_id) do
|
def normalize(ap_id, options) when is_binary(ap_id) do
|
||||||
cond do
|
cond do
|
||||||
Keyword.get(options, :id_only) ->
|
|
||||||
ap_id
|
|
||||||
|
|
||||||
Keyword.get(options, :fetch) ->
|
Keyword.get(options, :fetch) ->
|
||||||
case Fetcher.fetch_object_from_id(ap_id, options) do
|
case Fetcher.fetch_object_from_id(ap_id, options) do
|
||||||
{:ok, object} -> object
|
{:ok, object} -> object
|
||||||
|
|
@ -401,28 +398,6 @@ defmodule Pleroma.Object do
|
||||||
String.starts_with?(id, Pleroma.Web.Endpoint.url() <> "/")
|
String.starts_with?(id, Pleroma.Web.Endpoint.url() <> "/")
|
||||||
end
|
end
|
||||||
|
|
||||||
def replies(object, opts \\ []) do
|
|
||||||
object = Object.normalize(object, fetch: false)
|
|
||||||
|
|
||||||
query =
|
|
||||||
Object
|
|
||||||
|> where(
|
|
||||||
[o],
|
|
||||||
fragment("(?)->>'inReplyTo' = ?", o.data, ^object.data["id"])
|
|
||||||
)
|
|
||||||
|> order_by([o], asc: o.id)
|
|
||||||
|
|
||||||
if opts[:self_only] do
|
|
||||||
actor = object.data["actor"]
|
|
||||||
where(query, [o], fragment("(?)->>'actor' = ?", o.data, ^actor))
|
|
||||||
else
|
|
||||||
query
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self_replies(object, opts \\ []),
|
|
||||||
do: replies(object, Keyword.put(opts, :self_only, true))
|
|
||||||
|
|
||||||
def tags(%Object{data: %{"tag" => tags}}) when is_list(tags), do: tags
|
def tags(%Object{data: %{"tag" => tags}}) when is_list(tags), do: tags
|
||||||
|
|
||||||
def tags(_), do: []
|
def tags(_), do: []
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
defmodule Pleroma.Object.Updater do
|
defmodule Pleroma.Object.Updater do
|
||||||
require Pleroma.Constants
|
require Pleroma.Constants
|
||||||
|
|
||||||
|
alias Pleroma.Maps
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
|
|
||||||
|
|
@ -115,6 +116,7 @@ defmodule Pleroma.Object.Updater do
|
||||||
# Choices are the same, but counts are different
|
# Choices are the same, but counts are different
|
||||||
to_be_updated
|
to_be_updated
|
||||||
|> Map.put(key, updated_object[key])
|
|> Map.put(key, updated_object[key])
|
||||||
|
|> Maps.put_if_present("votersCount", updated_object["votersCount"])
|
||||||
else
|
else
|
||||||
# Choices (or vote type) have changed, do not allow this
|
# Choices (or vote type) have changed, do not allow this
|
||||||
_ -> to_be_updated
|
_ -> to_be_updated
|
||||||
|
|
|
||||||
|
|
@ -95,13 +95,30 @@ defmodule Pleroma.Pagination do
|
||||||
offset: :integer,
|
offset: :integer,
|
||||||
limit: :integer,
|
limit: :integer,
|
||||||
skip_extra_order: :boolean,
|
skip_extra_order: :boolean,
|
||||||
skip_order: :boolean
|
skip_order: :boolean,
|
||||||
|
order_asc: :boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
changeset = cast({%{}, param_types}, params, Map.keys(param_types))
|
changeset = cast({%{}, param_types}, params, Map.keys(param_types))
|
||||||
changeset.changes
|
changeset.changes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp order_statement(query, table_binding, :asc) do
|
||||||
|
order_by(
|
||||||
|
query,
|
||||||
|
[{u, table_position(query, table_binding)}],
|
||||||
|
fragment("? asc nulls last", u.id)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp order_statement(query, table_binding, :desc) do
|
||||||
|
order_by(
|
||||||
|
query,
|
||||||
|
[{u, table_position(query, table_binding)}],
|
||||||
|
fragment("? desc nulls last", u.id)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
defp restrict(query, :min_id, %{min_id: min_id}, table_binding) do
|
defp restrict(query, :min_id, %{min_id: min_id}, table_binding) do
|
||||||
where(query, [{q, table_position(query, table_binding)}], q.id > ^min_id)
|
where(query, [{q, table_position(query, table_binding)}], q.id > ^min_id)
|
||||||
end
|
end
|
||||||
|
|
@ -119,19 +136,16 @@ defmodule Pleroma.Pagination do
|
||||||
defp restrict(%{order_bys: [_ | _]} = query, :order, %{skip_extra_order: true}, _), do: query
|
defp restrict(%{order_bys: [_ | _]} = query, :order, %{skip_extra_order: true}, _), do: query
|
||||||
|
|
||||||
defp restrict(query, :order, %{min_id: _}, table_binding) do
|
defp restrict(query, :order, %{min_id: _}, table_binding) do
|
||||||
order_by(
|
order_statement(query, table_binding, :asc)
|
||||||
query,
|
|
||||||
[{u, table_position(query, table_binding)}],
|
|
||||||
fragment("? asc nulls last", u.id)
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp restrict(query, :order, _options, table_binding) do
|
defp restrict(query, :order, %{max_id: _}, table_binding) do
|
||||||
order_by(
|
order_statement(query, table_binding, :desc)
|
||||||
query,
|
end
|
||||||
[{u, table_position(query, table_binding)}],
|
|
||||||
fragment("? desc nulls last", u.id)
|
defp restrict(query, :order, options, table_binding) do
|
||||||
)
|
dir = if options[:order_asc], do: :asc, else: :desc
|
||||||
|
order_statement(query, table_binding, dir)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp restrict(query, :offset, %{offset: offset}, _table_binding) do
|
defp restrict(query, :offset, %{offset: offset}, _table_binding) do
|
||||||
|
|
@ -151,11 +165,9 @@ defmodule Pleroma.Pagination do
|
||||||
|
|
||||||
defp restrict(query, _, _, _), do: query
|
defp restrict(query, _, _, _), do: query
|
||||||
|
|
||||||
defp enforce_order(result, %{min_id: _}) do
|
defp enforce_order(result, %{min_id: _, order_asc: true}), do: result
|
||||||
result
|
defp enforce_order(result, %{min_id: _}), do: Enum.reverse(result)
|
||||||
|> Enum.reverse()
|
defp enforce_order(result, %{max_id: _, order_asc: true}), do: Enum.reverse(result)
|
||||||
end
|
|
||||||
|
|
||||||
defp enforce_order(result, _), do: result
|
defp enforce_order(result, _), do: result
|
||||||
|
|
||||||
defp table_position(%Ecto.Query{} = query, binding_name) do
|
defp table_position(%Ecto.Query{} = query, binding_name) do
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.ReverseProxy do
|
defmodule Pleroma.ReverseProxy do
|
||||||
|
alias Pleroma.Utils.URIEncoding
|
||||||
|
|
||||||
@range_headers ~w(range if-range)
|
@range_headers ~w(range if-range)
|
||||||
@keep_req_headers ~w(accept accept-encoding cache-control if-modified-since) ++
|
@keep_req_headers ~w(accept accept-encoding cache-control if-modified-since) ++
|
||||||
~w(if-unmodified-since if-none-match) ++ @range_headers
|
~w(if-unmodified-since if-none-match) ++ @range_headers
|
||||||
|
|
@ -155,11 +157,12 @@ defmodule Pleroma.ReverseProxy do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp request(method, url, headers, opts) do
|
defp request(method, url, headers, opts) do
|
||||||
Logger.debug("#{__MODULE__} #{method} #{url} #{inspect(headers)}")
|
|
||||||
method = method |> String.downcase() |> String.to_existing_atom()
|
method = method |> String.downcase() |> String.to_existing_atom()
|
||||||
|
|
||||||
url = maybe_encode_url(url)
|
url = maybe_encode_url(url)
|
||||||
|
|
||||||
|
Logger.debug("#{__MODULE__} #{method} #{url} #{inspect(headers)}")
|
||||||
|
|
||||||
case client().request(method, url, headers, "", opts) do
|
case client().request(method, url, headers, "", opts) do
|
||||||
{:ok, code, headers, client} when code in @valid_resp_codes ->
|
{:ok, code, headers, client} when code in @valid_resp_codes ->
|
||||||
{:ok, code, downcase_headers(headers), client}
|
{:ok, code, downcase_headers(headers), client}
|
||||||
|
|
@ -459,9 +462,9 @@ defmodule Pleroma.ReverseProxy do
|
||||||
# Also do it for test environment
|
# Also do it for test environment
|
||||||
defp maybe_encode_url(url) do
|
defp maybe_encode_url(url) do
|
||||||
case Application.get_env(:tesla, :adapter) do
|
case Application.get_env(:tesla, :adapter) do
|
||||||
Tesla.Adapter.Hackney -> Pleroma.HTTP.encode_url(url)
|
Tesla.Adapter.Hackney -> URIEncoding.encode_url(url)
|
||||||
{Tesla.Adapter.Finch, _} -> Pleroma.HTTP.encode_url(url)
|
{Tesla.Adapter.Finch, _} -> URIEncoding.encode_url(url)
|
||||||
Tesla.Mock -> Pleroma.HTTP.encode_url(url)
|
Tesla.Mock -> URIEncoding.encode_url(url)
|
||||||
_ -> url
|
_ -> url
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,11 @@ defmodule Pleroma.ReverseProxy.Client.Hackney do
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def request(method, url, headers, body, opts \\ []) do
|
def request(method, url, headers, body, opts \\ []) do
|
||||||
|
opts =
|
||||||
|
Keyword.put_new(opts, :path_encode_fun, fn path ->
|
||||||
|
path
|
||||||
|
end)
|
||||||
|
|
||||||
:hackney.request(method, url, headers, body, opts)
|
:hackney.request(method, url, headers, body, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Signature do
|
defmodule Pleroma.Signature do
|
||||||
|
@behaviour Pleroma.Signature.API
|
||||||
@behaviour HTTPSignatures.Adapter
|
@behaviour HTTPSignatures.Adapter
|
||||||
|
|
||||||
alias Pleroma.EctoType.ActivityPub.ObjectValidators
|
alias Pleroma.EctoType.ActivityPub.ObjectValidators
|
||||||
|
|
@ -53,7 +54,7 @@ defmodule Pleroma.Signature do
|
||||||
|
|
||||||
def fetch_public_key(conn) do
|
def fetch_public_key(conn) do
|
||||||
with {:ok, actor_id} <- get_actor_id(conn),
|
with {:ok, actor_id} <- get_actor_id(conn),
|
||||||
{:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
|
{:ok, public_key} <- User.get_or_fetch_public_key_for_ap_id(actor_id) do
|
||||||
{:ok, public_key}
|
{:ok, public_key}
|
||||||
else
|
else
|
||||||
e ->
|
e ->
|
||||||
|
|
|
||||||
14
lib/pleroma/signature/api.ex
Normal file
14
lib/pleroma/signature/api.ex
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Signature.API do
|
||||||
|
@moduledoc """
|
||||||
|
Behaviour for signing requests and producing HTTP Date headers.
|
||||||
|
|
||||||
|
This is used to allow tests to replace the signing implementation with Mox.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@callback sign(user :: Pleroma.User.t(), headers :: map()) :: String.t()
|
||||||
|
@callback signed_date() :: String.t()
|
||||||
|
end
|
||||||
|
|
@ -17,7 +17,7 @@ defmodule Pleroma.Tesla.Middleware.EncodeUrl do
|
||||||
|
|
||||||
@impl Tesla.Middleware
|
@impl Tesla.Middleware
|
||||||
def call(%Tesla.Env{url: url} = env, next, _) do
|
def call(%Tesla.Env{url: url} = env, next, _) do
|
||||||
url = Pleroma.HTTP.encode_url(url)
|
url = Pleroma.Utils.URIEncoding.encode_url(url)
|
||||||
|
|
||||||
env = %{env | url: url}
|
env = %{env | url: url}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ defmodule Pleroma.Upload do
|
||||||
"""
|
"""
|
||||||
alias Ecto.UUID
|
alias Ecto.UUID
|
||||||
alias Pleroma.Maps
|
alias Pleroma.Maps
|
||||||
|
alias Pleroma.Utils.URIEncoding
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
|
|
@ -230,11 +231,18 @@ defmodule Pleroma.Upload do
|
||||||
tmp_path
|
tmp_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Encoding the whole path here is fine since the path is in a
|
||||||
|
# UUID/<file name> form.
|
||||||
|
# The file at this point isn't %-encoded, so the path shouldn't
|
||||||
|
# be decoded first like Pleroma.Utils.URIEncoding.encode_url/1 does.
|
||||||
defp url_from_spec(%__MODULE__{name: name}, base_url, {:file, path}) do
|
defp url_from_spec(%__MODULE__{name: name}, base_url, {:file, path}) do
|
||||||
|
encode_opts = [bypass_decode: true, bypass_parse: true]
|
||||||
|
|
||||||
path =
|
path =
|
||||||
URI.encode(path, &char_unescaped?/1) <>
|
URIEncoding.encode_url(path, encode_opts) <>
|
||||||
if Pleroma.Config.get([__MODULE__, :link_name], false) do
|
if Pleroma.Config.get([__MODULE__, :link_name], false) do
|
||||||
"?name=#{URI.encode(name, &char_unescaped?/1)}"
|
enum = %{name: name}
|
||||||
|
"?#{URI.encode_query(enum)}"
|
||||||
else
|
else
|
||||||
""
|
""
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -233,8 +233,8 @@ defmodule Pleroma.User do
|
||||||
for {_relationship_type, [{_outgoing_relation, outgoing_relation_target}, _]} <-
|
for {_relationship_type, [{_outgoing_relation, outgoing_relation_target}, _]} <-
|
||||||
@user_relationships_config do
|
@user_relationships_config do
|
||||||
# `def blocked_users_relation/2`, `def muted_users_relation/2`,
|
# `def blocked_users_relation/2`, `def muted_users_relation/2`,
|
||||||
# `def reblog_muted_users_relation/2`, `def notification_muted_users/2`,
|
# `def reblog_muted_users_relation/2`, `def notification_muted_users_relation/2`,
|
||||||
# `def subscriber_users/2`, `def endorsed_users_relation/2`
|
# `def subscriber_users_relation/2`, `def endorsed_users_relation/2`
|
||||||
def unquote(:"#{outgoing_relation_target}_relation")(user, restrict_deactivated? \\ false) do
|
def unquote(:"#{outgoing_relation_target}_relation")(user, restrict_deactivated? \\ false) do
|
||||||
target_users_query = assoc(user, unquote(outgoing_relation_target))
|
target_users_query = assoc(user, unquote(outgoing_relation_target))
|
||||||
|
|
||||||
|
|
@ -288,6 +288,7 @@ defmodule Pleroma.User do
|
||||||
defdelegate following?(follower, followed), to: FollowingRelationship
|
defdelegate following?(follower, followed), to: FollowingRelationship
|
||||||
defdelegate following_ap_ids(user), to: FollowingRelationship
|
defdelegate following_ap_ids(user), to: FollowingRelationship
|
||||||
defdelegate get_follow_requests(user), to: FollowingRelationship
|
defdelegate get_follow_requests(user), to: FollowingRelationship
|
||||||
|
defdelegate get_outgoing_follow_requests(user), to: FollowingRelationship
|
||||||
defdelegate search(query, opts \\ []), to: User.Search
|
defdelegate search(query, opts \\ []), to: User.Search
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
|
@ -801,13 +802,6 @@ defmodule Pleroma.User do
|
||||||
when is_nil(password) do
|
when is_nil(password) do
|
||||||
params = Map.put_new(params, :accepts_chat_messages, true)
|
params = Map.put_new(params, :accepts_chat_messages, true)
|
||||||
|
|
||||||
params =
|
|
||||||
if Map.has_key?(params, :email) do
|
|
||||||
Map.put_new(params, :email, params[:email])
|
|
||||||
else
|
|
||||||
params
|
|
||||||
end
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
|> cast(params, [
|
|> cast(params, [
|
||||||
:name,
|
:name,
|
||||||
|
|
@ -1364,7 +1358,7 @@ defmodule Pleroma.User do
|
||||||
@spec get_by_nickname(String.t()) :: User.t() | nil
|
@spec get_by_nickname(String.t()) :: User.t() | nil
|
||||||
def get_by_nickname(nickname) do
|
def get_by_nickname(nickname) do
|
||||||
Repo.get_by(User, nickname: nickname) ||
|
Repo.get_by(User, nickname: nickname) ||
|
||||||
if Regex.match?(~r(@#{Pleroma.Web.Endpoint.host()})i, nickname) do
|
if Regex.match?(~r(@#{Pleroma.Web.Endpoint.host()}$)i, nickname) do
|
||||||
Repo.get_by(User, nickname: local_nickname(nickname))
|
Repo.get_by(User, nickname: local_nickname(nickname))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -2314,6 +2308,15 @@ defmodule Pleroma.User do
|
||||||
|
|
||||||
def public_key(_), do: {:error, "key not found"}
|
def public_key(_), do: {:error, "key not found"}
|
||||||
|
|
||||||
|
def get_or_fetch_public_key_for_ap_id(ap_id) do
|
||||||
|
with {:ok, %User{} = user} <- get_or_fetch_by_ap_id(ap_id),
|
||||||
|
{:ok, public_key} <- public_key(user) do
|
||||||
|
{:ok, public_key}
|
||||||
|
else
|
||||||
|
_ -> :error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def get_public_key_for_ap_id(ap_id) do
|
def get_public_key_for_ap_id(ap_id) do
|
||||||
with %User{} = user <- get_cached_by_ap_id(ap_id),
|
with %User{} = user <- get_cached_by_ap_id(ap_id),
|
||||||
{:ok, public_key} <- public_key(user) do
|
{:ok, public_key} <- public_key(user) do
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ defmodule Pleroma.User.Search do
|
||||||
following = Keyword.get(opts, :following, false)
|
following = Keyword.get(opts, :following, false)
|
||||||
result_limit = Keyword.get(opts, :limit, @limit)
|
result_limit = Keyword.get(opts, :limit, @limit)
|
||||||
offset = Keyword.get(opts, :offset, 0)
|
offset = Keyword.get(opts, :offset, 0)
|
||||||
|
capabilities = Keyword.get(opts, :capabilities, [])
|
||||||
|
|
||||||
for_user = Keyword.get(opts, :for_user)
|
for_user = Keyword.get(opts, :for_user)
|
||||||
|
|
||||||
|
|
@ -32,7 +33,7 @@ defmodule Pleroma.User.Search do
|
||||||
|
|
||||||
results =
|
results =
|
||||||
query_string
|
query_string
|
||||||
|> search_query(for_user, following, top_user_ids)
|
|> search_query(for_user, following, top_user_ids, capabilities)
|
||||||
|> Pagination.fetch_paginated(%{"offset" => offset, "limit" => result_limit}, :offset)
|
|> Pagination.fetch_paginated(%{"offset" => offset, "limit" => result_limit}, :offset)
|
||||||
|
|
||||||
results
|
results
|
||||||
|
|
@ -80,7 +81,7 @@ defmodule Pleroma.User.Search do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp search_query(query_string, for_user, following, top_user_ids) do
|
defp search_query(query_string, for_user, following, top_user_ids, capabilities) do
|
||||||
for_user
|
for_user
|
||||||
|> base_query(following)
|
|> base_query(following)
|
||||||
|> filter_blocked_user(for_user)
|
|> filter_blocked_user(for_user)
|
||||||
|
|
@ -94,6 +95,7 @@ defmodule Pleroma.User.Search do
|
||||||
|> subquery()
|
|> subquery()
|
||||||
|> order_by(desc: :search_rank)
|
|> order_by(desc: :search_rank)
|
||||||
|> maybe_restrict_local(for_user)
|
|> maybe_restrict_local(for_user)
|
||||||
|
|> maybe_restrict_accepting_chat_messages(capabilities)
|
||||||
|> filter_deactivated_users()
|
|> filter_deactivated_users()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -214,6 +216,14 @@ defmodule Pleroma.User.Search do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp maybe_restrict_accepting_chat_messages(query, capabilities) do
|
||||||
|
if "accepts_chat_messages" in capabilities do
|
||||||
|
from(q in query, where: q.accepts_chat_messages == true)
|
||||||
|
else
|
||||||
|
query
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
defp limit, do: Pleroma.Config.get([:instance, :limit_to_local_content], :unauthenticated)
|
defp limit, do: Pleroma.Config.get([:instance, :limit_to_local_content], :unauthenticated)
|
||||||
|
|
||||||
defp restrict_local(q), do: where(q, [u], u.local == true)
|
defp restrict_local(q), do: where(q, [u], u.local == true)
|
||||||
|
|
|
||||||
142
lib/pleroma/utils/uri_encoding.ex
Normal file
142
lib/pleroma/utils/uri_encoding.ex
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2025 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Utils.URIEncoding do
|
||||||
|
@moduledoc """
|
||||||
|
Utility functions for dealing with URI encoding of paths and queries
|
||||||
|
with support for query-encoding quirks.
|
||||||
|
"""
|
||||||
|
require Pleroma.Constants
|
||||||
|
|
||||||
|
# We don't always want to decode the path first, like is the case in
|
||||||
|
# Pleroma.Upload.url_from_spec/3.
|
||||||
|
@doc """
|
||||||
|
Wraps URI encoding/decoding functions from Elixir's standard library to fix usually unintended side-effects.
|
||||||
|
|
||||||
|
Supports two URL processing options in the optional 2nd argument with the default being `false`:
|
||||||
|
|
||||||
|
* `bypass_parse` - Bypasses `URI.parse` stage, useful when it's not desirable to parse to URL first
|
||||||
|
before encoding it. Supports only encoding as the Path segment of a URI.
|
||||||
|
* `bypass_decode` - Bypasses `URI.decode` stage for the Path segment of a URI. Used when a URL
|
||||||
|
has to be double %-encoded for internal reasons.
|
||||||
|
|
||||||
|
Options must be specified as a Keyword with tuples with booleans, otherwise
|
||||||
|
`{:error, :invalid_opts}` is returned. Example:
|
||||||
|
`encode_url(url, [bypass_parse: true, bypass_decode: true])`
|
||||||
|
"""
|
||||||
|
@spec encode_url(String.t(), Keyword.t()) :: String.t() | {:error, :invalid_opts}
|
||||||
|
def encode_url(url, opts \\ []) when is_binary(url) and is_list(opts) do
|
||||||
|
bypass_parse = Keyword.get(opts, :bypass_parse, false)
|
||||||
|
bypass_decode = Keyword.get(opts, :bypass_decode, false)
|
||||||
|
|
||||||
|
with true <- is_boolean(bypass_parse),
|
||||||
|
true <- is_boolean(bypass_decode) do
|
||||||
|
cond do
|
||||||
|
bypass_parse ->
|
||||||
|
encode_path(url, bypass_decode)
|
||||||
|
|
||||||
|
true ->
|
||||||
|
URI.parse(url)
|
||||||
|
|> then(fn parsed ->
|
||||||
|
path = encode_path(parsed.path, bypass_decode)
|
||||||
|
|
||||||
|
query = encode_query(parsed.query, parsed.host)
|
||||||
|
|
||||||
|
%{parsed | path: path, query: query}
|
||||||
|
end)
|
||||||
|
|> URI.to_string()
|
||||||
|
end
|
||||||
|
else
|
||||||
|
_ -> {:error, :invalid_opts}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_path(nil, _bypass_decode), do: nil
|
||||||
|
|
||||||
|
# URI.encode/2 deliberately does not encode all chars that are forbidden
|
||||||
|
# in the path component of a URI. It only encodes chars that are forbidden
|
||||||
|
# in the whole URI. A predicate in the 2nd argument is used to fix that here.
|
||||||
|
# URI.encode/2 uses the predicate function to determine whether each byte
|
||||||
|
# (in an integer representation) should be encoded or not.
|
||||||
|
defp encode_path(path, bypass_decode) when is_binary(path) do
|
||||||
|
path =
|
||||||
|
cond do
|
||||||
|
bypass_decode ->
|
||||||
|
path
|
||||||
|
|
||||||
|
true ->
|
||||||
|
URI.decode(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
path
|
||||||
|
|> URI.encode(fn byte ->
|
||||||
|
URI.char_unreserved?(byte) ||
|
||||||
|
Enum.any?(
|
||||||
|
Pleroma.Constants.uri_path_allowed_reserved_chars(),
|
||||||
|
fn char ->
|
||||||
|
char == byte
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Order of kv pairs in query is not preserved when using URI.decode_query.
|
||||||
|
# URI.query_decoder/2 returns a stream which so far appears to not change order.
|
||||||
|
# Immediately switch to a list to prevent breakage for sites that expect
|
||||||
|
# the order of query keys to be always the same.
|
||||||
|
defp encode_query(query, host) when is_binary(query) do
|
||||||
|
query
|
||||||
|
|> URI.query_decoder()
|
||||||
|
|> Enum.to_list()
|
||||||
|
|> do_encode_query(host)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_query(nil, _), do: nil
|
||||||
|
|
||||||
|
# Always uses www_form encoding.
|
||||||
|
# Taken from Elixir's URI module.
|
||||||
|
defp do_encode_query(enumerable, host) do
|
||||||
|
Enum.map_join(enumerable, "&", &maybe_apply_query_quirk(&1, host))
|
||||||
|
end
|
||||||
|
|
||||||
|
# https://git.pleroma.social/pleroma/pleroma/-/issues/1055
|
||||||
|
defp maybe_apply_query_quirk({key, value}, "i.guim.co.uk" = _host) do
|
||||||
|
case key do
|
||||||
|
"precrop" ->
|
||||||
|
query_encode_kv_pair({key, value}, ~c":,")
|
||||||
|
|
||||||
|
key ->
|
||||||
|
query_encode_kv_pair({key, value})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_apply_query_quirk({key, value}, _), do: query_encode_kv_pair({key, value})
|
||||||
|
|
||||||
|
# Taken from Elixir's URI module and modified to support quirks.
|
||||||
|
defp query_encode_kv_pair({key, value}, rules \\ []) when is_list(rules) do
|
||||||
|
cond do
|
||||||
|
length(rules) > 0 ->
|
||||||
|
# URI.encode_query/2 does not appear to follow spec and encodes all parts
|
||||||
|
# of our URI path Constant. This appears to work outside of edge-cases
|
||||||
|
# like The Guardian Rich Media Cards, keeping behavior same as with
|
||||||
|
# URI.encode_query/2 unless otherwise specified via rules.
|
||||||
|
(URI.encode_www_form(Kernel.to_string(key)) <>
|
||||||
|
"=" <>
|
||||||
|
URI.encode(value, fn byte ->
|
||||||
|
URI.char_unreserved?(byte) ||
|
||||||
|
Enum.any?(
|
||||||
|
rules,
|
||||||
|
fn char ->
|
||||||
|
char == byte
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end))
|
||||||
|
|> String.replace("%20", "+")
|
||||||
|
|
||||||
|
true ->
|
||||||
|
URI.encode_www_form(Kernel.to_string(key)) <>
|
||||||
|
"=" <> URI.encode_www_form(Kernel.to_string(value))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -414,10 +414,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||||
|
|
||||||
with flag_data <- make_flag_data(params, additional),
|
with flag_data <- make_flag_data(params, additional),
|
||||||
{:ok, activity} <- insert(flag_data, local),
|
{:ok, activity} <- insert(flag_data, local),
|
||||||
{:ok, stripped_activity} <- strip_report_status_data(activity),
|
|
||||||
_ <- notify_and_stream(activity),
|
_ <- notify_and_stream(activity),
|
||||||
:ok <-
|
:ok <- maybe_federate(activity) do
|
||||||
maybe_federate(stripped_activity) do
|
|
||||||
User.all_users_with_privilege(:reports_manage_reports)
|
User.all_users_with_privilege(:reports_manage_reports)
|
||||||
|> Enum.filter(fn user -> user.ap_id != actor end)
|
|> Enum.filter(fn user -> user.ap_id != actor end)
|
||||||
|> Enum.filter(fn user -> not is_nil(user.email) end)
|
|> Enum.filter(fn user -> not is_nil(user.email) end)
|
||||||
|
|
@ -501,6 +499,28 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def fetch_objects_for_replies_collection(parent_ap_id, opts \\ %{}) do
|
||||||
|
opts =
|
||||||
|
opts
|
||||||
|
|> Map.put(:order_asc, true)
|
||||||
|
|> Map.put(:id_type, :integer)
|
||||||
|
|
||||||
|
from(o in Object,
|
||||||
|
where:
|
||||||
|
fragment("?->>'inReplyTo' = ?", o.data, ^parent_ap_id) and
|
||||||
|
fragment(
|
||||||
|
"(?->'to' \\? ?::text OR ?->'cc' \\? ?::text)",
|
||||||
|
o.data,
|
||||||
|
^Pleroma.Constants.as_public(),
|
||||||
|
o.data,
|
||||||
|
^Pleroma.Constants.as_public()
|
||||||
|
) and
|
||||||
|
fragment("?->>'type' <> 'Answer'", o.data),
|
||||||
|
select: %{id: o.id, ap_id: fragment("?->>'id'", o.data)}
|
||||||
|
)
|
||||||
|
|> Pagination.fetch_paginated(opts, :keyset)
|
||||||
|
end
|
||||||
|
|
||||||
@spec fetch_latest_direct_activity_id_for_context(String.t(), keyword() | map()) ::
|
@spec fetch_latest_direct_activity_id_for_context(String.t(), keyword() | map()) ::
|
||||||
Ecto.UUID.t() | nil
|
Ecto.UUID.t() | nil
|
||||||
def fetch_latest_direct_activity_id_for_context(context, opts \\ %{}) do
|
def fetch_latest_direct_activity_id_for_context(context, opts \\ %{}) do
|
||||||
|
|
@ -1065,6 +1085,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||||
from(activity in query, where: fragment("?->>'type' != 'Announce'", activity.data))
|
from(activity in query, where: fragment("?->>'type' != 'Announce'", activity.data))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp restrict_reblogs(query, %{only_reblogs: true}) do
|
||||||
|
from(activity in query, where: fragment("?->>'type' = 'Announce'", activity.data))
|
||||||
|
end
|
||||||
|
|
||||||
defp restrict_reblogs(query, _), do: query
|
defp restrict_reblogs(query, _), do: query
|
||||||
|
|
||||||
defp restrict_muted(query, %{with_muted: true}), do: query
|
defp restrict_muted(query, %{with_muted: true}), do: query
|
||||||
|
|
@ -1567,7 +1591,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||||
|
|
||||||
defp get_actor_url(_url), do: nil
|
defp get_actor_url(_url), do: nil
|
||||||
|
|
||||||
defp normalize_image(%{"url" => url} = data) do
|
defp normalize_image(%{"url" => url} = data) when is_binary(url) do
|
||||||
%{
|
%{
|
||||||
"type" => "Image",
|
"type" => "Image",
|
||||||
"url" => [%{"href" => url}]
|
"url" => [%{"href" => url}]
|
||||||
|
|
@ -1575,6 +1599,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||||
|> maybe_put_description(data)
|
|> maybe_put_description(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp normalize_image(%{"url" => urls}) when is_list(urls) do
|
||||||
|
url = urls |> List.first()
|
||||||
|
|
||||||
|
%{"url" => url}
|
||||||
|
|> normalize_image()
|
||||||
|
end
|
||||||
|
|
||||||
defp normalize_image(urls) when is_list(urls), do: urls |> List.first() |> normalize_image()
|
defp normalize_image(urls) when is_list(urls), do: urls |> List.first() |> normalize_image()
|
||||||
defp normalize_image(_), do: nil
|
defp normalize_image(_), do: nil
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|
||||||
|
|
||||||
@federating_only_actions [:internal_fetch, :relay, :relay_following, :relay_followers]
|
@federating_only_actions [:internal_fetch, :relay, :relay_following, :relay_followers]
|
||||||
|
|
||||||
|
@object_replies_known_param_keys ["page", "min_id", "max_id", "since_id", "limit"]
|
||||||
|
|
||||||
plug(FederatingPlug when action in @federating_only_actions)
|
plug(FederatingPlug when action in @federating_only_actions)
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
|
|
@ -95,6 +97,36 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def object_replies(%{assigns: assigns, query_params: params} = conn, _all_params) do
|
||||||
|
object_ap_id = conn.path_info |> Enum.reverse() |> tl() |> Enum.reverse()
|
||||||
|
object_ap_id = Endpoint.url() <> "/" <> Enum.join(object_ap_id, "/")
|
||||||
|
|
||||||
|
# Most other API params are converted to atoms by OpenAPISpex 3.x
|
||||||
|
# and therefore helper functions assume atoms. For consistency,
|
||||||
|
# also convert our params to atoms here.
|
||||||
|
params =
|
||||||
|
params
|
||||||
|
|> Map.take(@object_replies_known_param_keys)
|
||||||
|
|> Enum.into(%{}, fn {k, v} -> {String.to_existing_atom(k), v} end)
|
||||||
|
|> Map.put(:object_ap_id, object_ap_id)
|
||||||
|
|> Map.put(:order_asc, true)
|
||||||
|
|> Map.put(:conn, conn)
|
||||||
|
|
||||||
|
with %Object{} = object <- Object.get_cached_by_ap_id(object_ap_id),
|
||||||
|
user <- Map.get(assigns, :user, nil),
|
||||||
|
{_, true} <- {:visible?, Visibility.visible_for_user?(object, user)} do
|
||||||
|
conn
|
||||||
|
|> maybe_skip_cache(user)
|
||||||
|
|> set_cache_ttl_for(object)
|
||||||
|
|> put_resp_content_type("application/activity+json")
|
||||||
|
|> put_view(ObjectView)
|
||||||
|
|> render("object_replies.json", render_params: params)
|
||||||
|
else
|
||||||
|
{:visible?, false} -> {:error, :not_found}
|
||||||
|
nil -> {:error, :not_found}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def track_object_fetch(conn, nil), do: conn
|
def track_object_fetch(conn, nil), do: conn
|
||||||
|
|
||||||
def track_object_fetch(conn, object_id) do
|
def track_object_fetch(conn, object_id) do
|
||||||
|
|
@ -257,8 +289,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|
||||||
|> put_view(UserView)
|
|> put_view(UserView)
|
||||||
|> render("activity_collection_page.json", %{
|
|> render("activity_collection_page.json", %{
|
||||||
activities: activities,
|
activities: activities,
|
||||||
pagination: ControllerHelper.get_pagination_fields(conn, activities),
|
pagination: ControllerHelper.get_pagination_fields(conn, activities)
|
||||||
iri: "#{user.ap_id}/outbox"
|
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -404,8 +435,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|
||||||
|> put_view(UserView)
|
|> put_view(UserView)
|
||||||
|> render("activity_collection_page.json", %{
|
|> render("activity_collection_page.json", %{
|
||||||
activities: activities,
|
activities: activities,
|
||||||
pagination: ControllerHelper.get_pagination_fields(conn, activities),
|
pagination: ControllerHelper.get_pagination_fields(conn, activities)
|
||||||
iri: "#{user.ap_id}/inbox"
|
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -482,6 +512,42 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|
||||||
{:ok, activity}
|
{:ok, activity}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# We currently lack a Flag ObjectValidator since both CommonAPI and Transmogrifier
|
||||||
|
# both send it straight to ActivityPub.flag and C2S currently has to go through
|
||||||
|
# the normal pipeline which requires an ObjectValidator.
|
||||||
|
# TODO: Add a Flag Activity ObjectValidator
|
||||||
|
defp check_allowed_action(_, %{"type" => "Flag"}) do
|
||||||
|
{:error, "Flag activities aren't currently supported in C2S"}
|
||||||
|
end
|
||||||
|
|
||||||
|
# It would respond with 201 and silently fail with:
|
||||||
|
# Could not decode featured collection at fetch #{user.ap_id} \
|
||||||
|
# {:error, "Trying to fetch local resource"}
|
||||||
|
defp check_allowed_action(%{ap_id: ap_id}, %{"type" => "Update", "object" => %{"id" => ap_id}}),
|
||||||
|
do: {:error, "Updating profile is not currently supported in C2S"}
|
||||||
|
|
||||||
|
defp check_allowed_action(_, activity), do: {:ok, activity}
|
||||||
|
|
||||||
|
defp validate_visibility(%User{} = user, %{"type" => type, "object" => object} = activity) do
|
||||||
|
with {_, %Object{} = normalized_object} <-
|
||||||
|
{:normalize, Object.normalize(object, fetch: false)},
|
||||||
|
{_, true} <- {:visibility, Visibility.visible_for_user?(normalized_object, user)} do
|
||||||
|
{:ok, activity}
|
||||||
|
else
|
||||||
|
{:normalize, _} ->
|
||||||
|
if type in ["Create", "Listen"] do
|
||||||
|
# Creating new object via C2S; user is local and authenticated
|
||||||
|
# via the :authenticate Plug pipeline.
|
||||||
|
{:ok, activity}
|
||||||
|
else
|
||||||
|
{:error, "No such object found"}
|
||||||
|
end
|
||||||
|
|
||||||
|
{:visibility, _} ->
|
||||||
|
{:forbidden, "You can't interact with this object"}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def update_outbox(
|
def update_outbox(
|
||||||
%{assigns: %{user: %User{nickname: nickname, ap_id: actor} = user}} = conn,
|
%{assigns: %{user: %User{nickname: nickname, ap_id: actor} = user}} = conn,
|
||||||
%{"nickname" => nickname} = params
|
%{"nickname" => nickname} = params
|
||||||
|
|
@ -493,6 +559,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|
||||||
|> Map.put("actor", actor)
|
|> Map.put("actor", actor)
|
||||||
|
|
||||||
with {:ok, params} <- fix_user_message(user, params),
|
with {:ok, params} <- fix_user_message(user, params),
|
||||||
|
{:ok, params} <- check_allowed_action(user, params),
|
||||||
|
{:ok, params} <- validate_visibility(user, params),
|
||||||
{:ok, activity, _} <- Pipeline.common_pipeline(params, local: true),
|
{:ok, activity, _} <- Pipeline.common_pipeline(params, local: true),
|
||||||
%Activity{data: activity_data} <- Activity.normalize(activity) do
|
%Activity{data: activity_data} <- Activity.normalize(activity) do
|
||||||
conn
|
conn
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy do
|
||||||
content =~ quote_url -> true
|
content =~ quote_url -> true
|
||||||
# Does the content already have a .quote-inline span?
|
# Does the content already have a .quote-inline span?
|
||||||
content =~ "<span class=\"quote-inline\">" -> true
|
content =~ "<span class=\"quote-inline\">" -> true
|
||||||
|
# Does the content already have a .quote-inline p? (Mastodon)
|
||||||
|
content =~ "<p class=\"quote-inline\">" -> true
|
||||||
# No inline quote found
|
# No inline quote found
|
||||||
true -> false
|
true -> false
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -56,20 +56,24 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
|
||||||
defp fix_tag(%{"tag" => tag} = data) when is_map(tag), do: Map.put(data, "tag", [tag])
|
defp fix_tag(%{"tag" => tag} = data) when is_map(tag), do: Map.put(data, "tag", [tag])
|
||||||
defp fix_tag(data), do: Map.drop(data, ["tag"])
|
defp fix_tag(data), do: Map.drop(data, ["tag"])
|
||||||
|
|
||||||
|
# legacy internal *oma format
|
||||||
|
defp fix_replies(%{"replies" => replies} = data) when is_list(replies), do: data
|
||||||
|
|
||||||
defp fix_replies(%{"replies" => %{"first" => %{"items" => replies}}} = data)
|
defp fix_replies(%{"replies" => %{"first" => %{"items" => replies}}} = data)
|
||||||
when is_list(replies),
|
when is_list(replies),
|
||||||
do: Map.put(data, "replies", replies)
|
do: Map.put(data, "replies", replies)
|
||||||
|
|
||||||
|
defp fix_replies(%{"replies" => %{"first" => %{"orderedItems" => replies}}} = data)
|
||||||
|
when is_list(replies),
|
||||||
|
do: Map.put(data, "replies", replies)
|
||||||
|
|
||||||
defp fix_replies(%{"replies" => %{"items" => replies}} = data) when is_list(replies),
|
defp fix_replies(%{"replies" => %{"items" => replies}} = data) when is_list(replies),
|
||||||
do: Map.put(data, "replies", replies)
|
do: Map.put(data, "replies", replies)
|
||||||
|
|
||||||
# TODO: Pleroma does not have any support for Collections at the moment.
|
defp fix_replies(%{"replies" => %{"orderedItems" => replies}} = data) when is_list(replies),
|
||||||
# If the `replies` field is not something the ObjectID validator can handle,
|
do: Map.put(data, "replies", replies)
|
||||||
# the activity/object would be rejected, which is bad behavior.
|
|
||||||
defp fix_replies(%{"replies" => replies} = data) when not is_list(replies),
|
|
||||||
do: Map.drop(data, ["replies"])
|
|
||||||
|
|
||||||
defp fix_replies(data), do: data
|
defp fix_replies(data), do: Map.delete(data, "replies")
|
||||||
|
|
||||||
def fix_attachments(%{"attachment" => attachment} = data) when is_map(attachment),
|
def fix_attachments(%{"attachment" => attachment} = data) when is_map(attachment),
|
||||||
do: Map.put(data, "attachment", [attachment])
|
do: Map.put(data, "attachment", [attachment])
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,15 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
|
||||||
require Pleroma.Constants
|
require Pleroma.Constants
|
||||||
|
|
||||||
def cast_and_filter_recipients(message, field, follower_collection, field_fallback \\ []) do
|
def cast_and_filter_recipients(message, field, follower_collection, field_fallback \\ []) do
|
||||||
{:ok, data} = ObjectValidators.Recipients.cast(message[field] || field_fallback)
|
# Fix as:Public/Public before ObjectID casting drops it, but keep `field_fallback`
|
||||||
|
# semantics (only used when the field is missing).
|
||||||
|
recipients =
|
||||||
|
%{field => message[field] || field_fallback}
|
||||||
|
|> Transmogrifier.fix_addressing_list(field)
|
||||||
|
|> Transmogrifier.fix_addressing_public(field)
|
||||||
|
|> Map.fetch!(field)
|
||||||
|
|
||||||
|
{:ok, data} = ObjectValidators.Recipients.cast(recipients)
|
||||||
|
|
||||||
data =
|
data =
|
||||||
Enum.reject(data, fn x ->
|
Enum.reject(data, fn x ->
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.Publisher.Prepared
|
alias Pleroma.Web.ActivityPub.Publisher.Prepared
|
||||||
alias Pleroma.Web.ActivityPub.Relay
|
alias Pleroma.Web.ActivityPub.Relay
|
||||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
|
||||||
alias Pleroma.Workers.PublisherWorker
|
alias Pleroma.Workers.PublisherWorker
|
||||||
|
|
||||||
require Pleroma.Constants
|
require Pleroma.Constants
|
||||||
|
|
@ -26,6 +25,18 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
||||||
ActivityPub outgoing federation module.
|
ActivityPub outgoing federation module.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@signature_impl Application.compile_env(
|
||||||
|
:pleroma,
|
||||||
|
[__MODULE__, :signature_impl],
|
||||||
|
Pleroma.Signature
|
||||||
|
)
|
||||||
|
|
||||||
|
@transmogrifier_impl Application.compile_env(
|
||||||
|
:pleroma,
|
||||||
|
[__MODULE__, :transmogrifier_impl],
|
||||||
|
Pleroma.Web.ActivityPub.Transmogrifier
|
||||||
|
)
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Enqueue publishing a single activity.
|
Enqueue publishing a single activity.
|
||||||
"""
|
"""
|
||||||
|
|
@ -68,7 +79,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
||||||
Determine if an activity can be represented by running it through Transmogrifier.
|
Determine if an activity can be represented by running it through Transmogrifier.
|
||||||
"""
|
"""
|
||||||
def representable?(%Activity{} = activity) do
|
def representable?(%Activity{} = activity) do
|
||||||
with {:ok, _data} <- Transmogrifier.prepare_outgoing(activity.data) do
|
with {:ok, _data} <- @transmogrifier_impl.prepare_outgoing(activity.data) do
|
||||||
true
|
true
|
||||||
else
|
else
|
||||||
_e ->
|
_e ->
|
||||||
|
|
@ -91,7 +102,17 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
||||||
Logger.debug("Federating #{ap_id} to #{inbox}")
|
Logger.debug("Federating #{ap_id} to #{inbox}")
|
||||||
uri = %{path: path} = URI.parse(inbox)
|
uri = %{path: path} = URI.parse(inbox)
|
||||||
|
|
||||||
{:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
|
{:ok, data} = @transmogrifier_impl.prepare_outgoing(activity.data)
|
||||||
|
|
||||||
|
{actor, data} =
|
||||||
|
with {_, false} <- {:actor_changed?, data["actor"] != activity.data["actor"]} do
|
||||||
|
{actor, data}
|
||||||
|
else
|
||||||
|
{:actor_changed?, true} ->
|
||||||
|
# If prepare_outgoing changes the actor, re-get it from the db
|
||||||
|
new_actor = User.get_cached_by_ap_id(data["actor"])
|
||||||
|
{new_actor, data}
|
||||||
|
end
|
||||||
|
|
||||||
param_cc = Map.get(params, :cc, [])
|
param_cc = Map.get(params, :cc, [])
|
||||||
|
|
||||||
|
|
@ -115,10 +136,10 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
||||||
|
|
||||||
digest = "SHA-256=" <> (:crypto.hash(:sha256, json) |> Base.encode64())
|
digest = "SHA-256=" <> (:crypto.hash(:sha256, json) |> Base.encode64())
|
||||||
|
|
||||||
date = Pleroma.Signature.signed_date()
|
date = @signature_impl.signed_date()
|
||||||
|
|
||||||
signature =
|
signature =
|
||||||
Pleroma.Signature.sign(actor, %{
|
@signature_impl.sign(actor, %{
|
||||||
"(request-target)": "post #{path}",
|
"(request-target)": "post #{path}",
|
||||||
host: signature_host(uri),
|
host: signature_host(uri),
|
||||||
"content-length": byte_size(json),
|
"content-length": byte_size(json),
|
||||||
|
|
@ -310,17 +331,21 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
||||||
Repo.checkout(fn ->
|
Repo.checkout(fn ->
|
||||||
Enum.each([priority_inboxes, other_inboxes], fn inboxes ->
|
Enum.each([priority_inboxes, other_inboxes], fn inboxes ->
|
||||||
Enum.each(inboxes, fn inbox ->
|
Enum.each(inboxes, fn inbox ->
|
||||||
%User{ap_id: ap_id} = Enum.find(recipients, fn actor -> actor.inbox == inbox end)
|
{%User{ap_id: ap_id}, priority} =
|
||||||
|
get_user_with_priority(inbox, priority_recipients, recipients)
|
||||||
|
|
||||||
# Get all the recipients on the same host and add them to cc. Otherwise, a remote
|
# Get all the recipients on the same host and add them to cc. Otherwise, a remote
|
||||||
# instance would only accept a first message for the first recipient and ignore the rest.
|
# instance would only accept a first message for the first recipient and ignore the rest.
|
||||||
cc = get_cc_ap_ids(ap_id, recipients)
|
cc = get_cc_ap_ids(ap_id, recipients)
|
||||||
|
|
||||||
__MODULE__.enqueue_one(%{
|
__MODULE__.enqueue_one(
|
||||||
inbox: inbox,
|
%{
|
||||||
cc: cc,
|
inbox: inbox,
|
||||||
activity_id: activity.id
|
cc: cc,
|
||||||
})
|
activity_id: activity.id
|
||||||
|
},
|
||||||
|
priority: priority
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
@ -382,4 +407,15 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
||||||
end
|
end
|
||||||
|
|
||||||
def gather_nodeinfo_protocol_names, do: ["activitypub"]
|
def gather_nodeinfo_protocol_names, do: ["activitypub"]
|
||||||
|
|
||||||
|
defp get_user_with_priority(inbox, priority_recipients, recipients) do
|
||||||
|
[{priority_recipients, 0}, {recipients, 1}]
|
||||||
|
|> Enum.find_value(fn {recipients, priority} ->
|
||||||
|
with %User{} = user <- Enum.find(recipients, fn actor -> actor.inbox == inbox end) do
|
||||||
|
{user, priority}
|
||||||
|
else
|
||||||
|
_ -> nil
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
A module to handle coding from internal to wire ActivityPub and back.
|
A module to handle coding from internal to wire ActivityPub and back.
|
||||||
"""
|
"""
|
||||||
|
@behaviour Pleroma.Web.ActivityPub.Transmogrifier.API
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.EctoType.ActivityPub.ObjectValidators
|
alias Pleroma.EctoType.ActivityPub.ObjectValidators
|
||||||
alias Pleroma.Maps
|
alias Pleroma.Maps
|
||||||
|
|
@ -22,7 +23,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||||
alias Pleroma.Web.ActivityPub.Visibility
|
alias Pleroma.Web.ActivityPub.Visibility
|
||||||
alias Pleroma.Web.Federator
|
alias Pleroma.Web.Federator
|
||||||
|
|
||||||
import Ecto.Query
|
|
||||||
import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1]
|
import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1]
|
||||||
|
|
||||||
require Pleroma.Constants
|
require Pleroma.Constants
|
||||||
|
|
@ -103,6 +103,24 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Bovine compatibility
|
||||||
|
https://codeberg.org/bovine/bovine/issues/53
|
||||||
|
"""
|
||||||
|
def fix_addressing_public(map, field) do
|
||||||
|
addrs = Map.get(map, field, []) |> List.wrap()
|
||||||
|
|
||||||
|
Map.put(
|
||||||
|
map,
|
||||||
|
field,
|
||||||
|
Enum.map(addrs, fn
|
||||||
|
"Public" -> Pleroma.Constants.as_public()
|
||||||
|
"as:Public" -> Pleroma.Constants.as_public()
|
||||||
|
x -> x
|
||||||
|
end)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
# if directMessage flag is set to true, leave the addressing alone
|
# if directMessage flag is set to true, leave the addressing alone
|
||||||
def fix_explicit_addressing(%{"directMessage" => true} = object, _follower_collection),
|
def fix_explicit_addressing(%{"directMessage" => true} = object, _follower_collection),
|
||||||
do: object
|
do: object
|
||||||
|
|
@ -160,6 +178,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||||
|> fix_addressing_list("cc")
|
|> fix_addressing_list("cc")
|
||||||
|> fix_addressing_list("bto")
|
|> fix_addressing_list("bto")
|
||||||
|> fix_addressing_list("bcc")
|
|> fix_addressing_list("bcc")
|
||||||
|
|> fix_addressing_public("to")
|
||||||
|
|> fix_addressing_public("cc")
|
||||||
|
|> fix_addressing_public("bto")
|
||||||
|
|> fix_addressing_public("bcc")
|
||||||
|> fix_explicit_addressing(follower_collection)
|
|> fix_explicit_addressing(follower_collection)
|
||||||
|> fix_implicit_addressing(follower_collection)
|
|> fix_implicit_addressing(follower_collection)
|
||||||
end
|
end
|
||||||
|
|
@ -739,48 +761,26 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||||
def set_quote_url(obj), do: obj
|
def set_quote_url(obj), do: obj
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Serialized Mastodon-compatible `replies` collection containing _self-replies_.
|
Inline first page of the `replies` collection,
|
||||||
Based on Mastodon's ActivityPub::NoteSerializer#replies.
|
containing any replies in chronological order.
|
||||||
"""
|
"""
|
||||||
def set_replies(obj_data) do
|
def set_replies(%{"type" => type} = obj_data)
|
||||||
replies_uris =
|
when type in Pleroma.Constants.status_object_types() do
|
||||||
with limit when limit > 0 <-
|
with obj_ap_id when is_binary(obj_ap_id) <- obj_data["id"],
|
||||||
Pleroma.Config.get([:activitypub, :note_replies_output_limit], 0),
|
limit when limit > 0 <-
|
||||||
%Object{} = object <- Object.get_cached_by_ap_id(obj_data["id"]) do
|
Pleroma.Config.get([:activitypub, :note_replies_output_limit], 0),
|
||||||
object
|
collection <-
|
||||||
|> Object.self_replies()
|
Pleroma.Web.ActivityPub.ObjectView.render("object_replies.json", %{
|
||||||
|> select([o], fragment("?->>'id'", o.data))
|
render_params: %{object_ap_id: obj_data["id"], limit: limit, skip_ap_ctx: true}
|
||||||
|> limit(^limit)
|
}) do
|
||||||
|> Repo.all()
|
Map.put(obj_data, "replies", collection)
|
||||||
else
|
else
|
||||||
_ -> []
|
0 -> Map.put(obj_data, "replies", obj_data["id"] <> "/replies")
|
||||||
end
|
_ -> obj_data
|
||||||
|
end
|
||||||
set_replies(obj_data, replies_uris)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp set_replies(obj, []) do
|
def set_replies(obj_data), do: obj_data
|
||||||
obj
|
|
||||||
end
|
|
||||||
|
|
||||||
defp set_replies(obj, replies_uris) do
|
|
||||||
replies_collection = %{
|
|
||||||
"type" => "Collection",
|
|
||||||
"items" => replies_uris
|
|
||||||
}
|
|
||||||
|
|
||||||
Map.merge(obj, %{"replies" => replies_collection})
|
|
||||||
end
|
|
||||||
|
|
||||||
def replies(%{"replies" => %{"first" => %{"items" => items}}}) when not is_nil(items) do
|
|
||||||
items
|
|
||||||
end
|
|
||||||
|
|
||||||
def replies(%{"replies" => %{"items" => items}}) when not is_nil(items) do
|
|
||||||
items
|
|
||||||
end
|
|
||||||
|
|
||||||
def replies(_), do: []
|
|
||||||
|
|
||||||
# Prepares the object of an outgoing create activity.
|
# Prepares the object of an outgoing create activity.
|
||||||
def prepare_object(object) do
|
def prepare_object(object) do
|
||||||
|
|
@ -850,6 +850,27 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||||
{:ok, data}
|
{:ok, data}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def prepare_outgoing(%{"type" => "Update", "object" => %{"type" => objtype} = object} = data)
|
||||||
|
when objtype in Pleroma.Constants.actor_types() do
|
||||||
|
object =
|
||||||
|
object
|
||||||
|
|> maybe_fix_user_object()
|
||||||
|
|> strip_internal_fields()
|
||||||
|
|
||||||
|
data =
|
||||||
|
data
|
||||||
|
|> Map.put("object", object)
|
||||||
|
|> strip_internal_fields()
|
||||||
|
|> Map.merge(Utils.make_json_ld_header(object))
|
||||||
|
|> Map.delete("bcc")
|
||||||
|
|
||||||
|
{:ok, data}
|
||||||
|
end
|
||||||
|
|
||||||
|
def prepare_outgoing(%{"type" => "Update", "object" => %{}} = data) do
|
||||||
|
raise "Requested to serve an Update for non-updateable object type: #{inspect(data)}"
|
||||||
|
end
|
||||||
|
|
||||||
def prepare_outgoing(%{"type" => "Announce", "actor" => ap_id, "object" => object_id} = data) do
|
def prepare_outgoing(%{"type" => "Announce", "actor" => ap_id, "object" => object_id} = data) do
|
||||||
object =
|
object =
|
||||||
object_id
|
object_id
|
||||||
|
|
@ -909,6 +930,14 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def prepare_outgoing(%{"type" => "Flag"} = data) do
|
||||||
|
with {:ok, stripped_activity} <- Utils.strip_report_status_data(data),
|
||||||
|
stripped_activity <- Utils.maybe_anonymize_reporter(stripped_activity),
|
||||||
|
stripped_activity <- Map.merge(stripped_activity, Utils.make_json_ld_header()) do
|
||||||
|
{:ok, stripped_activity}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def prepare_outgoing(%{"type" => _type} = data) do
|
def prepare_outgoing(%{"type" => _type} = data) do
|
||||||
data =
|
data =
|
||||||
data
|
data
|
||||||
|
|
|
||||||
11
lib/pleroma/web/activity_pub/transmogrifier/api.ex
Normal file
11
lib/pleroma/web/activity_pub/transmogrifier/api.ex
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ActivityPub.Transmogrifier.API do
|
||||||
|
@moduledoc """
|
||||||
|
Behaviour for the subset of Transmogrifier used by Publisher.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@callback prepare_outgoing(map()) :: {:ok, map()} | {:error, term()}
|
||||||
|
end
|
||||||
|
|
@ -82,7 +82,11 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||||
def unaddressed_message?(params),
|
def unaddressed_message?(params),
|
||||||
do:
|
do:
|
||||||
[params["to"], params["cc"], params["bto"], params["bcc"]]
|
[params["to"], params["cc"], params["bto"], params["bcc"]]
|
||||||
|> Enum.all?(&is_nil(&1))
|
|> Enum.all?(fn
|
||||||
|
nil -> true
|
||||||
|
[] -> true
|
||||||
|
_ -> false
|
||||||
|
end)
|
||||||
|
|
||||||
@spec recipient_in_message(User.t(), User.t(), map()) :: boolean()
|
@spec recipient_in_message(User.t(), User.t(), map()) :: boolean()
|
||||||
def recipient_in_message(%User{ap_id: ap_id} = recipient, %User{} = actor, params),
|
def recipient_in_message(%User{ap_id: ap_id} = recipient, %User{} = actor, params),
|
||||||
|
|
@ -859,8 +863,14 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||||
|
|
||||||
def update_report_state(_, _), do: {:error, "Unsupported state"}
|
def update_report_state(_, _), do: {:error, "Unsupported state"}
|
||||||
|
|
||||||
def strip_report_status_data(activity) do
|
def strip_report_status_data(%Activity{} = activity) do
|
||||||
[actor | reported_activities] = activity.data["object"]
|
with {:ok, new_data} <- strip_report_status_data(activity.data) do
|
||||||
|
{:ok, %{activity | data: new_data}}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def strip_report_status_data(data) do
|
||||||
|
[actor | reported_activities] = data["object"]
|
||||||
|
|
||||||
stripped_activities =
|
stripped_activities =
|
||||||
Enum.reduce(reported_activities, [], fn act, acc ->
|
Enum.reduce(reported_activities, [], fn act, acc ->
|
||||||
|
|
@ -870,9 +880,36 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
new_data = put_in(activity.data, ["object"], [actor | stripped_activities])
|
new_data = put_in(data, ["object"], [actor | stripped_activities])
|
||||||
|
|
||||||
{:ok, %{activity | data: new_data}}
|
{:ok, new_data}
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_anonymized_reporter do
|
||||||
|
with true <- Pleroma.Config.get([:activitypub, :anonymize_reporter]),
|
||||||
|
nickname when is_binary(nickname) <-
|
||||||
|
Pleroma.Config.get([:activitypub, :anonymize_reporter_local_nickname]),
|
||||||
|
%User{ap_id: ap_id, local: true} <- User.get_cached_by_nickname(nickname) do
|
||||||
|
ap_id
|
||||||
|
else
|
||||||
|
_ -> nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def maybe_anonymize_reporter(%Activity{data: data} = activity) do
|
||||||
|
new_data = maybe_anonymize_reporter(data)
|
||||||
|
%Activity{activity | actor: new_data["actor"], data: new_data}
|
||||||
|
end
|
||||||
|
|
||||||
|
def maybe_anonymize_reporter(activity) do
|
||||||
|
ap_id = get_anonymized_reporter()
|
||||||
|
|
||||||
|
if is_binary(ap_id) do
|
||||||
|
activity
|
||||||
|
|> Map.put("actor", ap_id)
|
||||||
|
else
|
||||||
|
activity
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_activity_visibility(activity, visibility) when visibility in @valid_visibilities do
|
def update_activity_visibility(activity, visibility) when visibility in @valid_visibilities do
|
||||||
|
|
|
||||||
59
lib/pleroma/web/activity_pub/views/collection_view_helper.ex
Normal file
59
lib/pleroma/web/activity_pub/views/collection_view_helper.ex
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# Copyright © 2025 Akkoma Authors <https://akkoma.dev/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ActivityPub.CollectionViewHelper do
|
||||||
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
|
|
||||||
|
def collection_page_offset(collection, iri, page, show_items \\ true, total \\ nil) do
|
||||||
|
offset = (page - 1) * 10
|
||||||
|
items = Enum.slice(collection, offset, 10)
|
||||||
|
items = Enum.map(items, fn user -> user.ap_id end)
|
||||||
|
total = total || length(collection)
|
||||||
|
|
||||||
|
map = %{
|
||||||
|
"id" => "#{iri}?page=#{page}",
|
||||||
|
"type" => "OrderedCollectionPage",
|
||||||
|
"partOf" => iri,
|
||||||
|
"totalItems" => total,
|
||||||
|
"orderedItems" => if(show_items, do: items, else: [])
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset + 10 < total do
|
||||||
|
Map.put(map, "next", "#{iri}?page=#{page + 1}")
|
||||||
|
else
|
||||||
|
map
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_omit_next(pagination, _items, nil), do: pagination
|
||||||
|
|
||||||
|
defp maybe_omit_next(pagination, items, limit) when is_binary(limit) do
|
||||||
|
case Integer.parse(limit) do
|
||||||
|
{limit, ""} -> maybe_omit_next(pagination, items, limit)
|
||||||
|
_ -> maybe_omit_next(pagination, items, nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_omit_next(pagination, items, limit) when is_number(limit) do
|
||||||
|
if Enum.count(items) < limit, do: Map.delete(pagination, "next"), else: pagination
|
||||||
|
end
|
||||||
|
|
||||||
|
def collection_page_keyset(
|
||||||
|
display_items,
|
||||||
|
pagination,
|
||||||
|
limit \\ nil,
|
||||||
|
skip_ap_context \\ false
|
||||||
|
) do
|
||||||
|
%{
|
||||||
|
"type" => "OrderedCollectionPage",
|
||||||
|
"orderedItems" => display_items
|
||||||
|
}
|
||||||
|
|> Map.merge(pagination)
|
||||||
|
|> maybe_omit_next(display_items, limit)
|
||||||
|
|> then(fn m ->
|
||||||
|
if skip_ap_context, do: m, else: Map.merge(m, Utils.make_json_ld_header())
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -6,7 +6,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectView do
|
||||||
use Pleroma.Web, :view
|
use Pleroma.Web, :view
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
alias Pleroma.Web.ActivityPub.CollectionViewHelper
|
||||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||||
|
alias Pleroma.Web.ControllerHelper
|
||||||
|
|
||||||
def render("object.json", %{object: %Object{} = object}) do
|
def render("object.json", %{object: %Object{} = object}) do
|
||||||
base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header(object.data)
|
base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header(object.data)
|
||||||
|
|
@ -15,26 +18,94 @@ defmodule Pleroma.Web.ActivityPub.ObjectView do
|
||||||
Map.merge(base, additional)
|
Map.merge(base, additional)
|
||||||
end
|
end
|
||||||
|
|
||||||
def render("object.json", %{object: %Activity{data: %{"type" => activity_type}} = activity})
|
def render("object.json", %{object: %Activity{} = activity}) do
|
||||||
when activity_type in ["Create", "Listen"] do
|
{:ok, ap_data} = Transmogrifier.prepare_outgoing(activity.data)
|
||||||
base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header(activity.data)
|
ap_data
|
||||||
object = Object.normalize(activity, fetch: false)
|
|
||||||
|
|
||||||
additional =
|
|
||||||
Transmogrifier.prepare_object(activity.data)
|
|
||||||
|> Map.put("object", Transmogrifier.prepare_object(object.data))
|
|
||||||
|
|
||||||
Map.merge(base, additional)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def render("object.json", %{object: %Activity{} = activity}) do
|
def render("object_replies.json", %{
|
||||||
base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header(activity.data)
|
conn: conn,
|
||||||
object_id = Object.normalize(activity, id_only: true)
|
render_params: %{object_ap_id: object_ap_id, page: "true"} = params
|
||||||
|
}) do
|
||||||
|
params = Map.put_new(params, :limit, 40)
|
||||||
|
|
||||||
additional =
|
items = ActivityPub.fetch_objects_for_replies_collection(object_ap_id, params)
|
||||||
Transmogrifier.prepare_object(activity.data)
|
display_items = map_reply_collection_items(items)
|
||||||
|> Map.put("object", object_id)
|
|
||||||
|
|
||||||
Map.merge(base, additional)
|
pagination = ControllerHelper.get_pagination_fields(conn, items, %{}, :asc)
|
||||||
|
|
||||||
|
CollectionViewHelper.collection_page_keyset(display_items, pagination, params[:limit])
|
||||||
|
end
|
||||||
|
|
||||||
|
def render(
|
||||||
|
"object_replies.json",
|
||||||
|
%{
|
||||||
|
render_params: %{object_ap_id: object_ap_id} = params
|
||||||
|
} = opts
|
||||||
|
) do
|
||||||
|
params =
|
||||||
|
params
|
||||||
|
|> Map.drop([:max_id, :min_id, :since_id, :object_ap_id])
|
||||||
|
|> Map.put_new(:limit, 40)
|
||||||
|
|> Map.put(:total, true)
|
||||||
|
|
||||||
|
%{total: total, items: items} =
|
||||||
|
ActivityPub.fetch_objects_for_replies_collection(object_ap_id, params)
|
||||||
|
|
||||||
|
display_items = map_reply_collection_items(items)
|
||||||
|
|
||||||
|
first_pagination = reply_collection_first_pagination(items, opts)
|
||||||
|
|
||||||
|
col_ap =
|
||||||
|
%{
|
||||||
|
"id" => object_ap_id <> "/replies",
|
||||||
|
"type" => "OrderedCollection",
|
||||||
|
"totalItems" => total
|
||||||
|
}
|
||||||
|
|
||||||
|
col_ap =
|
||||||
|
if total > 0 do
|
||||||
|
first_page =
|
||||||
|
CollectionViewHelper.collection_page_keyset(
|
||||||
|
display_items,
|
||||||
|
first_pagination,
|
||||||
|
params[:limit],
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
|
Map.put(col_ap, "first", first_page)
|
||||||
|
else
|
||||||
|
col_ap
|
||||||
|
end
|
||||||
|
|
||||||
|
if params[:skip_ap_ctx] do
|
||||||
|
col_ap
|
||||||
|
else
|
||||||
|
Map.merge(col_ap, Pleroma.Web.ActivityPub.Utils.make_json_ld_header())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp map_reply_collection_items(items), do: Enum.map(items, fn %{ap_id: ap_id} -> ap_id end)
|
||||||
|
|
||||||
|
defp reply_collection_first_pagination(items, %{conn: %Plug.Conn{} = conn}) do
|
||||||
|
pagination = ControllerHelper.get_pagination_fields(conn, items, %{"page" => true}, :asc)
|
||||||
|
Map.put(pagination, "id", Phoenix.Controller.current_url(conn, %{"page" => true}))
|
||||||
|
end
|
||||||
|
|
||||||
|
defp reply_collection_first_pagination(items, %{render_params: %{object_ap_id: object_ap_id}}) do
|
||||||
|
%{
|
||||||
|
"id" => object_ap_id <> "/replies?page=true",
|
||||||
|
"partOf" => object_ap_id <> "/replies"
|
||||||
|
}
|
||||||
|
|> then(fn m ->
|
||||||
|
case items do
|
||||||
|
[] ->
|
||||||
|
m
|
||||||
|
|
||||||
|
i ->
|
||||||
|
next_id = object_ap_id <> "/replies?page=true&min_id=#{List.last(i)[:id]}"
|
||||||
|
Map.put(m, "next", next_id)
|
||||||
|
end
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Web.ActivityPub.CollectionViewHelper
|
||||||
alias Pleroma.Web.ActivityPub.ObjectView
|
alias Pleroma.Web.ActivityPub.ObjectView
|
||||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
|
|
@ -164,7 +165,13 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||||
0
|
0
|
||||||
end
|
end
|
||||||
|
|
||||||
collection(following, "#{user.ap_id}/following", page, showing_items, total)
|
CollectionViewHelper.collection_page_offset(
|
||||||
|
following,
|
||||||
|
"#{user.ap_id}/following",
|
||||||
|
page,
|
||||||
|
showing_items,
|
||||||
|
total
|
||||||
|
)
|
||||||
|> Map.merge(Utils.make_json_ld_header())
|
|> Map.merge(Utils.make_json_ld_header())
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -189,7 +196,12 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||||
"totalItems" => total,
|
"totalItems" => total,
|
||||||
"first" =>
|
"first" =>
|
||||||
if showing_items do
|
if showing_items do
|
||||||
collection(following, "#{user.ap_id}/following", 1, !user.hide_follows)
|
CollectionViewHelper.collection_page_offset(
|
||||||
|
following,
|
||||||
|
"#{user.ap_id}/following",
|
||||||
|
1,
|
||||||
|
!user.hide_follows
|
||||||
|
)
|
||||||
else
|
else
|
||||||
"#{user.ap_id}/following?page=1"
|
"#{user.ap_id}/following?page=1"
|
||||||
end
|
end
|
||||||
|
|
@ -212,7 +224,13 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||||
0
|
0
|
||||||
end
|
end
|
||||||
|
|
||||||
collection(followers, "#{user.ap_id}/followers", page, showing_items, total)
|
CollectionViewHelper.collection_page_offset(
|
||||||
|
followers,
|
||||||
|
"#{user.ap_id}/followers",
|
||||||
|
page,
|
||||||
|
showing_items,
|
||||||
|
total
|
||||||
|
)
|
||||||
|> Map.merge(Utils.make_json_ld_header())
|
|> Map.merge(Utils.make_json_ld_header())
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -236,7 +254,12 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||||
"type" => "OrderedCollection",
|
"type" => "OrderedCollection",
|
||||||
"first" =>
|
"first" =>
|
||||||
if showing_items do
|
if showing_items do
|
||||||
collection(followers, "#{user.ap_id}/followers", 1, showing_items, total)
|
CollectionViewHelper.collection_page_offset(
|
||||||
|
followers,
|
||||||
|
"#{user.ap_id}/followers",
|
||||||
|
1,
|
||||||
|
showing_items
|
||||||
|
)
|
||||||
else
|
else
|
||||||
"#{user.ap_id}/followers?page=1"
|
"#{user.ap_id}/followers?page=1"
|
||||||
end
|
end
|
||||||
|
|
@ -256,7 +279,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||||
|
|
||||||
def render("activity_collection_page.json", %{
|
def render("activity_collection_page.json", %{
|
||||||
activities: activities,
|
activities: activities,
|
||||||
iri: iri,
|
|
||||||
pagination: pagination
|
pagination: pagination
|
||||||
}) do
|
}) do
|
||||||
collection =
|
collection =
|
||||||
|
|
@ -265,13 +287,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||||
data
|
data
|
||||||
end)
|
end)
|
||||||
|
|
||||||
%{
|
CollectionViewHelper.collection_page_keyset(collection, pagination)
|
||||||
"type" => "OrderedCollectionPage",
|
|
||||||
"partOf" => iri,
|
|
||||||
"orderedItems" => collection
|
|
||||||
}
|
|
||||||
|> Map.merge(Utils.make_json_ld_header())
|
|
||||||
|> Map.merge(pagination)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def render("featured.json", %{
|
def render("featured.json", %{
|
||||||
|
|
@ -299,27 +315,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||||
Map.put(map, "totalItems", total)
|
Map.put(map, "totalItems", total)
|
||||||
end
|
end
|
||||||
|
|
||||||
def collection(collection, iri, page, show_items \\ true, total \\ nil) do
|
|
||||||
offset = (page - 1) * 10
|
|
||||||
items = Enum.slice(collection, offset, 10)
|
|
||||||
items = Enum.map(items, fn user -> user.ap_id end)
|
|
||||||
total = total || length(collection)
|
|
||||||
|
|
||||||
map = %{
|
|
||||||
"id" => "#{iri}?page=#{page}",
|
|
||||||
"type" => "OrderedCollectionPage",
|
|
||||||
"partOf" => iri,
|
|
||||||
"totalItems" => total,
|
|
||||||
"orderedItems" => if(show_items, do: items, else: [])
|
|
||||||
}
|
|
||||||
|
|
||||||
if offset < total do
|
|
||||||
Map.put(map, "next", "#{iri}?page=#{page + 1}")
|
|
||||||
else
|
|
||||||
map
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp maybe_make_image(func, description, key, user) do
|
defp maybe_make_image(func, description, key, user) do
|
||||||
if image = func.(user, no_default: true) do
|
if image = func.(user, no_default: true) do
|
||||||
%{
|
%{
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,22 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
|
||||||
|> Pleroma.List.member?(user)
|
|> Pleroma.List.member?(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def visible_for_user?(%Activity{object: %Object{} = object} = activity, nil) do
|
||||||
|
activity_visibility? = restrict_unauthenticated_access?(activity)
|
||||||
|
activity_public? = public?(activity) and not local_public?(activity)
|
||||||
|
object_visibility? = restrict_unauthenticated_access?(object)
|
||||||
|
object_public? = public?(object) and not local_public?(object)
|
||||||
|
|
||||||
|
# Activity could be local, but object might not (Announce/Like)
|
||||||
|
cond do
|
||||||
|
activity_visibility? or object_visibility? ->
|
||||||
|
false
|
||||||
|
|
||||||
|
true ->
|
||||||
|
activity_public? and object_public?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def visible_for_user?(%{__struct__: module} = message, nil)
|
def visible_for_user?(%{__struct__: module} = message, nil)
|
||||||
when module in [Activity, Object] do
|
when module in [Activity, Object] do
|
||||||
if restrict_unauthenticated_access?(message),
|
if restrict_unauthenticated_access?(message),
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue