diff --git a/.gitignore b/.gitignore
index 6ae21e914..599b52b9e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,8 +27,6 @@ erl_crash.dump
# variables.
/config/*.secret.exs
/config/generated_config.exs
-/config/*.env
-
# Database setup file, some may forget to delete it
/config/setup_db.psql
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index c9ab84892..121e4abfe 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -22,6 +22,7 @@ stages:
- docker
before_script:
+ - apt-get update && apt-get install -y cmake
- mix local.hex --force
- mix local.rebar --force
@@ -58,25 +59,27 @@ unit-testing:
alias: postgres
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
script:
- - apt-get update && apt-get install -y libimage-exiftool-perl
+ - apt-get update && apt-get install -y libimage-exiftool-perl ffmpeg
- mix deps.get
- mix ecto.create
- mix ecto.migrate
- mix coveralls --preload-modules
-federated-testing:
- stage: test
- cache: *testing_cache_policy
- services:
- - name: minibikini/postgres-with-rum:12
- alias: postgres
- command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- script:
- - mix deps.get
- - mix ecto.create
- - mix ecto.migrate
- - epmd -daemon
- - mix test --trace --only federated
+# Removed to fix CI issue. In this early state it wasn't adding much value anyway.
+# TODO Fix and reinstate federated testing
+# federated-testing:
+# stage: test
+# cache: *testing_cache_policy
+# services:
+# - name: minibikini/postgres-with-rum:12
+# alias: postgres
+# command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
+# script:
+# - mix deps.get
+# - mix ecto.create
+# - mix ecto.migrate
+# - epmd -daemon
+# - mix test --trace --only federated
unit-testing-rum:
stage: test
@@ -90,7 +93,7 @@ unit-testing-rum:
<<: *global_variables
RUM_ENABLED: "true"
script:
- - apt-get update && apt-get install -y libimage-exiftool-perl
+ - apt-get update && apt-get install -y libimage-exiftool-perl ffmpeg
- mix deps.get
- mix ecto.create
- mix ecto.migrate
@@ -193,6 +196,7 @@ amd64:
variables: &release-variables
MIX_ENV: prod
before_script: &before-release
+ - apt-get update && apt-get install -y cmake
- echo "import Mix.Config" > config/prod.secret.exs
- mix local.hex --force
- mix local.rebar --force
@@ -211,7 +215,7 @@ amd64-musl:
cache: *release-cache
variables: *release-variables
before_script: &before-release-musl
- - apk add git gcc g++ musl-dev make
+ - apk add git gcc g++ musl-dev make cmake
- echo "import Mix.Config" > config/prod.secret.exs
- mix local.hex --force
- mix local.rebar --force
@@ -278,6 +282,8 @@ docker:
IMAGE_TAG_SLUG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
IMAGE_TAG_LATEST: $CI_REGISTRY_IMAGE:latest
IMAGE_TAG_LATEST_STABLE: $CI_REGISTRY_IMAGE:latest-stable
+ DOCKER_BUILDX_URL: https://github.com/docker/buildx/releases/download/v0.4.1/buildx-v0.4.1.linux-amd64
+ DOCKER_BUILDX_HASH: 71a7d01439aa8c165a25b59c44d3f016fddbd98b
before_script: &before-docker
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker pull $IMAGE_TAG_SLUG || true
@@ -285,10 +291,14 @@ docker:
- export CI_VCS_REF=$CI_COMMIT_SHORT_SHA
allow_failure: true
script:
- - docker build --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST .
- - docker push $IMAGE_TAG
- - docker push $IMAGE_TAG_SLUG
- - docker push $IMAGE_TAG_LATEST
+ - mkdir -p /root/.docker/cli-plugins
+ - wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
+ - echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
+ - chmod +x ~/.docker/cli-plugins/docker-buildx
+ - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
+ - docker buildx create --name mbuilder --driver docker-container --use
+ - docker buildx inspect --bootstrap
+ - docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST .
tags:
- dind
only:
@@ -303,10 +313,14 @@ docker-stable:
before_script: *before-docker
allow_failure: true
script:
- - docker build --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST_STABLE .
- - docker push $IMAGE_TAG
- - docker push $IMAGE_TAG_SLUG
- - docker push $IMAGE_TAG_LATEST_STABLE
+ - mkdir -p /root/.docker/cli-plugins
+ - wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
+ - echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
+ - chmod +x ~/.docker/cli-plugins/docker-buildx
+ - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
+ - docker buildx create --name mbuilder --driver docker-container --use
+ - docker buildx inspect --bootstrap
+ - docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST_STABLE .
tags:
- dind
only:
@@ -321,9 +335,15 @@ docker-release:
before_script: *before-docker
allow_failure: true
script:
- - docker build --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG .
- - docker push $IMAGE_TAG
- - docker push $IMAGE_TAG_SLUG
+ script:
+ - mkdir -p /root/.docker/cli-plugins
+ - wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
+ - echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
+ - chmod +x ~/.docker/cli-plugins/docker-buildx
+ - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
+ - docker buildx create --name mbuilder --driver docker-container --use
+ - docker buildx inspect --bootstrap
+ - docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG .
tags:
- dind
only:
diff --git a/.gitlab/merge_request_templates/Release.md b/.gitlab/merge_request_templates/Release.md
index 237f74e00..b2c772696 100644
--- a/.gitlab/merge_request_templates/Release.md
+++ b/.gitlab/merge_request_templates/Release.md
@@ -3,3 +3,4 @@
* [ ] Compile a changelog
* [ ] Create an MR with an announcement to pleroma.social
* [ ] Tag the release
+* [ ] Merge `stable` into `develop` (in case the fixes are already in develop, use `git merge -s ours --no-commit` and manually merge the changelogs)
diff --git a/CC-BY-4.0 b/CC-BY-4.0
new file mode 100644
index 000000000..4ea99c213
--- /dev/null
+++ b/CC-BY-4.0
@@ -0,0 +1,395 @@
+Attribution 4.0 International
+
+=======================================================================
+
+Creative Commons Corporation ("Creative Commons") is not a law firm and
+does not provide legal services or legal advice. Distribution of
+Creative Commons public licenses does not create a lawyer-client or
+other relationship. Creative Commons makes its licenses and related
+information available on an "as-is" basis. Creative Commons gives no
+warranties regarding its licenses, any material licensed under their
+terms and conditions, or any related information. Creative Commons
+disclaims all liability for damages resulting from their use to the
+fullest extent possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and
+conditions that creators and other rights holders may use to share
+original works of authorship and other material subject to copyright
+and certain other rights specified in the public license below. The
+following considerations are for informational purposes only, are not
+exhaustive, and do not form part of our licenses.
+
+ Considerations for licensors: Our public licenses are
+ intended for use by those authorized to give the public
+ permission to use material in ways otherwise restricted by
+ copyright and certain other rights. Our licenses are
+ irrevocable. Licensors should read and understand the terms
+ and conditions of the license they choose before applying it.
+ Licensors should also secure all rights necessary before
+ applying our licenses so that the public can reuse the
+ material as expected. Licensors should clearly mark any
+ material not subject to the license. This includes other CC-
+ licensed material, or material used under an exception or
+ limitation to copyright. More considerations for licensors:
+ wiki.creativecommons.org/Considerations_for_licensors
+
+ Considerations for the public: By using one of our public
+ licenses, a licensor grants the public permission to use the
+ licensed material under specified terms and conditions. If
+ the licensor's permission is not necessary for any reason--for
+ example, because of any applicable exception or limitation to
+ copyright--then that use is not regulated by the license. Our
+ licenses grant only permissions under copyright and certain
+ other rights that a licensor has authority to grant. Use of
+ the licensed material may still be restricted for other
+ reasons, including because others have copyright or other
+ rights in the material. A licensor may make special requests,
+ such as asking that all changes be marked or described.
+ Although not required by our licenses, you are encouraged to
+ respect those requests where reasonable. More considerations
+ for the public:
+ wiki.creativecommons.org/Considerations_for_licensees
+
+=======================================================================
+
+Creative Commons Attribution 4.0 International Public License
+
+By exercising the Licensed Rights (defined below), You accept and agree
+to be bound by the terms and conditions of this Creative Commons
+Attribution 4.0 International Public License ("Public License"). To the
+extent this Public License may be interpreted as a contract, You are
+granted the Licensed Rights in consideration of Your acceptance of
+these terms and conditions, and the Licensor grants You such rights in
+consideration of benefits the Licensor receives from making the
+Licensed Material available under these terms and conditions.
+
+
+Section 1 -- Definitions.
+
+ a. Adapted Material means material subject to Copyright and Similar
+ Rights that is derived from or based upon the Licensed Material
+ and in which the Licensed Material is translated, altered,
+ arranged, transformed, or otherwise modified in a manner requiring
+ permission under the Copyright and Similar Rights held by the
+ Licensor. For purposes of this Public License, where the Licensed
+ Material is a musical work, performance, or sound recording,
+ Adapted Material is always produced where the Licensed Material is
+ synched in timed relation with a moving image.
+
+ b. Adapter's License means the license You apply to Your Copyright
+ and Similar Rights in Your contributions to Adapted Material in
+ accordance with the terms and conditions of this Public License.
+
+ c. Copyright and Similar Rights means copyright and/or similar rights
+ closely related to copyright including, without limitation,
+ performance, broadcast, sound recording, and Sui Generis Database
+ Rights, without regard to how the rights are labeled or
+ categorized. For purposes of this Public License, the rights
+ specified in Section 2(b)(1)-(2) are not Copyright and Similar
+ Rights.
+
+ d. Effective Technological Measures means those measures that, in the
+ absence of proper authority, may not be circumvented under laws
+ fulfilling obligations under Article 11 of the WIPO Copyright
+ Treaty adopted on December 20, 1996, and/or similar international
+ agreements.
+
+ e. Exceptions and Limitations means fair use, fair dealing, and/or
+ any other exception or limitation to Copyright and Similar Rights
+ that applies to Your use of the Licensed Material.
+
+ f. Licensed Material means the artistic or literary work, database,
+ or other material to which the Licensor applied this Public
+ License.
+
+ g. Licensed Rights means the rights granted to You subject to the
+ terms and conditions of this Public License, which are limited to
+ all Copyright and Similar Rights that apply to Your use of the
+ Licensed Material and that the Licensor has authority to license.
+
+ h. Licensor means the individual(s) or entity(ies) granting rights
+ under this Public License.
+
+ i. Share means to provide material to the public by any means or
+ process that requires permission under the Licensed Rights, such
+ as reproduction, public display, public performance, distribution,
+ dissemination, communication, or importation, and to make material
+ available to the public including in ways that members of the
+ public may access the material from a place and at a time
+ individually chosen by them.
+
+ j. Sui Generis Database Rights means rights other than copyright
+ resulting from Directive 96/9/EC of the European Parliament and of
+ the Council of 11 March 1996 on the legal protection of databases,
+ as amended and/or succeeded, as well as other essentially
+ equivalent rights anywhere in the world.
+
+ k. You means the individual or entity exercising the Licensed Rights
+ under this Public License. Your has a corresponding meaning.
+
+
+Section 2 -- Scope.
+
+ a. License grant.
+
+ 1. Subject to the terms and conditions of this Public License,
+ the Licensor hereby grants You a worldwide, royalty-free,
+ non-sublicensable, non-exclusive, irrevocable license to
+ exercise the Licensed Rights in the Licensed Material to:
+
+ a. reproduce and Share the Licensed Material, in whole or
+ in part; and
+
+ b. produce, reproduce, and Share Adapted Material.
+
+ 2. Exceptions and Limitations. For the avoidance of doubt, where
+ Exceptions and Limitations apply to Your use, this Public
+ License does not apply, and You do not need to comply with
+ its terms and conditions.
+
+ 3. Term. The term of this Public License is specified in Section
+ 6(a).
+
+ 4. Media and formats; technical modifications allowed. The
+ Licensor authorizes You to exercise the Licensed Rights in
+ all media and formats whether now known or hereafter created,
+ and to make technical modifications necessary to do so. The
+ Licensor waives and/or agrees not to assert any right or
+ authority to forbid You from making technical modifications
+ necessary to exercise the Licensed Rights, including
+ technical modifications necessary to circumvent Effective
+ Technological Measures. For purposes of this Public License,
+ simply making modifications authorized by this Section 2(a)
+ (4) never produces Adapted Material.
+
+ 5. Downstream recipients.
+
+ a. Offer from the Licensor -- Licensed Material. Every
+ recipient of the Licensed Material automatically
+ receives an offer from the Licensor to exercise the
+ Licensed Rights under the terms and conditions of this
+ Public License.
+
+ b. No downstream restrictions. You may not offer or impose
+ any additional or different terms or conditions on, or
+ apply any Effective Technological Measures to, the
+ Licensed Material if doing so restricts exercise of the
+ Licensed Rights by any recipient of the Licensed
+ Material.
+
+ 6. No endorsement. Nothing in this Public License constitutes or
+ may be construed as permission to assert or imply that You
+ are, or that Your use of the Licensed Material is, connected
+ with, or sponsored, endorsed, or granted official status by,
+ the Licensor or others designated to receive attribution as
+ provided in Section 3(a)(1)(A)(i).
+
+ b. Other rights.
+
+ 1. Moral rights, such as the right of integrity, are not
+ licensed under this Public License, nor are publicity,
+ privacy, and/or other similar personality rights; however, to
+ the extent possible, the Licensor waives and/or agrees not to
+ assert any such rights held by the Licensor to the limited
+ extent necessary to allow You to exercise the Licensed
+ Rights, but not otherwise.
+
+ 2. Patent and trademark rights are not licensed under this
+ Public License.
+
+ 3. To the extent possible, the Licensor waives any right to
+ collect royalties from You for the exercise of the Licensed
+ Rights, whether directly or through a collecting society
+ under any voluntary or waivable statutory or compulsory
+ licensing scheme. In all other cases the Licensor expressly
+ reserves any right to collect such royalties.
+
+
+Section 3 -- License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the
+following conditions.
+
+ a. Attribution.
+
+ 1. If You Share the Licensed Material (including in modified
+ form), You must:
+
+ a. retain the following if it is supplied by the Licensor
+ with the Licensed Material:
+
+ i. identification of the creator(s) of the Licensed
+ Material and any others designated to receive
+ attribution, in any reasonable manner requested by
+ the Licensor (including by pseudonym if
+ designated);
+
+ ii. a copyright notice;
+
+ iii. a notice that refers to this Public License;
+
+ iv. a notice that refers to the disclaimer of
+ warranties;
+
+ v. a URI or hyperlink to the Licensed Material to the
+ extent reasonably practicable;
+
+ b. indicate if You modified the Licensed Material and
+ retain an indication of any previous modifications; and
+
+ c. indicate the Licensed Material is licensed under this
+ Public License, and include the text of, or the URI or
+ hyperlink to, this Public License.
+
+ 2. You may satisfy the conditions in Section 3(a)(1) in any
+ reasonable manner based on the medium, means, and context in
+ which You Share the Licensed Material. For example, it may be
+ reasonable to satisfy the conditions by providing a URI or
+ hyperlink to a resource that includes the required
+ information.
+
+ 3. If requested by the Licensor, You must remove any of the
+ information required by Section 3(a)(1)(A) to the extent
+ reasonably practicable.
+
+ 4. If You Share Adapted Material You produce, the Adapter's
+ License You apply must not prevent recipients of the Adapted
+ Material from complying with this Public License.
+
+
+Section 4 -- Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that
+apply to Your use of the Licensed Material:
+
+ a. for the avoidance of doubt, Section 2(a)(1) grants You the right
+ to extract, reuse, reproduce, and Share all or a substantial
+ portion of the contents of the database;
+
+ b. if You include all or a substantial portion of the database
+ contents in a database in which You have Sui Generis Database
+ Rights, then the database in which You have Sui Generis Database
+ Rights (but not its individual contents) is Adapted Material; and
+
+ c. You must comply with the conditions in Section 3(a) if You Share
+ all or a substantial portion of the contents of the database.
+
+For the avoidance of doubt, this Section 4 supplements and does not
+replace Your obligations under this Public License where the Licensed
+Rights include other Copyright and Similar Rights.
+
+
+Section 5 -- Disclaimer of Warranties and Limitation of Liability.
+
+ a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
+ EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
+ AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
+ IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
+ WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
+ ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
+ KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
+ ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
+
+ b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
+ TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
+ NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
+ INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
+ COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
+ USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
+ DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
+ IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
+
+ c. The disclaimer of warranties and limitation of liability provided
+ above shall be interpreted in a manner that, to the extent
+ possible, most closely approximates an absolute disclaimer and
+ waiver of all liability.
+
+
+Section 6 -- Term and Termination.
+
+ a. This Public License applies for the term of the Copyright and
+ Similar Rights licensed here. However, if You fail to comply with
+ this Public License, then Your rights under this Public License
+ terminate automatically.
+
+ b. Where Your right to use the Licensed Material has terminated under
+ Section 6(a), it reinstates:
+
+ 1. automatically as of the date the violation is cured, provided
+ it is cured within 30 days of Your discovery of the
+ violation; or
+
+ 2. upon express reinstatement by the Licensor.
+
+ For the avoidance of doubt, this Section 6(b) does not affect any
+ right the Licensor may have to seek remedies for Your violations
+ of this Public License.
+
+ c. For the avoidance of doubt, the Licensor may also offer the
+ Licensed Material under separate terms or conditions or stop
+ distributing the Licensed Material at any time; however, doing so
+ will not terminate this Public License.
+
+ d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
+ License.
+
+
+Section 7 -- Other Terms and Conditions.
+
+ a. The Licensor shall not be bound by any additional or different
+ terms or conditions communicated by You unless expressly agreed.
+
+ b. Any arrangements, understandings, or agreements regarding the
+ Licensed Material not stated herein are separate from and
+ independent of the terms and conditions of this Public License.
+
+
+Section 8 -- Interpretation.
+
+ a. For the avoidance of doubt, this Public License does not, and
+ shall not be interpreted to, reduce, limit, restrict, or impose
+ conditions on any use of the Licensed Material that could lawfully
+ be made without permission under this Public License.
+
+ b. To the extent possible, if any provision of this Public License is
+ deemed unenforceable, it shall be automatically reformed to the
+ minimum extent necessary to make it enforceable. If the provision
+ cannot be reformed, it shall be severed from this Public License
+ without affecting the enforceability of the remaining terms and
+ conditions.
+
+ c. No term or condition of this Public License will be waived and no
+ failure to comply consented to unless expressly agreed to by the
+ Licensor.
+
+ d. Nothing in this Public License constitutes or may be interpreted
+ as a limitation upon, or waiver of, any privileges and immunities
+ that apply to the Licensor or You, including from the legal
+ processes of any jurisdiction or authority.
+
+
+=======================================================================
+
+Creative Commons is not a party to its public
+licenses. Notwithstanding, Creative Commons may elect to apply one of
+its public licenses to material it publishes and in those instances
+will be considered the “Licensor.” The text of the Creative Commons
+public licenses is dedicated to the public domain under the CC0 Public
+Domain Dedication. Except for the limited purpose of indicating that
+material is shared under a Creative Commons public license or as
+otherwise permitted by the Creative Commons policies published at
+creativecommons.org/policies, Creative Commons does not authorize the
+use of the trademark "Creative Commons" or any other trademark or logo
+of Creative Commons without its prior written consent including,
+without limitation, in connection with any unauthorized modifications
+to any of its public licenses or any other arrangements,
+understandings, or agreements concerning use of licensed material. For
+the avoidance of doubt, this paragraph does not form part of the
+public licenses.
+
+Creative Commons may be contacted at creativecommons.org.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 71c2c0317..97908caf7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,20 +3,127 @@ 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/).
-## [unreleased]
+## Unreleased
+
+### Added
+- Mix tasks for controlling user account confirmation status in bulk (`mix pleroma.user confirm_all` and `mix pleroma.user unconfirm_all`)
+- Mix task for sending confirmation emails to all unconfirmed users (`mix pleroma.email send_confirmation_mails`)
+- Mix task option for force-unfollowing relays
### Changed
+
+- **Breaking:** Pleroma Admin API: emoji packs and files routes changed.
+- **Breaking:** Sensitive/NSFW statuses no longer disable link previews.
+- Search: Users are now findable by their urls.
+- Renamed `:await_up_timeout` in `:connections_pool` namespace to `:connect_timeout`, old name is deprecated.
+- Renamed `:timeout` in `pools` namespace to `:recv_timeout`, old name is deprecated.
+- The `discoverable` field in the `User` struct will now add a NOINDEX metatag to profile pages when false.
+- Users with the `discoverable` field set to false will not show up in searches.
+- Minimum lifetime for ephmeral activities changed to 10 minutes and made configurable (`:min_lifetime` option).
+- Introduced optional dependencies on `ffmpeg`, `ImageMagick`, `exiftool` software packages. Please refer to `docs/installation/optional/media_graphics_packages.md`.
+
+### Added
+- Media preview proxy (requires `ffmpeg` and `ImageMagick` to be installed and media proxy to be enabled; see `:media_preview_proxy` config for more details).
+- Pleroma API: Importing the mutes users from CSV files.
+- Experimental websocket-based federation between Pleroma instances.
+
+
+ API Changes
+
+- Pleroma API: Importing the mutes users from CSV files.
+- Admin API: Importing emoji from a zip file
+- Pleroma API: Pagination for remote/local packs and emoji.
+
+
+
+### Removed
+
+- **Breaking:** `Pleroma.Workers.Cron.StatsWorker` setting from Oban `:crontab` (moved to a simpler implementation).
+- **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).
+- 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.
+
+### Fixed
+
+- Add documented-but-missing chat pagination.
+- Allow sending out emails again.
+
+## Unreleased (Patch)
+
+### Changed
+- API: Empty parameter values for integer parameters are now ignored in non-strict validaton mode.
+
+## [2.1.2] - 2020-09-17
+
+### Security
+
+- Fix most MRF rules either crashing or not being applied to objects passed into the Common Pipeline (ChatMessage, Question, Answer, Audio, Event).
+
+### Fixed
+
+- Welcome Chat messages preventing user registration with MRF Simple Policy applied to the local instance.
+- Mastodon API: the public timeline returning an error when the `reply_visibility` parameter is set to `self` for an unauthenticated user.
+- Mastodon Streaming API: Handler crashes on authentication failures, resulting in error logs.
+- Mastodon Streaming API: Error logs on client pings.
+- Rich media: Log spam on failures. Now the error is only logged once per attempt.
+
+### Changed
+
+- Rich Media: A HEAD request is now done to the url, to ensure it has the appropriate content type and size before proceeding with a GET.
+
+### Upgrade notes
+
+1. Restart Pleroma
+
+## [2.1.1] - 2020-09-08
+
+### 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 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.
+
+### Changed
+
+- **Breaking:** The metadata providers RelMe and Feed are no longer configurable. RelMe should always be activated and Feed only provides a header tag for the actual RSS/Atom feed when the instance is public.
+- Improved error message when cmake is not available at build stage.
+
+### Added
+- Rich media failure tracking (along with `:failure_backoff` option).
+
+
+ Admin API Changes
+
+- Add `PATCH /api/pleroma/admin/instance_document/:document_name` to modify the Terms of Service and Instance Panel HTML pages via Admin API
+
+
+### Fixed
+- 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
+- Mastodon API: Search parameter `following` now correctly returns the followings rather than the followers
+- Mastodon API: Timelines hanging for (`number of posts with links * rich media timeout`) in the worst case.
+ Reduced to just rich media timeout.
+- Mastodon API: Cards being wrong for preview statuses due to cache key collision.
+- Password resets no longer processed for deactivated accounts.
+- Favicon scraper raising exceptions on URLs longer than 255 characters.
+
+## [2.1.0] - 2020-08-28
+
+### Changed
+
+- **Breaking:** The default descriptions on uploads are now empty. The old behavior (filename as default) can be configured, see the cheat sheet.
- **Breaking:** Added the ObjectAgePolicy to the default set of MRFs. This will delist and strip the follower collection of any message received that is older than 7 days. This will stop users from seeing very old messages in the timelines. The messages can still be viewed on the user's page and in conversations. They also still trigger notifications.
- **Breaking:** Elixir >=1.9 is now required (was >= 1.8)
- **Breaking:** Configuration: `:auto_linker, :opts` moved to `:pleroma, Pleroma.Formatter`. Old config namespace is deprecated.
+- **Breaking:** Configuration: `:instance, welcome_user_nickname` moved to `:welcome, :direct_message, :sender_nickname`, `:instance, :welcome_message` moved to `:welcome, :direct_message, :message`. Old config namespace is deprecated.
+- **Breaking:** LDAP: Fallback to local database authentication has been removed for security reasons and lack of a mechanism to ensure the passwords are synchronized when LDAP passwords are updated.
+- **Breaking** Changed defaults for `:restrict_unauthenticated` so that when `:instance, :public` is set to `false` then all `:restrict_unauthenticated` items be effectively set to `true`. If you'd like to allow unauthenticated access to specific API endpoints on a private instance, please explicitly set `:restrict_unauthenticated` to non-default value in `config/prod.secret.exs`.
- In Conversations, return only direct messages as `last_status`
- Using the `only_media` filter on timelines will now exclude reblog media
- MFR policy to set global expiration for all local Create activities
- OGP rich media parser merged with TwitterCard
- Configuration: `:instance, rewrite_policy` moved to `:mrf, policies`, `:instance, :mrf_transparency` moved to `:mrf, :transparency`, `:instance, :mrf_transparency_exclusions` moved to `:mrf, :transparency_exclusions`. Old config namespace is deprecated.
- Configuration: `:media_proxy, whitelist` format changed to host with scheme (e.g. `http://example.com` instead of `example.com`). Domain format is deprecated.
-- **Breaking:** Configuration: `:instance, welcome_user_nickname` moved to `:welcome, :direct_message, :sender_nickname`, `:instance, :welcome_message` moved to `:welcome, :direct_message, :message`. Old config namespace is deprecated.
-- **Breaking:** LDAP: Fallback to local database authentication has been removed for security reasons and lack of a mechanism to ensure the passwords are synchronized when LDAP passwords are updated.
API Changes
@@ -24,33 +131,37 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- **Breaking:** Pleroma API: The routes to update avatar, banner and background have been removed.
- **Breaking:** Image description length is limited now.
- **Breaking:** Emoji API: changed methods and renamed routes.
+- **Breaking:** Notification Settings API for suppressing notifications has been simplified down to `block_from_strangers`.
+- **Breaking:** Notification Settings API option for hiding push notification contents has been renamed to `hide_notification_contents`.
- MastodonAPI: Allow removal of avatar, banner and background.
- Streaming: Repeats of a user's posts will no longer be pushed to the user's stream.
- Mastodon API: Added `pleroma.metadata.fields_limits` to /api/v1/instance
- Mastodon API: On deletion, returns the original post text.
- Mastodon API: Add `pleroma.unread_count` to the Marker entity.
-- **Breaking:** Notification Settings API for suppressing notifications
- has been simplified down to `block_from_strangers`.
-- **Breaking:** Notification Settings API option for hiding push notification
- contents has been renamed to `hide_notification_contents`
- Mastodon API: Added `pleroma.metadata.post_formats` to /api/v1/instance
- Mastodon API (legacy): Allow query parameters for `/api/v1/domain_blocks`, e.g. `/api/v1/domain_blocks?domain=badposters.zone`
+- Mastodon API: Make notifications about statuses from muted users and threads read automatically
- Pleroma API: `/api/pleroma/captcha` responses now include `seconds_valid` with an integer value.
+
Admin API Changes
+- **Breaking** Changed relay `/api/pleroma/admin/relay` endpoints response format.
- Status visibility stats: now can return stats per instance.
-
- Mix task to refresh counter cache (`mix pleroma.refresh_counter_cache`)
+
### Removed
+
- **Breaking:** removed `with_move` parameter from notifications timeline.
### Added
+- Frontends: Add mix task to install frontends.
+- Frontends: Add configurable frontends for primary and admin fe.
- Configuration: Added a blacklist for email servers.
- Chats: Added `accepts_chat_messages` field to user, exposed in APIs and federation.
- Chats: Added support for federated chats. For details, see the docs.
@@ -93,6 +204,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Fixed
+- Fix list pagination and other list issues.
- Support pagination in conversations API
- **Breaking**: SimplePolicy `:reject` and `:accept` allow deletions again
- Fix follower/blocks import when nicknames starts with @
@@ -106,12 +218,81 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fix edge case where MediaProxy truncates media, usually caused when Caddy is serving content for the other Federated instance.
- Emoji Packs could not be listed when instance was set to `public: false`
- Fix whole_word always returning false on filter get requests
+- Migrations not working on OTP releases if the database was connected over ssl
+- Fix relay following
-## [Unreleased (patch)]
+## [2.0.7] - 2020-06-13
+
+### Security
+- Fix potential DoSes exploiting atom leaks in rich media parser and the `UserAllowListPolicy` MRF policy
### Fixed
+- CSP: not allowing images/media from every host when mediaproxy is disabled
+- CSP: not adding mediaproxy base url to image/media hosts
+- StaticFE missing the CSS file
+
+### Upgrade notes
+
+1. Restart Pleroma
+
+## [2.0.6] - 2020-06-09
+
+### Security
+- CSP: harden `image-src` and `media-src` when MediaProxy is used
+
+### Fixed
+- AP C2S: Fix pagination in inbox/outbox
+- Various compilation errors on OTP 23
+- Mastodon API streaming: Repeats from muted threads not being filtered
+
+### Changed
+- Various database performance improvements
+
+### Upgrade notes
+1. Run database migrations (inside Pleroma directory):
+ - OTP: `./bin/pleroma_ctl migrate`
+ - From Source: `mix ecto.migrate`
+2. Restart Pleroma
+
+## [2.0.5] - 2020-05-13
+
+### Security
+- Fix possible private status leaks in Mastodon Streaming API
+
+### Fixed
+- Crashes when trying to block a user if block federation is disabled
+- Not being able to start the instance without `erlang-eldap` installed
+- Users with bios over the limit getting rejected
+- Follower counters not being updated on incoming follow accepts
+
+### Upgrade notes
+
+1. Restart Pleroma
+
+## [2.0.4] - 2020-05-10
+
+### Security
+- AP C2S: Fix a potential DoS by creating nonsensical objects that break timelines
+
+### Fixed
+- Peertube user lookups not working
+- `InsertSkeletonsForDeletedUsers` migration failing on some instances
- Healthcheck reporting the number of memory currently used, rather than allocated in total
-- `InsertSkeletonsForDeletedUsers` failing on some instances
+- LDAP not being usable in OTP releases
+- Default apache configuration having tls chain issues
+
+### Upgrade notes
+
+#### Apache only
+
+1. Remove the following line from your config:
+```
+ SSLCertificateFile /etc/letsencrypt/live/${servername}/cert.pem
+```
+
+#### Everyone
+
+1. Restart Pleroma
## [2.0.3] - 2020-05-02
@@ -135,7 +316,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Follow request notifications
API Changes
-
- Admin API: `GET /api/pleroma/admin/need_reboot`.
@@ -170,6 +350,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Static-FE: Fix remote posts not being sanitized
### Fixed
+=======
+- 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
- Instance panel not being updated immediately due to wrong `Cache-Control` headers
- Statuses posted with BBCode/Markdown having unncessary newlines in Pleroma-FE
diff --git a/Dockerfile b/Dockerfile
index 0f4fcd0bb..c210cf79c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -4,7 +4,7 @@ COPY . .
ENV MIX_ENV=prod
-RUN apk add git gcc g++ musl-dev make &&\
+RUN apk add git gcc g++ musl-dev make cmake &&\
echo "import Mix.Config" > config/prod.secret.exs &&\
mix local.hex --force &&\
mix local.rebar --force &&\
@@ -31,7 +31,7 @@ LABEL maintainer="ops@pleroma.social" \
ARG HOME=/opt/pleroma
ARG DATA=/var/lib/pleroma
-RUN echo "http://nl.alpinelinux.org/alpine/latest-stable/community" >> /etc/apk/repositories &&\
+RUN echo "https://nl.alpinelinux.org/alpine/latest-stable/community" >> /etc/apk/repositories &&\
apk update &&\
apk add exiftool imagemagick ncurses postgresql-client &&\
adduser --system --shell /bin/false --home ${HOME} pleroma &&\
diff --git a/README.md b/README.md
index 6ca3118fb..7a05b9e48 100644
--- a/README.md
+++ b/README.md
@@ -18,15 +18,16 @@ If you are running Linux (glibc or musl) on x86/arm, the recommended way to inst
### From Source
If your platform is not supported, or you just want to be able to edit the source code easily, you may install Pleroma from source.
-- [Debian-based](https://docs-develop.pleroma.social/backend/installation/debian_based_en/)
-- [Debian-based (jp)](https://docs-develop.pleroma.social/backend/installation/debian_based_jp/)
- [Alpine Linux](https://docs-develop.pleroma.social/backend/installation/alpine_linux_en/)
- [Arch Linux](https://docs-develop.pleroma.social/backend/installation/arch_linux_en/)
+- [CentOS 7](https://docs-develop.pleroma.social/backend/installation/centos7_en/)
+- [Debian-based](https://docs-develop.pleroma.social/backend/installation/debian_based_en/)
+- [Debian-based (jp)](https://docs-develop.pleroma.social/backend/installation/debian_based_jp/)
+- [FreeBSD](https://docs-develop.pleroma.social/backend/installation/freebsd_en/)
- [Gentoo Linux](https://docs-develop.pleroma.social/backend/installation/gentoo_en/)
- [NetBSD](https://docs-develop.pleroma.social/backend/installation/netbsd_en/)
- [OpenBSD](https://docs-develop.pleroma.social/backend/installation/openbsd_en/)
- [OpenBSD (fi)](https://docs-develop.pleroma.social/backend/installation/openbsd_fi/)
-- [CentOS 7](https://docs-develop.pleroma.social/backend/installation/centos7_en/)
### OS/Distro packages
Currently Pleroma is not packaged by any OS/Distros, but if you want to package it for one, we can guide you through the process on our [community channels](#community-channels). If you want to change default options in your Pleroma package, please **discuss it with us first**.
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 000000000..8617c1434
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,16 @@
+# Pleroma backend security policy
+
+## Supported versions
+
+Currently, Pleroma offers bugfixes and security patches only for the latest minor release.
+
+| Version | Support
+|---------| --------
+| 2.1 | Bugfixes and security patches
+
+## Reporting a vulnerability
+
+Please use confidential issues (tick the "This issue is confidential and should only be visible to team members with at least Reporter access." box when submitting) at our [bugtracker](https://git.pleroma.social/pleroma/pleroma/-/issues/new) for reporting vulnerabilities.
+## Announcements
+
+New releases are announced at [pleroma.social](https://pleroma.social/announcements/). All security releases are tagged with ["Security"](https://pleroma.social/announcements/tags/security/). You can be notified of them by subscribing to an Atom feed at .
diff --git a/config/benchmark.exs b/config/benchmark.exs
index e867253eb..5567ff26e 100644
--- a/config/benchmark.exs
+++ b/config/benchmark.exs
@@ -59,8 +59,6 @@
"BLH1qVhJItRGCfxgTtONfsOKDc9VRAraXw-3NsmjMngWSh7NxOizN6bkuRA7iLTMPS82PjwJAr3UoK9EC1IFrz4",
private_key: "_-XZ0iebPrRfZ_o0-IatTdszYa8VCH1yLN-JauK7HHA"
-config :web_push_encryption, :http_client, Pleroma.Web.WebPushHttpClientMock
-
config :pleroma, Pleroma.ScheduledActivity,
daily_user_limit: 2,
total_user_limit: 3,
diff --git a/config/config.exs b/config/config.exs
index 100dbca15..d53663d36 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -72,7 +72,8 @@
pool: :upload
]
],
- filename_display_max_length: 30
+ filename_display_max_length: 30,
+ default_description: nil
config :pleroma, Pleroma.Uploaders.Local, uploads: "uploads"
@@ -129,6 +130,7 @@
dispatch: [
{:_,
[
+ {"/api/fedsocket/v1", Pleroma.Web.FedSockets.IncomingHandler, []},
{"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
{"/websocket", Phoenix.Endpoint.CowboyWebSocket,
{Phoenix.Transports.WebSocket,
@@ -147,6 +149,16 @@
"SameSite=Lax"
]
+config :pleroma, :fed_sockets,
+ enabled: false,
+ connection_duration: :timer.hours(8),
+ rejection_duration: :timer.minutes(15),
+ fed_socket_fetches: [
+ default: 12_000,
+ interval: 3_000,
+ lazy: false
+ ]
+
# Configures Elixir's Logger
config :logger, :console,
level: :debug,
@@ -215,7 +227,6 @@
allow_relay: true,
public: true,
quarantined_instances: [],
- managed_config: true,
static_dir: "instance/static/",
allowed_post_formats: [
"text/plain",
@@ -411,6 +422,7 @@
Pleroma.Web.RichMedia.Parsers.TwitterCard,
Pleroma.Web.RichMedia.Parsers.OEmbed
],
+ failure_backoff: 60_000,
ttl_setters: [Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl]
config :pleroma, :media_proxy,
@@ -422,6 +434,8 @@
proxy_opts: [
redirect_on_failure: false,
max_body_length: 25 * 1_048_576,
+ # Note: max_read_duration defaults to Pleroma.ReverseProxy.max_read_duration_default/1
+ max_read_duration: 30_000,
http: [
follow_redirect: true,
pool: :media
@@ -436,6 +450,14 @@
config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Script, script_path: nil
+# Note: media preview proxy depends on media proxy to be enabled
+config :pleroma, :media_preview_proxy,
+ enabled: false,
+ thumbnail_max_width: 600,
+ thumbnail_max_height: 600,
+ image_quality: 85,
+ min_content_length: 100 * 1024
+
config :pleroma, :chat, enabled: true
config :phoenix, :format_encoders, json: Jason
@@ -452,9 +474,7 @@
config :pleroma, Pleroma.Web.Metadata,
providers: [
Pleroma.Web.Metadata.Providers.OpenGraph,
- Pleroma.Web.Metadata.Providers.TwitterCard,
- Pleroma.Web.Metadata.Providers.RelMe,
- Pleroma.Web.Metadata.Providers.Feed
+ Pleroma.Web.Metadata.Providers.TwitterCard
],
unfurl_nsfw: false
@@ -530,8 +550,10 @@
log: false,
queues: [
activity_expiration: 10,
+ token_expiration: 5,
federator_incoming: 50,
federator_outgoing: 50,
+ ingestion_queue: 50,
web_push: 50,
mailer: 10,
transmogrifier: 20,
@@ -543,9 +565,6 @@
],
plugins: [Oban.Plugins.Pruner],
crontab: [
- {"0 0 * * *", Pleroma.Workers.Cron.ClearOauthTokenWorker},
- {"0 * * * *", Pleroma.Workers.Cron.StatsWorker},
- {"* * * * *", Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker},
{"0 0 * * 0", Pleroma.Workers.Cron.DigestEmailsWorker},
{"0 0 * * *", Pleroma.Workers.Cron.NewUsersDigestWorker}
]
@@ -656,9 +675,20 @@
account_confirmation_resend: {8_640_000, 5},
ap_routes: {60_000, 15}
-config :pleroma, Pleroma.ActivityExpiration, enabled: true
+config :pleroma, Pleroma.Workers.PurgeExpiredActivity, enabled: true, min_lifetime: 600
-config :pleroma, Pleroma.Plugs.RemoteIp, enabled: true
+config :pleroma, Pleroma.Plugs.RemoteIp,
+ enabled: true,
+ headers: ["x-forwarded-for"],
+ proxies: [],
+ reserved: [
+ "127.0.0.0/8",
+ "::1/128",
+ "fc00::/7",
+ "10.0.0.0/8",
+ "172.16.0.0/12",
+ "192.168.0.0/16"
+ ]
config :pleroma, :static_fe, enabled: false
@@ -670,7 +700,50 @@
# With no frontend configuration, the bundled files from the `static` directory will
# be used.
#
-# config :pleroma, :frontends, primary: %{"name" => "pleroma", "ref" => "develop"}
+# config :pleroma, :frontends,
+# primary: %{"name" => "pleroma-fe", "ref" => "develop"},
+# admin: %{"name" => "admin-fe", "ref" => "stable"},
+# available: %{...}
+
+config :pleroma, :frontends,
+ available: %{
+ "kenoma" => %{
+ "name" => "kenoma",
+ "git" => "https://git.pleroma.social/lambadalambda/kenoma",
+ "build_url" =>
+ "https://git.pleroma.social/lambadalambda/kenoma/-/jobs/artifacts/${ref}/download?job=build",
+ "ref" => "master"
+ },
+ "pleroma-fe" => %{
+ "name" => "pleroma-fe",
+ "git" => "https://git.pleroma.social/pleroma/pleroma-fe",
+ "build_url" =>
+ "https://git.pleroma.social/pleroma/pleroma-fe/-/jobs/artifacts/${ref}/download?job=build",
+ "ref" => "develop"
+ },
+ "fedi-fe" => %{
+ "name" => "fedi-fe",
+ "git" => "https://git.pleroma.social/pleroma/fedi-fe",
+ "build_url" =>
+ "https://git.pleroma.social/pleroma/fedi-fe/-/jobs/artifacts/${ref}/download?job=build",
+ "ref" => "master"
+ },
+ "admin-fe" => %{
+ "name" => "admin-fe",
+ "git" => "https://git.pleroma.social/pleroma/admin-fe",
+ "build_url" =>
+ "https://git.pleroma.social/pleroma/admin-fe/-/jobs/artifacts/${ref}/download?job=build",
+ "ref" => "develop"
+ },
+ "soapbox-fe" => %{
+ "name" => "soapbox-fe",
+ "git" => "https://gitlab.com/soapbox-pub/soapbox-fe",
+ "build_url" =>
+ "https://gitlab.com/soapbox-pub/soapbox-fe/-/jobs/artifacts/${ref}/download?job=build-production",
+ "ref" => "v1.0.0",
+ "build_dir" => "static"
+ }
+ }
config :pleroma, :web_cache_ttl,
activity_pub: nil,
@@ -691,24 +764,28 @@
max_connections: 250,
max_idle_time: 30_000,
retry: 0,
- await_up_timeout: 5_000
+ connect_timeout: 5_000
config :pleroma, :pools,
federation: [
size: 50,
- max_waiting: 10
+ max_waiting: 10,
+ recv_timeout: 10_000
],
media: [
size: 50,
- max_waiting: 10
+ max_waiting: 20,
+ recv_timeout: 15_000
],
upload: [
size: 25,
- max_waiting: 5
+ max_waiting: 5,
+ recv_timeout: 15_000
],
default: [
size: 10,
- max_waiting: 2
+ max_waiting: 2,
+ recv_timeout: 5_000
]
config :pleroma, :hackney_pools,
@@ -725,10 +802,12 @@
timeout: 300_000
]
+private_instance? = :if_instance_is_private
+
config :pleroma, :restrict_unauthenticated,
- timelines: %{local: false, federated: false},
- profiles: %{local: false, remote: false},
- activities: %{local: false, remote: false}
+ timelines: %{local: private_instance?, federated: private_instance?},
+ profiles: %{local: private_instance?, remote: private_instance?},
+ activities: %{local: private_instance?, remote: private_instance?}
config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: false
@@ -741,8 +820,12 @@
config :ex_aws, http_client: Pleroma.HTTP.ExAws
+config :web_push_encryption, http_client: Pleroma.HTTP.WebPush
+
config :pleroma, :instances_favicons, enabled: false
+config :floki, :html_parser, Floki.HTMLParser.FastHtml
+
config :pleroma, Pleroma.Web.Auth.Authenticator, Pleroma.Web.Auth.PleromaAuthenticator
# Import environment specific config. This must remain at the bottom
diff --git a/config/description.exs b/config/description.exs
index d823812fb..3902b9632 100644
--- a/config/description.exs
+++ b/config/description.exs
@@ -12,6 +12,58 @@
compress: false
]
+installed_frontend_options = [
+ %{
+ key: "name",
+ label: "Name",
+ type: :string,
+ description:
+ "Name of the installed frontend. Valid config must include both `Name` and `Reference` values."
+ },
+ %{
+ key: "ref",
+ label: "Reference",
+ type: :string,
+ description:
+ "Reference of the installed frontend to be used. Valid config must include both `Name` and `Reference` values."
+ }
+]
+
+frontend_options = [
+ %{
+ key: "name",
+ label: "Name",
+ type: :string,
+ description: "Name of the frontend."
+ },
+ %{
+ key: "ref",
+ label: "Reference",
+ type: :string,
+ description: "Reference of the frontend to be used."
+ },
+ %{
+ key: "git",
+ label: "Git Repository URL",
+ type: :string,
+ description: "URL of the git repository of the frontend"
+ },
+ %{
+ key: "build_url",
+ label: "Build URL",
+ type: :string,
+ description:
+ "Either an url to a zip file containing the frontend or a template to build it by inserting the `ref`. The string `${ref}` will be replaced by the configured `ref`.",
+ example: "https://some.url/builds/${ref}.zip"
+ },
+ %{
+ key: "build_dir",
+ label: "Build directory",
+ type: :string,
+ description: "The directory inside the zip file "
+ }
+]
+
config :pleroma, :config_description, [
%{
group: :pleroma,
@@ -194,7 +246,7 @@
type: [:string, {:list, :string}, {:list, :tuple}],
description:
"List of actions for the mogrify command. It's possible to add self-written settings as string. " <>
- "For example `[\"auto-orient\", \"strip\", {\"resize\", \"3840x1080>\"}]` string will be parsed into list of the settings.",
+ "For example `auto-orient, strip, {\"resize\", \"3840x1080>\"}` value will be parsed into valid list of the settings.",
suggestions: [
"strip",
"auto-orient",
@@ -221,6 +273,19 @@
}
]
},
+ %{
+ group: :pleroma,
+ key: :fed_sockets,
+ type: :group,
+ description: "Websocket based federation",
+ children: [
+ %{
+ key: :enabled,
+ type: :boolean,
+ description: "Enable FedSockets"
+ }
+ ]
+ },
%{
group: :pleroma,
key: Pleroma.Emails.Mailer,
@@ -715,12 +780,6 @@
"*.quarantined.com"
]
},
- %{
- key: :managed_config,
- type: :boolean,
- description:
- "Whenether the config for pleroma-fe is configured in this config or in static/config.json"
- },
%{
key: :static_dir,
type: :string,
@@ -951,7 +1010,7 @@
},
%{
key: :instance_thumbnail,
- type: :string,
+ type: {:string, :image},
description:
"The instance thumbnail can be any image that represents your instance and is used by some apps or services when they display information about your instance.",
suggestions: ["/instance/thumbnail.jpeg"]
@@ -964,25 +1023,25 @@
]
},
%{
- group: :welcome,
+ group: :pleroma,
+ key: :welcome,
type: :group,
description: "Welcome messages settings",
children: [
%{
- group: :direct_message,
- type: :group,
+ key: :direct_message,
+ type: :keyword,
descpiption: "Direct message settings",
children: [
%{
key: :enabled,
type: :boolean,
- description: "Enables sends direct message for new user after registration"
+ description: "Enables sending a direct message to newly registered users"
},
%{
key: :message,
type: :string,
- description:
- "A message that will be sent to a newly registered users as a direct message",
+ description: "A message that will be sent to newly registered users",
suggestions: [
"Hi, @username! Welcome on board!"
]
@@ -990,7 +1049,7 @@
%{
key: :sender_nickname,
type: :string,
- description: "The nickname of the local user that sends the welcome message",
+ description: "The nickname of the local user that sends a welcome message",
suggestions: [
"lain"
]
@@ -998,20 +1057,20 @@
]
},
%{
- group: :chat_message,
- type: :group,
+ key: :chat_message,
+ type: :keyword,
descpiption: "Chat message settings",
children: [
%{
key: :enabled,
type: :boolean,
- description: "Enables sends chat message for new user after registration"
+ description: "Enables sending a chat message to newly registered users"
},
%{
key: :message,
type: :string,
description:
- "A message that will be sent to a newly registered users as a chat message",
+ "A message that will be sent to newly registered users as a chat message",
suggestions: [
"Hello, welcome on board!"
]
@@ -1019,7 +1078,7 @@
%{
key: :sender_nickname,
type: :string,
- description: "The nickname of the local user that sends the welcome message",
+ description: "The nickname of the local user that sends a welcome chat message",
suggestions: [
"lain"
]
@@ -1027,20 +1086,20 @@
]
},
%{
- group: :email,
- type: :group,
+ key: :email,
+ type: :keyword,
descpiption: "Email message settings",
children: [
%{
key: :enabled,
type: :boolean,
- description: "Enables sends direct message for new user after registration"
+ description: "Enables sending an email to newly registered users"
},
%{
key: :sender,
type: [:string, :tuple],
description:
- "The email address or tuple with `{nickname, email}` that will use as sender to the welcome email.",
+ "Email address and/or nickname that will be used to send the welcome email.",
suggestions: [
{"Pleroma App", "welcome@pleroma.app"}
]
@@ -1049,21 +1108,21 @@
key: :subject,
type: :string,
description:
- "The subject of welcome email. Can be use EEX template with `user` and `instance_name` variables.",
+ "Subject of the welcome email. EEX template with user and instance_name variables can be used.",
suggestions: ["Welcome to <%= instance_name%>"]
},
%{
key: :html,
type: :string,
description:
- "The html content of welcome email. Can be use EEX template with `user` and `instance_name` variables.",
+ "HTML content of the welcome email. EEX template with user and instance_name variables can be used.",
suggestions: ["
Hello <%= user.name%>. Welcome to <%= instance_name%>
"]
},
%{
key: :text,
type: :string,
description:
- "The text content of welcome email. Can be use EEX template with `user` and `instance_name` variables.",
+ "Text content of the welcome email. EEX template with user and instance_name variables can be used.",
suggestions: ["Hello <%= user.name%>. \n Welcome to <%= instance_name%>\n"]
}
]
@@ -1236,7 +1295,7 @@
},
%{
key: :background,
- type: :string,
+ type: {:string, :image},
description:
"URL of the background, unless viewing a user profile with a background that is set",
suggestions: ["/images/city.jpg"]
@@ -1293,7 +1352,7 @@
},
%{
key: :logo,
- type: :string,
+ type: {:string, :image},
description: "URL of the logo, defaults to Pleroma's logo",
suggestions: ["/static/logo.png"]
},
@@ -1325,7 +1384,7 @@
%{
key: :nsfwCensorImage,
label: "NSFW Censor Image",
- type: :string,
+ type: {:string, :image},
description:
"URL of the image to use for hiding NSFW media attachments in the timeline",
suggestions: ["/static/img/nsfw.74818f9.png"]
@@ -1451,7 +1510,7 @@
},
%{
key: :default_user_avatar,
- type: :string,
+ type: {:string, :image},
description: "URL of the default user avatar",
suggestions: ["/images/avi.png"]
}
@@ -1810,12 +1869,12 @@
%{
key: :enabled,
type: :boolean,
- description: "Enables invalidate media cache"
+ description: "Enables media cache object invalidation."
},
%{
key: :provider,
type: :module,
- description: "Module which will be used to cache purge.",
+ description: "Module which will be used to purge objects from the cache.",
suggestions: [
Pleroma.Web.MediaProxy.Invalidation.Script,
Pleroma.Web.MediaProxy.Invalidation.Http
@@ -1831,6 +1890,7 @@
suggestions: [
redirect_on_failure: false,
max_body_length: 25 * 1_048_576,
+ max_read_duration: 30_000,
http: [
follow_redirect: true,
pool: :media
@@ -1851,6 +1911,11 @@
"Limits the content length to be approximately the " <>
"specified length. It is validated with the `content-length` header and also verified when proxying."
},
+ %{
+ key: :max_read_duration,
+ type: :integer,
+ description: "Timeout (in milliseconds) of GET request to remote URI."
+ },
%{
key: :http,
label: "HTTP",
@@ -1897,6 +1962,43 @@
}
]
},
+ %{
+ group: :pleroma,
+ key: :media_preview_proxy,
+ type: :group,
+ description: "Media preview proxy",
+ children: [
+ %{
+ key: :enabled,
+ type: :boolean,
+ description:
+ "Enables proxying of remote media preview to the instance's proxy. Requires enabled media proxy."
+ },
+ %{
+ key: :thumbnail_max_width,
+ type: :integer,
+ description:
+ "Max width of preview thumbnail for images (video preview always has original dimensions)."
+ },
+ %{
+ key: :thumbnail_max_height,
+ type: :integer,
+ description:
+ "Max height of preview thumbnail for images (video preview always has original dimensions)."
+ },
+ %{
+ key: :image_quality,
+ type: :integer,
+ description: "Quality of the output. Ranges from 0 (min quality) to 100 (max quality)."
+ },
+ %{
+ key: :min_content_length,
+ type: :integer,
+ description:
+ "Min content length to perform preview, in bytes. If greater than 0, media smaller in size will be served as is, without thumbnailing."
+ }
+ ]
+ },
%{
group: :pleroma,
key: Pleroma.Web.MediaProxy.Invalidation.Http,
@@ -2241,9 +2343,6 @@
type: {:list, :tuple},
description: "Settings for cron background jobs",
suggestions: [
- {"0 0 * * *", Pleroma.Workers.Cron.ClearOauthTokenWorker},
- {"0 * * * *", Pleroma.Workers.Cron.StatsWorker},
- {"* * * * *", Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker},
{"0 0 * * 0", Pleroma.Workers.Cron.DigestEmailsWorker},
{"0 0 * * *", Pleroma.Workers.Cron.NewUsersDigestWorker}
]
@@ -2336,13 +2435,20 @@
suggestions: [
Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl
]
+ },
+ %{
+ key: :failure_backoff,
+ type: :integer,
+ description:
+ "Amount of milliseconds after request failure, during which the request will not be retried.",
+ suggestions: [60_000]
}
]
},
%{
group: :pleroma,
key: Pleroma.Formatter,
- label: "Auto Linker",
+ label: "Linkify",
type: :group,
description:
"Configuration for Pleroma's link formatter which parses mentions, hashtags, and URLs.",
@@ -2419,14 +2525,20 @@
},
%{
group: :pleroma,
- key: Pleroma.ActivityExpiration,
+ key: Pleroma.Workers.PurgeExpiredActivity,
type: :group,
- description: "Expired activity settings",
+ description: "Expired activities settings",
children: [
%{
key: :enabled,
type: :boolean,
- description: "Whether expired activities will be sent to the job queue to be deleted"
+ description: "Enables expired activities addition & deletion"
+ },
+ %{
+ key: :min_lifetime,
+ type: :integer,
+ description: "Minimum lifetime for ephemeral activity (in seconds)",
+ suggestions: [600]
}
]
},
@@ -2642,7 +2754,7 @@
children: [
%{
key: :logo,
- type: :string,
+ type: {:string, :image},
description: "A path to a custom logo. Set it to `nil` to use the default Pleroma logo.",
suggestions: ["some/path/logo.png"]
},
@@ -3153,20 +3265,22 @@
%{
key: :headers,
type: {:list, :string},
- description:
- "A list of strings naming the `req_headers` to use when deriving the `remote_ip`. Order does not matter. Default: `~w[forwarded x-forwarded-for x-client-ip x-real-ip]`."
+ description: """
+ A list of strings naming the HTTP headers to use when deriving the true client IP. Default: `["x-forwarded-for"]`.
+ """
},
%{
key: :proxies,
type: {:list, :string},
description:
- "A list of strings in [CIDR](https://en.wikipedia.org/wiki/CIDR) notation specifying the IPs of known proxies. Default: `[]`."
+ "A list of upstream proxy IP subnets in CIDR notation from which we will parse the content of `headers`. Defaults to `[]`. IPv4 entries without a bitmask will be assumed to be /32 and IPv6 /128."
},
%{
key: :reserved,
type: {:list, :string},
- description:
- "Defaults to [localhost](https://en.wikipedia.org/wiki/Localhost) and [private network](https://en.wikipedia.org/wiki/Private_network)."
+ description: """
+ A list of reserved IP subnets in CIDR notation which should be ignored if found in `headers`. Defaults to `["127.0.0.0/8", "::1/128", "fc00::/7", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]`
+ """
}
]
},
@@ -3299,13 +3413,13 @@
group: :pleroma,
key: :connections_pool,
type: :group,
- description: "Advanced settings for `gun` connections pool",
+ description: "Advanced settings for `Gun` connections pool",
children: [
%{
key: :connection_acquisition_wait,
type: :integer,
description:
- "Timeout to acquire a connection from pool.The total max time is this value multiplied by the number of retries. Default: 250ms.",
+ "Timeout to acquire a connection from pool. The total max time is this value multiplied by the number of retries. Default: 250ms.",
suggestions: [250]
},
%{
@@ -3322,7 +3436,7 @@
suggestions: [250]
},
%{
- key: :await_up_timeout,
+ key: :connect_timeout,
type: :integer,
description: "Timeout while `gun` will wait until connection is up. Default: 5000ms.",
suggestions: [5000]
@@ -3340,7 +3454,7 @@
group: :pleroma,
key: :pools,
type: :group,
- description: "Advanced settings for `gun` workers pools",
+ description: "Advanced settings for `Gun` workers pools",
children:
Enum.map([:federation, :media, :upload, :default], fn pool_name ->
%{
@@ -3360,6 +3474,12 @@
description:
"Maximum number of requests waiting for other requests to finish. After this number is reached, the pool will start returning errrors when a new request is made",
suggestions: [10]
+ },
+ %{
+ key: :recv_timeout,
+ type: :integer,
+ description: "Timeout for the pool while gun will wait for response",
+ suggestions: [10_000]
}
]
}
@@ -3369,7 +3489,7 @@
group: :pleroma,
key: :hackney_pools,
type: :group,
- description: "Advanced settings for `hackney` connections pools",
+ description: "Advanced settings for `Hackney` connections pools",
children: [
%{
key: :federation,
@@ -3433,6 +3553,7 @@
%{
group: :pleroma,
key: :restrict_unauthenticated,
+ label: "Restrict Unauthenticated",
type: :group,
description:
"Disallow viewing timelines, user profiles and statuses for unauthenticated users.",
@@ -3552,17 +3673,38 @@
key: :primary,
type: :map,
description: "Primary frontend, the one that is served for all pages by default",
- children: [
- %{
- key: "name",
- type: :string,
- description: "Name of the installed primary frontend"
- },
- %{
- key: "ref",
- type: :string,
- description: "reference of the installed primary frontend to be used"
- }
+ children: installed_frontend_options
+ },
+ %{
+ key: :admin,
+ type: :map,
+ description: "Admin frontend",
+ children: installed_frontend_options
+ },
+ %{
+ key: :available,
+ type: :map,
+ description:
+ "A map containing available frontends and parameters for their installation.",
+ children: frontend_options
+ }
+ ]
+ },
+ %{
+ group: :pleroma,
+ key: Pleroma.Web.Preload,
+ type: :group,
+ description: "Preload-related settings",
+ children: [
+ %{
+ key: :providers,
+ type: {:list, :module},
+ description: "List of preload providers to enable",
+ suggestions: [
+ Pleroma.Web.Preload.Providers.Instance,
+ Pleroma.Web.Preload.Providers.User,
+ Pleroma.Web.Preload.Providers.Timelines,
+ Pleroma.Web.Preload.Providers.StatusNet
]
}
]
diff --git a/config/test.exs b/config/test.exs
index 413c7f0b9..95f860f2f 100644
--- a/config/test.exs
+++ b/config/test.exs
@@ -19,9 +19,17 @@
level: :warn,
format: "\n[$level] $message\n"
+config :pleroma, :fed_sockets,
+ enabled: false,
+ connection_duration: 5,
+ rejection_duration: 5
+
config :pleroma, :auth, oauth_consumer_strategies: []
-config :pleroma, Pleroma.Upload, filters: [], link_name: false
+config :pleroma, Pleroma.Upload,
+ filters: [],
+ link_name: false,
+ default_description: :filename
config :pleroma, Pleroma.Uploaders.Local, uploads: "test/uploads"
@@ -75,8 +83,6 @@
"BLH1qVhJItRGCfxgTtONfsOKDc9VRAraXw-3NsmjMngWSh7NxOizN6bkuRA7iLTMPS82PjwJAr3UoK9EC1IFrz4",
private_key: "_-XZ0iebPrRfZ_o0-IatTdszYa8VCH1yLN-JauK7HHA"
-config :web_push_encryption, :http_client, Pleroma.Web.WebPushHttpClientMock
-
config :pleroma, Oban,
queues: false,
crontab: false,
@@ -111,8 +117,6 @@
config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: true
-config :pleroma, :instances_favicons, enabled: true
-
config :pleroma, Pleroma.Uploaders.S3,
bucket: nil,
streaming_enabled: true,
diff --git a/docs/API/admin_api.md b/docs/API/admin_api.md
index 4b143e4ee..7bf13daef 100644
--- a/docs/API/admin_api.md
+++ b/docs/API/admin_api.md
@@ -313,14 +313,37 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
- On failure: `Not found`
- On success: JSON array of user's latest statuses
+## `GET /api/pleroma/admin/relay`
+
+### List Relays
+
+Params: none
+Response:
+
+* On success: JSON array of relays
+
+```json
+[
+ {"actor": "https://example.com/relay", "followed_back": true},
+ {"actor": "https://example2.com/relay", "followed_back": false}
+]
+```
+
## `POST /api/pleroma/admin/relay`
### Follow a Relay
-- Params:
- - `relay_url`
-- Response:
- - On success: URL of the followed relay
+Params:
+
+* `relay_url`
+
+Response:
+
+* On success: relay json object
+
+```json
+{"actor": "https://example.com/relay", "followed_back": true}
+```
## `DELETE /api/pleroma/admin/relay`
@@ -328,16 +351,15 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
- Params:
- `relay_url`
-- Response:
- - On success: URL of the unfollowed relay
+ - *optional* `force`: forcefully unfollow a relay even when the relay is not available. (default is `false`)
-## `GET /api/pleroma/admin/relay`
+Response:
-### List Relays
+* On success: URL of the unfollowed relay
-- Params: none
-- Response:
- - On success: JSON array of relays
+```json
+{"https://example.com/relay"}
+```
## `POST /api/pleroma/admin/users/invite_token`
@@ -1266,11 +1288,14 @@ Loads json generated from `config/descriptions.exs`.
- Params:
- *optional* `page`: **integer** page number
- *optional* `page_size`: **integer** number of log entries per page (default is `50`)
+- *optional* `query`: **string** search term
- Response:
``` json
{
+ "page_size": integer,
+ "count": integer,
"urls": [
"http://example.com/media/a688346.jpg",
"http://example.com/media/fb1f4d.jpg"
@@ -1290,12 +1315,7 @@ Loads json generated from `config/descriptions.exs`.
- Response:
``` json
-{
- "urls": [
- "http://example.com/media/a688346.jpg",
- "http://example.com/media/fb1f4d.jpg"
- ]
-}
+{ }
```
@@ -1311,11 +1331,169 @@ Loads json generated from `config/descriptions.exs`.
- Response:
``` json
-{
- "urls": [
- "http://example.com/media/a688346.jpg",
- "http://example.com/media/fb1f4d.jpg"
- ]
-}
+{ }
```
+
+## GET /api/pleroma/admin/users/:nickname/chats
+
+### List a user's chats
+
+- Params: None
+
+- Response:
+
+```json
+[
+ {
+ "sender": {
+ "id": "someflakeid",
+ "username": "somenick",
+ ...
+ },
+ "receiver": {
+ "id": "someflakeid",
+ "username": "somenick",
+ ...
+ },
+ "id" : "1",
+ "unread" : 2,
+ "last_message" : {...}, // The last message in that chat
+ "updated_at": "2020-04-21T15:11:46.000Z"
+ }
+]
+```
+
+## GET /api/pleroma/admin/chats/:chat_id
+
+### View a single chat
+
+- Params: None
+
+- Response:
+
+```json
+{
+ "sender": {
+ "id": "someflakeid",
+ "username": "somenick",
+ ...
+ },
+ "receiver": {
+ "id": "someflakeid",
+ "username": "somenick",
+ ...
+ },
+ "id" : "1",
+ "unread" : 2,
+ "last_message" : {...}, // The last message in that chat
+ "updated_at": "2020-04-21T15:11:46.000Z"
+}
+```
+
+## GET /api/pleroma/admin/chats/:chat_id/messages
+
+### List the messages in a chat
+
+- Params: `max_id`, `min_id`
+
+- Response:
+
+```json
+[
+ {
+ "account_id": "someflakeid",
+ "chat_id": "1",
+ "content": "Check this out :firefox:",
+ "created_at": "2020-04-21T15:11:46.000Z",
+ "emojis": [
+ {
+ "shortcode": "firefox",
+ "static_url": "https://dontbulling.me/emoji/Firefox.gif",
+ "url": "https://dontbulling.me/emoji/Firefox.gif",
+ "visible_in_picker": false
+ }
+ ],
+ "id": "13",
+ "unread": true
+ },
+ {
+ "account_id": "someflakeid",
+ "chat_id": "1",
+ "content": "Whats' up?",
+ "created_at": "2020-04-21T15:06:45.000Z",
+ "emojis": [],
+ "id": "12",
+ "unread": false
+ }
+]
+```
+
+## DELETE /api/pleroma/admin/chats/:chat_id/messages/:message_id
+
+### Delete a single message
+
+- Params: None
+
+- Response:
+
+```json
+{
+ "account_id": "someflakeid",
+ "chat_id": "1",
+ "content": "Check this out :firefox:",
+ "created_at": "2020-04-21T15:11:46.000Z",
+ "emojis": [
+ {
+ "shortcode": "firefox",
+ "static_url": "https://dontbulling.me/emoji/Firefox.gif",
+ "url": "https://dontbulling.me/emoji/Firefox.gif",
+ "visible_in_picker": false
+ }
+ ],
+ "id": "13",
+ "unread": false
+}
+```
+
+## `GET /api/pleroma/admin/instance_document/:document_name`
+
+### Get an instance document
+
+- Authentication: required
+
+- Response:
+
+Returns the content of the document
+
+```html
+
#{object.data["content"]}"
- else
- _ -> object.data["content"] || ""
- end
- end
+ def render_content(%{data: %{"name" => name}} = object) when not is_nil(name) and name != "" do
+ url = object.data["url"] || object.data["id"]
- def render_content(%{data: %{"type" => object_type}} = object)
- when object_type in ["Article", "Page"] do
- with summary when not is_nil(summary) and summary != "" <- object.data["name"],
- url when is_bitstring(url) <- object.data["url"] do
- "
\n \n \n {{ user.roles.admin ? $t('users.revokeAdmin') : $t('users.grantAdmin') }}\n \n \n {{ user.roles.moderator ? $t('users.revokeModerator') : $t('users.grantModerator') }}\n \n \n {{ user.deactivated ? $t('users.activateAccount') : $t('users.deactivateAccount') }}\n \n \n {{ $t('users.deleteAccount') }}\n \n \n {{ $t('users.confirmAccount') }}\n \n \n {{ $t('users.resendConfirmation') }}\n \n \n {{ $t('users.forceNsfw') }}\n \n \n \n {{ $t('users.stripMedia') }}\n \n \n \n {{ $t('users.forceUnlisted') }}\n \n \n \n {{ $t('users.sandbox') }}\n \n \n \n {{ $t('users.disableRemoteSubscription') }}\n \n \n \n {{ $t('users.disableAnySubscription') }}\n \n \n \n {{ $t('users.getPasswordResetToken') }}\n \n \n {{ $t('users.requirePasswordReset') }}\n \n \n \n\n\n\n\n\n","import { render, staticRenderFns } from \"./ModerationDropdown.vue?vue&type=template&id=25dd4f14&\"\nimport script from \"./ModerationDropdown.vue?vue&type=script&lang=js&\"\nexport * from \"./ModerationDropdown.vue?vue&type=script&lang=js&\"\nimport style0 from \"./ModerationDropdown.vue?vue&type=style&index=0&rel=stylesheet%2Fscss&lang=scss&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\ncomponent.options.__file = \"ModerationDropdown.vue\"\nexport default component.exports"],"sourceRoot":""}
\ No newline at end of file
diff --git a/priv/static/adminfe/static/js/chunk-60a9.22fe45f3.js b/priv/static/adminfe/static/js/chunk-60a9.22fe45f3.js
new file mode 100644
index 000000000..a23d46b72
--- /dev/null
+++ b/priv/static/adminfe/static/js/chunk-60a9.22fe45f3.js
@@ -0,0 +1,2 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([["chunk-60a9"],{"/En5":function(e,t,n){},"0Ruq":function(e,t,n){"use strict";var a=n("/En5");n.n(a).a},"9/5/":function(e,t,n){(function(t){var n="Expected a function",a=NaN,r="[object Symbol]",i=/^\s+|\s+$/g,o=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,c=/^0o[0-7]+$/i,u=parseInt,l="object"==typeof t&&t&&t.Object===Object&&t,d="object"==typeof self&&self&&self.Object===Object&&self,h=l||d||Function("return this")(),p=Object.prototype.toString,f=Math.max,v=Math.min,m=function(){return h.Date.now()};function b(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}function g(e){if("number"==typeof e)return e;if(function(e){return"symbol"==typeof e||function(e){return!!e&&"object"==typeof e}(e)&&p.call(e)==r}(e))return a;if(b(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=b(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(i,"");var n=s.test(e);return n||c.test(e)?u(e.slice(2),n?2:8):o.test(e)?a:+e}e.exports=function(e,t,a){var r,i,o,s,c,u,l=0,d=!1,h=!1,p=!0;if("function"!=typeof e)throw new TypeError(n);function y(t){var n=r,a=i;return r=i=void 0,l=t,s=e.apply(a,n)}function x(e){var n=e-u;return void 0===u||n>=t||n<0||h&&e-l>=o}function C(){var e=m();if(x(e))return _(e);c=setTimeout(C,function(e){var n=t-(e-u);return h?v(n,o-(e-l)):n}(e))}function _(e){return c=void 0,p&&r?y(e):(r=i=void 0,s)}function $(){var e=m(),n=x(e);if(r=arguments,i=this,u=e,n){if(void 0===c)return function(e){return l=e,c=setTimeout(C,t),d?y(e):s}(u);if(h)return c=setTimeout(C,t),y(u)}return void 0===c&&(c=setTimeout(C,t)),s}return t=g(t)||0,b(a)&&(d=!!a.leading,o=(h="maxWait"in a)?f(g(a.maxWait)||0,t):o,p="trailing"in a?!!a.trailing:p),$.cancel=function(){void 0!==c&&clearTimeout(c),l=0,r=u=i=c=void 0},$.flush=function(){return void 0===c?s:_(m())},$}}).call(this,n("yLpj"))},mAEd:function(e,t,n){"use strict";n.r(t);var a=n("9/5/"),r=n.n(a),i={name:"MediaProxyCache",components:{RebootButton:n("rIUS").a},data:function(){return{urls:"",ban:!1,search:"",selectedUrls:[]}},computed:{bannedUrls:function(){return this.$store.state.mediaProxyCache.bannedUrls},currentPage:function(){return this.$store.state.mediaProxyCache.currentPage},isDesktop:function(){return"desktop"===this.$store.state.app.device},loading:function(){return this.$store.state.mediaProxyCache.loading},pageSize:function(){return this.$store.state.mediaProxyCache.pageSize},removeSelectedDisabled:function(){return 0===this.selectedUrls.length},urlsCount:function(){return this.$store.state.mediaProxyCache.totalUrlsCount}},created:function(){var e=this;this.handleDebounceSearchInput=r()(function(t){e.$store.dispatch("SearchUrls",{query:t,page:1})},500)},mounted:function(){this.$store.dispatch("GetNodeInfo"),this.$store.dispatch("NeedReboot"),this.$store.dispatch("ListBannedUrls",{page:1})},methods:{evictURL:function(){var e=this.urls.split(",").map(function(e){return e.trim()}).filter(function(e){return e.length>0});this.$store.dispatch("PurgeUrls",{urls:e,ban:this.ban}),this.urls=""},handlePageChange:function(e){this.$store.dispatch("ListBannedUrls",{page:e})},handleSelectionChange:function(e){this.$data.selectedUrls=e},removeSelected:function(){var e=this.selectedUrls.map(function(e){return e.url});this.$store.dispatch("RemoveBannedUrls",e),this.selectedUrls=[]},removeUrl:function(e){this.$store.dispatch("RemoveBannedUrls",[e])}}},o=(n("0Ruq"),n("KHd+")),s=Object(o.a)(i,function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"media-proxy-cache-container"},[n("div",{staticClass:"media-proxy-cache-header-container"},[n("h1",[e._v(e._s(e.$t("mediaProxyCache.mediaProxyCache")))]),e._v(" "),n("reboot-button")],1),e._v(" "),n("p",{staticClass:"media-proxy-cache-header"},[e._v(e._s(e.$t("mediaProxyCache.evictObjectsHeader")))]),e._v(" "),n("div",{staticClass:"url-input-container"},[n("el-input",{staticClass:"url-input",attrs:{placeholder:e.$t("mediaProxyCache.url"),type:"textarea",autosize:"",clearable:""},model:{value:e.urls,callback:function(t){e.urls=t},expression:"urls"}}),e._v(" "),n("el-checkbox",{model:{value:e.ban,callback:function(t){e.ban=t},expression:"ban"}},[e._v(e._s(e.$t("mediaProxyCache.ban")))]),e._v(" "),n("el-button",{staticClass:"evict-button",on:{click:e.evictURL}},[e._v(e._s(e.$t("mediaProxyCache.evict")))])],1),e._v(" "),n("span",{staticClass:"expl url-input-expl"},[e._v(e._s(e.$t("mediaProxyCache.multipleInput")))]),e._v(" "),n("p",{staticClass:"media-proxy-cache-header"},[e._v(e._s(e.$t("mediaProxyCache.listBannedUrlsHeader")))]),e._v(" "),n("el-table",{directives:[{name:"loading",rawName:"v-loading",value:e.loading,expression:"loading"}],staticClass:"banned-urls-table",attrs:{data:e.bannedUrls},on:{"selection-change":e.handleSelectionChange}},[e._v(">\n "),n("el-table-column",{attrs:{type:"selection",align:"center",width:"55"}}),e._v(" "),n("el-table-column",{attrs:{"min-width":e.isDesktop?320:120,prop:"url"},scopedSlots:e._u([{key:"header",fn:function(t){return[n("el-input",{attrs:{placeholder:e.$t("users.search"),size:"mini","prefix-icon":"el-icon-search"},on:{input:e.handleDebounceSearchInput},model:{value:e.search,callback:function(t){e.search=t},expression:"search"}})]}}])}),e._v(" "),n("el-table-column",{scopedSlots:e._u([{key:"default",fn:function(t){return[n("el-button",{staticClass:"remove-url-button",attrs:{size:"mini"},on:{click:function(n){return e.removeUrl(t.row.url)}}},[e._v(e._s(e.$t("mediaProxyCache.remove")))])]}}])},[n("template",{slot:"header"},[n("el-button",{staticClass:"remove-url-button",attrs:{disabled:e.removeSelectedDisabled,size:"mini"},on:{click:function(t){return e.removeSelected()}}},[e._v(e._s(e.$t("mediaProxyCache.removeSelected")))])],1)],2)],1),e._v(" "),e.loading?e._e():n("div",{staticClass:"pagination"},[n("el-pagination",{attrs:{total:e.urlsCount,"current-page":e.currentPage,"page-size":e.pageSize,"hide-on-single-page":"",layout:"prev, pager, next"},on:{"current-change":e.handlePageChange}})],1)],1)},[],!1,null,"039e6dbb",null);s.options.__file="index.vue";t.default=s.exports}}]);
+//# sourceMappingURL=chunk-60a9.22fe45f3.js.map
\ No newline at end of file
diff --git a/priv/static/adminfe/static/js/chunk-60a9.22fe45f3.js.map b/priv/static/adminfe/static/js/chunk-60a9.22fe45f3.js.map
new file mode 100644
index 000000000..690979713
--- /dev/null
+++ b/priv/static/adminfe/static/js/chunk-60a9.22fe45f3.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["webpack:///./src/views/mediaProxyCache/index.vue?a139","webpack:///./node_modules/lodash.debounce/index.js","webpack:///./src/views/mediaProxyCache/index.vue?8634","webpack:///./src/views/mediaProxyCache/index.vue?888e","webpack:///src/views/mediaProxyCache/index.vue","webpack:///./src/views/mediaProxyCache/index.vue"],"names":["_node_modules_mini_css_extract_plugin_dist_loader_js_node_modules_css_loader_index_js_ref_11_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_lib_index_js_ref_11_2_node_modules_sass_loader_lib_loader_js_ref_11_3_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_style_index_0_id_039e6dbb_rel_stylesheet_2Fscss_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__","__webpack_require__","n","global","FUNC_ERROR_TEXT","NAN","symbolTag","reTrim","reIsBadHex","reIsBinary","reIsOctal","freeParseInt","parseInt","freeGlobal","Object","freeSelf","self","root","Function","objectToString","prototype","toString","nativeMax","Math","max","nativeMin","min","now","Date","isObject","value","type","toNumber","isObjectLike","call","isSymbol","other","valueOf","replace","isBinary","test","slice","module","exports","func","wait","options","lastArgs","lastThis","maxWait","result","timerId","lastCallTime","lastInvokeTime","leading","maxing","trailing","TypeError","invokeFunc","time","args","thisArg","undefined","apply","shouldInvoke","timeSinceLastCall","timerExpired","trailingEdge","setTimeout","remainingWait","debounced","isInvoking","arguments","this","leadingEdge","cancel","clearTimeout","flush","views_mediaProxyCachevue_type_script_lang_js_","name","components","RebootButton","data","urls","ban","search","selectedUrls","computed","bannedUrls","$store","state","mediaProxyCache","currentPage","isDesktop","app","device","loading","pageSize","removeSelectedDisabled","length","urlsCount","totalUrlsCount","created","_this","handleDebounceSearchInput","lodash_debounce_default","query","dispatch","page","mounted","methods","evictURL","split","map","url","trim","filter","el","handlePageChange","handleSelectionChange","$data","removeSelected","removeUrl","component","componentNormalizer","_vm","_h","$createElement","_c","_self","staticClass","_v","_s","$t","attrs","placeholder","autosize","clearable","model","callback","$$v","expression","on","click","directives","rawName","selection-change","align","width","min-width","prop","scopedSlots","_u","key","fn","scope","size","prefix-icon","input","$event","row","slot","disabled","_e","total","current-page","page-size","hide-on-single-page","layout","current-change","__file","__webpack_exports__"],"mappings":"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","file":"static/js/chunk-60a9.22fe45f3.js","sourcesContent":["import mod from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js!../../../node_modules/css-loader/index.js??ref--11-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/lib/index.js??ref--11-2!../../../node_modules/sass-loader/lib/loader.js??ref--11-3!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./index.vue?vue&type=style&index=0&id=039e6dbb&rel=stylesheet%2Fscss&lang=scss&scoped=true&\"; export default mod; export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js!../../../node_modules/css-loader/index.js??ref--11-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/lib/index.js??ref--11-2!../../../node_modules/sass-loader/lib/loader.js??ref--11-3!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./index.vue?vue&type=style&index=0&id=039e6dbb&rel=stylesheet%2Fscss&lang=scss&scoped=true&\"","/**\n * lodash (Custom Build) \n * Build: `lodash modularize exports=\"npm\" -o ./`\n * Copyright jQuery Foundation and other contributors \n * Released under MIT license \n * Based on Underscore.js 1.8.3 \n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */\n\n/** Used as the `TypeError` message for \"Functions\" methods. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/** Used as references for various `Number` constants. */\nvar NAN = 0 / 0;\n\n/** `Object#toString` result references. */\nvar symbolTag = '[object Symbol]';\n\n/** Used to match leading and trailing whitespace. */\nvar reTrim = /^\\s+|\\s+$/g;\n\n/** Used to detect bad signed hexadecimal string values. */\nvar reIsBadHex = /^[-+]0x[0-9a-f]+$/i;\n\n/** Used to detect binary string values. */\nvar reIsBinary = /^0b[01]+$/i;\n\n/** Used to detect octal string values. */\nvar reIsOctal = /^0o[0-7]+$/i;\n\n/** Built-in method references without a dependency on `root`. */\nvar freeParseInt = parseInt;\n\n/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max,\n nativeMin = Math.min;\n\n/**\n * Gets the timestamp of the number of milliseconds that have elapsed since\n * the Unix epoch (1 January 1970 00:00:00 UTC).\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Date\n * @returns {number} Returns the timestamp.\n * @example\n *\n * _.defer(function(stamp) {\n * console.log(_.now() - stamp);\n * }, _.now());\n * // => Logs the number of milliseconds it took for the deferred invocation.\n */\nvar now = function() {\n return root.Date.now();\n};\n\n/**\n * Creates a debounced function that delays invoking `func` until after `wait`\n * milliseconds have elapsed since the last time the debounced function was\n * invoked. The debounced function comes with a `cancel` method to cancel\n * delayed `func` invocations and a `flush` method to immediately invoke them.\n * Provide `options` to indicate whether `func` should be invoked on the\n * leading and/or trailing edge of the `wait` timeout. The `func` is invoked\n * with the last arguments provided to the debounced function. Subsequent\n * calls to the debounced function return the result of the last `func`\n * invocation.\n *\n * **Note:** If `leading` and `trailing` options are `true`, `func` is\n * invoked on the trailing edge of the timeout only if the debounced function\n * is invoked more than once during the `wait` timeout.\n *\n * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n * until to the next tick, similar to `setTimeout` with a timeout of `0`.\n *\n * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n * for details over the differences between `_.debounce` and `_.throttle`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to debounce.\n * @param {number} [wait=0] The number of milliseconds to delay.\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.leading=false]\n * Specify invoking on the leading edge of the timeout.\n * @param {number} [options.maxWait]\n * The maximum time `func` is allowed to be delayed before it's invoked.\n * @param {boolean} [options.trailing=true]\n * Specify invoking on the trailing edge of the timeout.\n * @returns {Function} Returns the new debounced function.\n * @example\n *\n * // Avoid costly calculations while the window size is in flux.\n * jQuery(window).on('resize', _.debounce(calculateLayout, 150));\n *\n * // Invoke `sendMail` when clicked, debouncing subsequent calls.\n * jQuery(element).on('click', _.debounce(sendMail, 300, {\n * 'leading': true,\n * 'trailing': false\n * }));\n *\n * // Ensure `batchLog` is invoked once after 1 second of debounced calls.\n * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });\n * var source = new EventSource('/stream');\n * jQuery(source).on('message', debounced);\n *\n * // Cancel the trailing debounced invocation.\n * jQuery(window).on('popstate', debounced.cancel);\n */\nfunction debounce(func, wait, options) {\n var lastArgs,\n lastThis,\n maxWait,\n result,\n timerId,\n lastCallTime,\n lastInvokeTime = 0,\n leading = false,\n maxing = false,\n trailing = true;\n\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n wait = toNumber(wait) || 0;\n if (isObject(options)) {\n leading = !!options.leading;\n maxing = 'maxWait' in options;\n maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;\n trailing = 'trailing' in options ? !!options.trailing : trailing;\n }\n\n function invokeFunc(time) {\n var args = lastArgs,\n thisArg = lastThis;\n\n lastArgs = lastThis = undefined;\n lastInvokeTime = time;\n result = func.apply(thisArg, args);\n return result;\n }\n\n function leadingEdge(time) {\n // Reset any `maxWait` timer.\n lastInvokeTime = time;\n // Start the timer for the trailing edge.\n timerId = setTimeout(timerExpired, wait);\n // Invoke the leading edge.\n return leading ? invokeFunc(time) : result;\n }\n\n function remainingWait(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime,\n result = wait - timeSinceLastCall;\n\n return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;\n }\n\n function shouldInvoke(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime;\n\n // Either this is the first call, activity has stopped and we're at the\n // trailing edge, the system time has gone backwards and we're treating\n // it as the trailing edge, or we've hit the `maxWait` limit.\n return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||\n (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));\n }\n\n function timerExpired() {\n var time = now();\n if (shouldInvoke(time)) {\n return trailingEdge(time);\n }\n // Restart the timer.\n timerId = setTimeout(timerExpired, remainingWait(time));\n }\n\n function trailingEdge(time) {\n timerId = undefined;\n\n // Only invoke if we have `lastArgs` which means `func` has been\n // debounced at least once.\n if (trailing && lastArgs) {\n return invokeFunc(time);\n }\n lastArgs = lastThis = undefined;\n return result;\n }\n\n function cancel() {\n if (timerId !== undefined) {\n clearTimeout(timerId);\n }\n lastInvokeTime = 0;\n lastArgs = lastCallTime = lastThis = timerId = undefined;\n }\n\n function flush() {\n return timerId === undefined ? result : trailingEdge(now());\n }\n\n function debounced() {\n var time = now(),\n isInvoking = shouldInvoke(time);\n\n lastArgs = arguments;\n lastThis = this;\n lastCallTime = time;\n\n if (isInvoking) {\n if (timerId === undefined) {\n return leadingEdge(lastCallTime);\n }\n if (maxing) {\n // Handle invocations in a tight loop.\n timerId = setTimeout(timerExpired, wait);\n return invokeFunc(lastCallTime);\n }\n }\n if (timerId === undefined) {\n timerId = setTimeout(timerExpired, wait);\n }\n return result;\n }\n debounced.cancel = cancel;\n debounced.flush = flush;\n return debounced;\n}\n\n/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\n/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return !!value && typeof value == 'object';\n}\n\n/**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\nfunction isSymbol(value) {\n return typeof value == 'symbol' ||\n (isObjectLike(value) && objectToString.call(value) == symbolTag);\n}\n\n/**\n * Converts `value` to a number.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n * @example\n *\n * _.toNumber(3.2);\n * // => 3.2\n *\n * _.toNumber(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toNumber(Infinity);\n * // => Infinity\n *\n * _.toNumber('3.2');\n * // => 3.2\n */\nfunction toNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n if (isObject(value)) {\n var other = typeof value.valueOf == 'function' ? value.valueOf() : value;\n value = isObject(other) ? (other + '') : other;\n }\n if (typeof value != 'string') {\n return value === 0 ? value : +value;\n }\n value = value.replace(reTrim, '');\n var isBinary = reIsBinary.test(value);\n return (isBinary || reIsOctal.test(value))\n ? freeParseInt(value.slice(2), isBinary ? 2 : 8)\n : (reIsBadHex.test(value) ? NAN : +value);\n}\n\nmodule.exports = debounce;\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"media-proxy-cache-container\"},[_c('div',{staticClass:\"media-proxy-cache-header-container\"},[_c('h1',[_vm._v(_vm._s(_vm.$t('mediaProxyCache.mediaProxyCache')))]),_vm._v(\" \"),_c('reboot-button')],1),_vm._v(\" \"),_c('p',{staticClass:\"media-proxy-cache-header\"},[_vm._v(_vm._s(_vm.$t('mediaProxyCache.evictObjectsHeader')))]),_vm._v(\" \"),_c('div',{staticClass:\"url-input-container\"},[_c('el-input',{staticClass:\"url-input\",attrs:{\"placeholder\":_vm.$t('mediaProxyCache.url'),\"type\":\"textarea\",\"autosize\":\"\",\"clearable\":\"\"},model:{value:(_vm.urls),callback:function ($$v) {_vm.urls=$$v},expression:\"urls\"}}),_vm._v(\" \"),_c('el-checkbox',{model:{value:(_vm.ban),callback:function ($$v) {_vm.ban=$$v},expression:\"ban\"}},[_vm._v(_vm._s(_vm.$t('mediaProxyCache.ban')))]),_vm._v(\" \"),_c('el-button',{staticClass:\"evict-button\",on:{\"click\":_vm.evictURL}},[_vm._v(_vm._s(_vm.$t('mediaProxyCache.evict')))])],1),_vm._v(\" \"),_c('span',{staticClass:\"expl url-input-expl\"},[_vm._v(_vm._s(_vm.$t('mediaProxyCache.multipleInput')))]),_vm._v(\" \"),_c('p',{staticClass:\"media-proxy-cache-header\"},[_vm._v(_vm._s(_vm.$t('mediaProxyCache.listBannedUrlsHeader')))]),_vm._v(\" \"),_c('el-table',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.loading),expression:\"loading\"}],staticClass:\"banned-urls-table\",attrs:{\"data\":_vm.bannedUrls},on:{\"selection-change\":_vm.handleSelectionChange}},[_vm._v(\">\\n \"),_c('el-table-column',{attrs:{\"type\":\"selection\",\"align\":\"center\",\"width\":\"55\"}}),_vm._v(\" \"),_c('el-table-column',{attrs:{\"min-width\":_vm.isDesktop ? 320 : 120,\"prop\":\"url\"},scopedSlots:_vm._u([{key:\"header\",fn:function(scope){return [_c('el-input',{attrs:{\"placeholder\":_vm.$t('users.search'),\"size\":\"mini\",\"prefix-icon\":\"el-icon-search\"},on:{\"input\":_vm.handleDebounceSearchInput},model:{value:(_vm.search),callback:function ($$v) {_vm.search=$$v},expression:\"search\"}})]}}])}),_vm._v(\" \"),_c('el-table-column',{scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-button',{staticClass:\"remove-url-button\",attrs:{\"size\":\"mini\"},on:{\"click\":function($event){return _vm.removeUrl(scope.row.url)}}},[_vm._v(_vm._s(_vm.$t('mediaProxyCache.remove')))])]}}])},[_c('template',{slot:\"header\"},[_c('el-button',{staticClass:\"remove-url-button\",attrs:{\"disabled\":_vm.removeSelectedDisabled,\"size\":\"mini\"},on:{\"click\":function($event){return _vm.removeSelected()}}},[_vm._v(_vm._s(_vm.$t('mediaProxyCache.removeSelected')))])],1)],2)],1),_vm._v(\" \"),(!_vm.loading)?_c('div',{staticClass:\"pagination\"},[_c('el-pagination',{attrs:{\"total\":_vm.urlsCount,\"current-page\":_vm.currentPage,\"page-size\":_vm.pageSize,\"hide-on-single-page\":\"\",\"layout\":\"prev, pager, next\"},on:{\"current-change\":_vm.handlePageChange}})],1):_vm._e()],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import mod from \"-!../../../node_modules/babel-loader/lib/index.js?cacheDirectory!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./index.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../node_modules/babel-loader/lib/index.js?cacheDirectory!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./index.vue?vue&type=script&lang=js&\"","\n