diff --git a/CHANGELOG.md b/CHANGELOG.md index 3eb4f0bdf..7afe5c21b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,6 +76,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - OAuth: admin scopes support (relevant setting: `[:auth, :enforce_oauth_admin_scope_usage]`). - New HTTP adapter [gun](https://github.com/ninenines/gun). Gun adapter requires minimum OTP version of 22.2 otherwise Pleroma won’t start. For hackney OTP update is not required. - Add an option `authorized_fetch_mode` to require HTTP signatures for AP fetches. +- ActivityPub: support for `replies` collection (output for outgoing federation & fetching on incoming federation). +- Mix task to refresh counter cache (`mix pleroma.refresh_counter_cache`)
API Changes @@ -103,6 +105,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Configuration: `feed` option for user atom feed. - Pleroma API: Add Emoji reactions - Admin API: Add `/api/pleroma/admin/instances/:instance/statuses` - lists all statuses from a given instance +- Admin API: Add `/api/pleroma/admin/users/:nickname/statuses` - lists all statuses from a given user - Admin API: `PATCH /api/pleroma/users/confirm_email` to confirm email for multiple users, `PATCH /api/pleroma/users/resend_confirmation_email` to resend confirmation email for multiple users - ActivityPub: Configurable `type` field of the actors. - Mastodon API: `/api/v1/accounts/:id` has `source/pleroma/actor_type` field. @@ -118,6 +121,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Tag feed: `/tags/:tag.rss` - list public statuses by hashtag. - Mastodon API: Add `reacted` property to `emoji_reactions` - Pleroma API: Add reactions for a single emoji. +- ActivityPub: `[:activitypub, :note_replies_output_limit]` setting sets the number of note self-replies to output on outgoing federation. +- Admin API: `GET /api/pleroma/admin/stats` to get status count by visibility scope +- Admin API: `GET /api/pleroma/admin/statuses` - list all statuses (accepts `godmode` and `local_only`)
### Fixed diff --git a/config/config.exs b/config/config.exs index 7f3a4d1b6..ed074a99c 100644 --- a/config/config.exs +++ b/config/config.exs @@ -198,6 +198,8 @@ max_expiration: 365 * 24 * 60 * 60 }, registrations_open: true, + invites_enabled: false, + account_activation_required: false, federating: true, federation_incoming_replies_max_depth: 100, federation_reachability_timeout_days: 7, @@ -305,6 +307,7 @@ unfollow_blocked: true, outgoing_blocks: true, follow_handshake_timeout: 500, + note_replies_output_limit: 5, sign_object_fetches: true, authorized_fetch_mode: false @@ -378,6 +381,8 @@ config :phoenix, :json_library, Jason +config :phoenix, :filter_parameters, ["password", "confirm"] + config :pleroma, :gopher, enabled: false, ip: {0, 0, 0, 0}, @@ -460,6 +465,7 @@ transmogrifier: 20, scheduled_activities: 10, background: 5, + remote_fetcher: 2, attachments_cleanup: 5, new_users_digest: 1 ], diff --git a/config/description.exs b/config/description.exs index ed93bd0b9..53edaa6a8 100644 --- a/config/description.exs +++ b/config/description.exs @@ -662,7 +662,7 @@ label: "Fed. incoming replies max depth", type: :integer, description: - "Max. depth of reply-to activities fetching on incoming federation, to prevent out-of-memory situations while" <> + "Max. depth of reply-to and reply activities fetching on incoming federation, to prevent out-of-memory situations while" <> " fetching very long threads. If set to `nil`, threads of any depth will be fetched. Lower this value if you experience out-of-memory crashes.", suggestions: [ 100 @@ -1615,160 +1615,6 @@ } ] }, - %{ - group: :pleroma, - key: Pleroma.Web.Endpoint, - type: :group, - description: "Phoenix endpoint configuration", - children: [ - %{ - key: :http, - label: "HTTP", - type: {:keyword, :integer, :tuple}, - description: "http protocol configuration", - suggestions: [ - port: 8080, - ip: {127, 0, 0, 1} - ], - children: [ - %{ - key: :dispatch, - type: {:list, :tuple}, - description: "dispatch settings", - suggestions: [ - {:_, - [ - {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, - {"/websocket", Phoenix.Endpoint.CowboyWebSocket, - {Phoenix.Transports.WebSocket, - {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, websocket_config}}}, - {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}} - ]} - # end copied from config.exs - ] - }, - %{ - key: :ip, - label: "IP", - type: :tuple, - description: "ip", - suggestions: [ - {0, 0, 0, 0} - ] - }, - %{ - key: :port, - type: :integer, - description: "port", - suggestions: [ - 2020 - ] - } - ] - }, - %{ - key: :url, - label: "URL", - type: {:keyword, :string, :integer}, - description: "configuration for generating urls", - suggestions: [ - host: "example.com", - port: 2020, - scheme: "https" - ], - children: [ - %{ - key: :host, - type: :string, - description: "Host", - suggestions: [ - "example.com" - ] - }, - %{ - key: :port, - type: :integer, - description: "port", - suggestions: [ - 2020 - ] - }, - %{ - key: :scheme, - type: :string, - description: "Scheme", - suggestions: [ - "https", - "https" - ] - } - ] - }, - %{ - key: :instrumenters, - type: {:list, :module}, - suggestions: [Pleroma.Web.Endpoint.Instrumenter] - }, - %{ - key: :protocol, - type: :string, - suggestions: ["https"] - }, - %{ - key: :secret_key_base, - type: :string, - suggestions: ["aK4Abxf29xU9TTDKre9coZPUgevcVCFQJe/5xP/7Lt4BEif6idBIbjupVbOrbKxl"] - }, - %{ - key: :signing_salt, - type: :string, - suggestions: ["CqaoopA2"] - }, - %{ - key: :render_errors, - type: :keyword, - suggestions: [view: Pleroma.Web.ErrorView, accepts: ~w(json)], - children: [ - %{ - key: :view, - type: :module, - suggestions: [Pleroma.Web.ErrorView] - }, - %{ - key: :accepts, - type: {:list, :string}, - suggestions: ["json"] - } - ] - }, - %{ - key: :pubsub, - type: :keyword, - suggestions: [name: Pleroma.PubSub, adapter: Phoenix.PubSub.PG2], - children: [ - %{ - key: :name, - type: :module, - suggestions: [Pleroma.PubSub] - }, - %{ - key: :adapter, - type: :module, - suggestions: [Phoenix.PubSub.PG2] - } - ] - }, - %{ - key: :secure_cookie_flag, - type: :boolean - }, - %{ - key: :extra_cookie_attrs, - type: {:list, :string}, - suggestions: ["SameSite=Lax"] - } - ] - }, %{ group: :pleroma, key: :activitypub, @@ -1790,6 +1636,12 @@ type: :boolean, description: "Sign object fetches with HTTP signatures" }, + %{ + key: :note_replies_output_limit, + type: :integer, + description: + "The number of Note replies' URIs to be included with outgoing federation (`5` to match Mastodon hardcoded value, `0` to disable the output)." + }, %{ key: :follow_handshake_timeout, type: :integer, @@ -2588,19 +2440,6 @@ } ] }, - %{ - group: :pleroma, - key: :database, - type: :group, - description: "Database related settings", - children: [ - %{ - key: :rum_enabled, - type: :boolean, - description: "If RUM indexes should be used. Default: disabled" - } - ] - }, %{ group: :pleroma, key: :rate_limit, @@ -2764,20 +2603,6 @@ } ] }, - %{ - group: :prometheus, - key: Pleroma.Web.Endpoint.MetricsExporter, - type: :group, - description: "Prometheus settings", - children: [ - %{ - key: :path, - type: :string, - description: "API endpoint with metrics", - suggestions: ["/api/pleroma/app_metrics"] - } - ] - }, %{ group: :http_signatures, type: :group, @@ -3045,7 +2870,7 @@ group: :pleroma, key: :feed, type: :group, - description: "Configure feed rendering.", + description: "Configure feed rendering", children: [ %{ key: :post_title, @@ -3095,7 +2920,7 @@ group: :pleroma, key: :modules, type: :group, - description: "Custom Runtime Modules.", + description: "Custom Runtime Modules", children: [ %{ key: :runtime_dir, @@ -3103,18 +2928,5 @@ description: "A path to custom Elixir modules (such as MRF policies)." } ] - }, - %{ - group: :pleroma, - type: :group, - description: "Allow instance configuration from database.", - children: [ - %{ - key: :configurable_from_database, - type: :boolean, - description: - "Allow transferring configuration to DB with the subsequent customization from Admin api. Default: disabled" - } - ] } ] diff --git a/docs/API/admin_api.md b/docs/API/admin_api.md index 4a448c1a5..e3f494795 100644 --- a/docs/API/admin_api.md +++ b/docs/API/admin_api.md @@ -260,10 +260,24 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret - `nickname` or `id` - *optional* `page_size`: number of statuses to return (default is `20`) - *optional* `godmode`: `true`/`false` – allows to see private statuses + - *optional* `with_reblogs`: `true`/`false` – allows to see reblogs (default is false) - Response: - On failure: `Not found` - On success: JSON array of user's latest statuses +## `GET /api/pleroma/admin/instances/:instance/statuses` + +### Retrive instance's latest statuses + +- Params: + - `instance`: instance name + - *optional* `page_size`: number of statuses to return (default is `20`) + - *optional* `godmode`: `true`/`false` – allows to see private statuses + - *optional* `with_reblogs`: `true`/`false` – allows to see reblogs (default is false) +- Response: + - On failure: `Not found` + - On success: JSON array of instance's latest statuses + ## `POST /api/pleroma/admin/relay` ### Follow a Relay @@ -941,3 +955,20 @@ Loads json generated from `config/descriptions.exs`. - Params: - `nicknames` - Response: Array of user nicknames + +## `GET /api/pleroma/admin/stats` + +### Stats + +- Response: + +```json +{ + "status_visibility": { + "direct": 739, + "private": 9, + "public": 17, + "unlisted": 14 + } +} +``` diff --git a/docs/administration/backup.md b/docs/administration/backup.md index 685c45128..692aa7368 100644 --- a/docs/administration/backup.md +++ b/docs/administration/backup.md @@ -18,7 +18,9 @@ 6. Run `sudo -Hu postgres pg_restore -d -v -1 ` 7. If you installed a newer Pleroma version, you should run `mix ecto.migrate`[^1]. This task performs database migrations, if there were any. 8. Restart the Pleroma service. - +9. After you've restarted Pleroma, you will notice that postgres will take up more cpu resources than usual. A lot in fact. To fix this you must do a VACUUM ANLAYZE. This can also be done while the instance is still running like so: + $ sudo -u postgres psql pleroma_database_name + pleroma=# VACUUM ANALYZE; [^1]: Prefix with `MIX_ENV=prod` to run it using the production config file. ## Remove diff --git a/docs/configuration/howto_theming_your_instance.md b/docs/configuration/howto_theming_your_instance.md new file mode 100644 index 000000000..d0daf5b25 --- /dev/null +++ b/docs/configuration/howto_theming_your_instance.md @@ -0,0 +1,74 @@ +# Theming your instance + +To add a custom theme to your instance, you'll first need to get a custom theme, upload it to the server, make it available to the instance and eventually you can set it as default. + +## Getting a custom theme + +### Create your own theme + +* You can create your own theme using the Pleroma FE by going to settings (gear on the top right) and choose the Theme tab. Here you have the options to create a personal theme. +* To download your theme, you can do Save preset +* If you want to upload a theme to customise it further, you can upload it using Load preset + +This will only save the theme for you personally. To make it available to the whole instance, you'll need to upload it to the server. + +### Get an existing theme + +* You can download a theme from another instance by going to that instance, go to settings and make sure you have the theme selected that you want. Then you can do Save preset to download it. +* You can also find and download custom themes at + +## Adding the custom theme to the instance + +### Upload the theme to the server + +Themes can be found in the [static directory](static_dir.md). Create `STATIC-DIR/static/themes/` if needed and copy your theme there. Next you need to add an entry for your theme to `STATIC-DIR/static/styles.json`. If you use a from source installation, you'll first need to copy the file from `priv/static/static/styles.json`. + +Example of `styles.json` where we add our own `my-awesome-theme.json` +```json +{ + "pleroma-dark": [ "Pleroma Dark", "#121a24", "#182230", "#b9b9ba", "#d8a070", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ], + "pleroma-light": [ "Pleroma Light", "#f2f4f6", "#dbe0e8", "#304055", "#f86f0f", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ], + "classic-dark": [ "Classic Dark", "#161c20", "#282e32", "#b9b9b9", "#baaa9c", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ], + "bird": [ "Bird", "#f8fafd", "#e6ecf0", "#14171a", "#0084b8", "#e0245e", "#17bf63", "#1b95e0", "#fab81e"], + "ir-black": [ "Ir Black", "#000000", "#242422", "#b5b3aa", "#ff6c60", "#FF6C60", "#A8FF60", "#96CBFE", "#FFFFB6" ], + "monokai": [ "Monokai", "#272822", "#383830", "#f8f8f2", "#f92672", "#F92672", "#a6e22e", "#66d9ef", "#f4bf75" ], + + "redmond-xx": "/static/themes/redmond-xx.json", + "redmond-xx-se": "/static/themes/redmond-xx-se.json", + "redmond-xxi": "/static/themes/redmond-xxi.json", + "breezy-dark": "/static/themes/breezy-dark.json", + "breezy-light": "/static/themes/breezy-light.json", + "mammal": "/static/themes/mammal.json", + "my-awesome-theme": "/static/themes/my-awesome-theme.json" +} +``` + +Now you'll already be able to select the theme in Pleroma FE from the drop-down. You don't need to restart Pleroma because we only changed static served files. You may need to refresh the page in your browser. You'll notice however that the theme doesn't have a name, it's just an empty entry in the drop-down. + +### Give the theme a name + +When you open one of the themes that ship with Pleroma, you'll notice that the json has a `"name"` key. Add a key-value pair to your theme where the key name is `"name"` and the value the name you want to give your theme. After this you can refresh te page in your browser and the name should be visible in the drop-down. + +Example of `my-awesome-theme.json` where we add the name "My Awesome Theme" +```json +{ + "_pleroma_theme_version": 2, + "name": "My Awesome Theme", + "theme": {} +} +``` + +### Set as default theme + +Now we can set the new theme as default in the [Pleroma FE configuration](General-tips-for-customizing-Pleroma-FE.md). + +Example of adding the new theme in the back-end config files +```elixir +config :pleroma, :frontend_configurations, + pleroma_fe: %{ + theme: "my-awesome-theme" + } +``` + +If you added it in the back-end configuration file, you'll need to restart your instance for the changes to take effect. If you don't see the changes, it's probably because the browser has cached the previous theme. In that case you'll want to clear browser caches. Alternatively you can use a private/incognito window just to see the changes. + diff --git a/docs/introduction.md b/docs/introduction.md index 823e14f53..a915c143c 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -41,7 +41,7 @@ On the top right you will also see a wrench icon. This opens your personal setti This is where the interesting stuff happens! Depending on the timeline you will see different statuses, but each status has a standard structure: -- Profile pic, name and link to profile. An optional left-arrow if it's a reply to another status (hovering will reveal the replied-to status). Clicking on the profile pic will uncollapse the user's profile. +- Profile pic, name and link to profile. An optional left-arrow if it's a reply to another status (hovering will reveal the reply-to status). Clicking on the profile pic will uncollapse the user's profile. - A `+` button on the right allows you to Expand/Collapse an entire discussion thread. It also updates in realtime! - An arrow icon allows you to open the status on the instance where it's originating from. - The text of the status, including mentions and attachements. If you click on a mention, it will automatically open the profile page of that person. diff --git a/lib/mix/tasks/pleroma/emoji.ex b/lib/mix/tasks/pleroma/emoji.ex index b4e8d3a0b..adac47c86 100644 --- a/lib/mix/tasks/pleroma/emoji.ex +++ b/lib/mix/tasks/pleroma/emoji.ex @@ -185,11 +185,7 @@ def run(["gen-pack", src]) do tmp_pack_dir = Path.join(System.tmp_dir!(), "emoji-pack-#{name}") - {:ok, _} = - :zip.unzip( - binary_archive, - cwd: tmp_pack_dir - ) + {:ok, _} = :zip.unzip(binary_archive, cwd: String.to_charlist(tmp_pack_dir)) emoji_map = Pleroma.Emoji.Loader.make_shortcode_to_file_map(tmp_pack_dir, exts) diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex index 9af6cda30..54d34e42f 100644 --- a/lib/mix/tasks/pleroma/instance.ex +++ b/lib/mix/tasks/pleroma/instance.ex @@ -6,6 +6,8 @@ defmodule Mix.Tasks.Pleroma.Instance do use Mix.Task import Mix.Pleroma + alias Pleroma.Config + @shortdoc "Manages Pleroma instance" @moduledoc File.read!("docs/administration/CLI_tasks/instance.md") @@ -63,7 +65,8 @@ def run(["gen" | rest]) do get_option( options, :instance_name, - "What is the name of your instance? (e.g. Pleroma/Soykaf)" + "What is the name of your instance? (e.g. The Corndog Emporium)", + domain ) email = get_option(options, :admin_email, "What is your admin email address?") @@ -153,6 +156,8 @@ def run(["gen" | rest]) do Pleroma.Config.get([:instance, :static_dir]) ) + Config.put([:instance, :static_dir], static_dir) + secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64) jwt_secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64) signing_salt = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8) @@ -202,8 +207,14 @@ def run(["gen" | rest]) do write_robots_txt(indexable, template_dir) shell_info( - "\n All files successfully written! Refer to the installation instructions for your platform for next steps" + "\n All files successfully written! Refer to the installation instructions for your platform for next steps." ) + + if db_configurable? do + shell_info( + " Please transfer your config to the database after running database migrations. Refer to \"Transfering the config to/from the database\" section of the docs for more information." + ) + end else shell_error( "The task would have overwritten the following files:\n" <> diff --git a/lib/mix/tasks/pleroma/refresh_counter_cache.ex b/lib/mix/tasks/pleroma/refresh_counter_cache.ex new file mode 100644 index 000000000..bc2571efd --- /dev/null +++ b/lib/mix/tasks/pleroma/refresh_counter_cache.ex @@ -0,0 +1,46 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.RefreshCounterCache do + @shortdoc "Refreshes counter cache" + + use Mix.Task + + alias Pleroma.Activity + alias Pleroma.CounterCache + alias Pleroma.Repo + + require Logger + import Ecto.Query + + def run([]) do + Mix.Pleroma.start_pleroma() + + ["public", "unlisted", "private", "direct"] + |> Enum.each(fn visibility -> + count = status_visibility_count_query(visibility) + name = "status_visibility_#{visibility}" + CounterCache.set(name, count) + Mix.Pleroma.shell_info("Set #{name} to #{count}") + end) + + Mix.Pleroma.shell_info("Done") + end + + defp status_visibility_count_query(visibility) do + Activity + |> where( + [a], + fragment( + "activity_visibility(?, ?, ?) = ?", + a.actor, + a.recipients, + a.data, + ^visibility + ) + ) + |> where([a], fragment("(? ->> 'type'::text) = 'Create'", a.data)) + |> Repo.aggregate(:count, :id, timeout: :timer.minutes(30)) + end +end diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex index 85c9e4954..ba10a705a 100644 --- a/lib/mix/tasks/pleroma/user.ex +++ b/lib/mix/tasks/pleroma/user.ex @@ -100,8 +100,7 @@ def run(["rm", nickname]) do User.perform(:delete, user) shell_info("User #{nickname} deleted.") else - _ -> - shell_error("No local user #{nickname}") + _ -> shell_error("No local user #{nickname}") end end diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index 72e2256ea..7fb1f913b 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -310,7 +310,7 @@ def follow_requests_for_actor(%Pleroma.User{ap_id: ap_id}) do def restrict_deactivated_users(query) do deactivated_users = - from(u in User.Query.build(deactivated: true), select: u.ap_id) + from(u in User.Query.build(%{deactivated: true}), select: u.ap_id) |> Repo.all() Activity.Queries.exclude_authors(query, deactivated_users) diff --git a/lib/pleroma/activity/queries.ex b/lib/pleroma/activity/queries.ex index 79f305201..8d08d81ca 100644 --- a/lib/pleroma/activity/queries.ex +++ b/lib/pleroma/activity/queries.ex @@ -7,7 +7,7 @@ defmodule Pleroma.Activity.Queries do Contains queries for Activity. """ - import Ecto.Query, only: [from: 2] + import Ecto.Query, only: [from: 2, where: 3] @type query :: Ecto.Queryable.t() | Activity.t() @@ -30,7 +30,7 @@ def by_actor(query \\ Activity, actor) do ) end - @spec by_author(query, String.t()) :: query + @spec by_author(query, User.t()) :: query def by_author(query \\ Activity, %User{ap_id: ap_id}) do from(a in query, where: a.actor == ^ap_id) end @@ -63,6 +63,22 @@ def by_object_id(query, object_id) when is_binary(object_id) do ) end + @spec by_object_in_reply_to_id(query, String.t(), keyword()) :: query + def by_object_in_reply_to_id(query, in_reply_to_id, opts \\ []) do + query = + if opts[:skip_preloading] do + Activity.with_joined_object(query) + else + Activity.with_preloaded_object(query) + end + + where( + query, + [activity, object: o], + fragment("(?)->>'inReplyTo' = ?", o.data, ^to_string(in_reply_to_id)) + ) + end + @spec by_type(query, String.t()) :: query def by_type(query \\ Activity, activity_type) do from( diff --git a/lib/pleroma/captcha/captcha.ex b/lib/pleroma/captcha/captcha.ex index c2765a5b8..cf75c3adc 100644 --- a/lib/pleroma/captcha/captcha.ex +++ b/lib/pleroma/captcha/captcha.ex @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors +# Copyright © 2017-2020 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Captcha do @@ -50,7 +50,7 @@ def handle_call(:new, _from, state) do token = new_captcha[:token] secret = KeyGenerator.generate(secret_key_base, token <> "_encrypt") sign_secret = KeyGenerator.generate(secret_key_base, token <> "_sign") - # Basicallty copy what Phoenix.Token does here, add the time to + # Basically copy what Phoenix.Token does here, add the time to # the actual data and make it a binary to then encrypt it encrypted_captcha_answer = %{ @@ -62,7 +62,7 @@ def handle_call(:new, _from, state) do { :reply, - # Repalce the answer with the encrypted answer + # Replace the answer with the encrypted answer %{new_captcha | answer_data: encrypted_captcha_answer}, state } @@ -82,7 +82,8 @@ def handle_call({:validate, token, captcha, answer_data}, _from, state) do valid_if_after = DateTime.subtract!(DateTime.now_utc(), seconds_valid) result = - with {:ok, data} <- MessageEncryptor.decrypt(answer_data, secret, sign_secret), + with false <- is_nil(answer_data), + {:ok, data} <- MessageEncryptor.decrypt(answer_data, secret, sign_secret), %{at: at, answer_data: answer_md5} <- :erlang.binary_to_term(data) do try do if DateTime.before?(at, valid_if_after), diff --git a/lib/pleroma/captcha/native.ex b/lib/pleroma/captcha/native.ex index 5306fe1aa..2c8db2c30 100644 --- a/lib/pleroma/captcha/native.ex +++ b/lib/pleroma/captcha/native.ex @@ -10,8 +10,8 @@ defmodule Pleroma.Captcha.Native do @impl Service def new do case Captcha.get() do - {:timeout} -> - %{error: dgettext("errors", "Captcha timeout")} + :error -> + %{error: dgettext("errors", "Captcha error")} {:ok, answer_data, img_binary} -> %{ diff --git a/lib/pleroma/conversation/participation.ex b/lib/pleroma/conversation/participation.ex index e5d28ebff..d4b255537 100644 --- a/lib/pleroma/conversation/participation.ex +++ b/lib/pleroma/conversation/participation.ex @@ -133,10 +133,8 @@ def restrict_recipients(query, user, %{"recipients" => user_ids}) do [user.id | user_ids] |> Enum.uniq() |> Enum.reduce([], fn user_id, acc -> - case FlakeId.Ecto.CompatType.dump(user_id) do - {:ok, user_id} -> [user_id | acc] - _ -> acc - end + {:ok, user_id} = FlakeId.Ecto.CompatType.dump(user_id) + [user_id | acc] end) conversation_subquery = diff --git a/lib/pleroma/counter_cache.ex b/lib/pleroma/counter_cache.ex new file mode 100644 index 000000000..8e868e956 --- /dev/null +++ b/lib/pleroma/counter_cache.ex @@ -0,0 +1,41 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.CounterCache do + alias Pleroma.CounterCache + alias Pleroma.Repo + use Ecto.Schema + import Ecto.Changeset + import Ecto.Query + + schema "counter_cache" do + field(:name, :string) + field(:count, :integer) + end + + def changeset(struct, params) do + struct + |> cast(params, [:name, :count]) + |> validate_required([:name]) + |> unique_constraint(:name) + end + + def get_as_map(names) when is_list(names) do + CounterCache + |> where([cc], cc.name in ^names) + |> Repo.all() + |> Enum.group_by(& &1.name, & &1.count) + |> Map.new(fn {k, v} -> {k, hd(v)} end) + end + + def set(name, count) do + %CounterCache{} + |> changeset(%{"name" => name, "count" => count}) + |> Repo.insert( + on_conflict: [set: [count: count]], + returning: true, + conflict_target: :name + ) + end +end diff --git a/lib/pleroma/mime.ex b/lib/pleroma/mime.ex index 36771533f..08f96f7bf 100644 --- a/lib/pleroma/mime.ex +++ b/lib/pleroma/mime.ex @@ -9,7 +9,7 @@ defmodule Pleroma.MIME do @default "application/octet-stream" @read_bytes 35 - @spec file_mime_type(String.t()) :: + @spec file_mime_type(String.t(), String.t()) :: {:ok, content_type :: String.t(), filename :: String.t()} | {:error, any()} | :error def file_mime_type(path, filename) do with {:ok, content_type} <- file_mime_type(path), diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex index 52556bf31..f316f8b36 100644 --- a/lib/pleroma/object.ex +++ b/lib/pleroma/object.ex @@ -301,4 +301,26 @@ def update_data(%Object{data: data} = object, attrs \\ %{}) do def local?(%Object{data: %{"id" => id}}) do String.starts_with?(id, Pleroma.Web.base_url() <> "/") end + + def replies(object, opts \\ []) do + object = Object.normalize(object) + + query = + Object + |> where( + [o], + fragment("(?)->>'inReplyTo' = ?", o.data, ^object.data["id"]) + ) + |> order_by([o], asc: o.id) + + if opts[:self_only] do + actor = object.data["actor"] + where(query, [o], fragment("(?)->>'actor' = ?", o.data, ^actor)) + else + query + end + end + + def self_replies(object, opts \\ []), + do: replies(object, Keyword.put(opts, :self_only, true)) end diff --git a/lib/pleroma/object/containment.ex b/lib/pleroma/object/containment.ex index 25aa32f60..9efa50edb 100644 --- a/lib/pleroma/object/containment.ex +++ b/lib/pleroma/object/containment.ex @@ -39,15 +39,8 @@ def get_actor(%{"actor" => nil, "attributedTo" => actor}) when not is_nil(actor) defp compare_uris(_, %URI{scheme: "tag"}), do: :ok end - defp compare_uris(%URI{} = id_uri, %URI{} = other_uri) do - if id_uri.host == other_uri.host do - :ok - else - :error - end - end - - defp compare_uris(_, _), do: :error + defp compare_uris(%URI{host: host} = _id_uri, %URI{host: host} = _other_uri), do: :ok + defp compare_uris(_id_uri, _other_uri), do: :error @doc """ Checks that an imported AP object's actor matches the domain it came from. diff --git a/lib/pleroma/object/fetcher.ex b/lib/pleroma/object/fetcher.ex index 5e9bf1574..d7fd35f1d 100644 --- a/lib/pleroma/object/fetcher.ex +++ b/lib/pleroma/object/fetcher.ex @@ -10,6 +10,7 @@ defmodule Pleroma.Object.Fetcher do alias Pleroma.Signature alias Pleroma.Web.ActivityPub.InternalFetchActor alias Pleroma.Web.ActivityPub.Transmogrifier + alias Pleroma.Web.Federator require Logger require Pleroma.Constants @@ -59,20 +60,23 @@ def refetch_object(%Object{data: %{"id" => id}} = object) do end end - # TODO: - # This will create a Create activity, which we need internally at the moment. + # Note: will create a Create activity, which we need internally at the moment. def fetch_object_from_id(id, options \\ []) do - with {:fetch_object, nil} <- {:fetch_object, Object.get_cached_by_ap_id(id)}, - {:fetch, {:ok, data}} <- {:fetch, fetch_and_contain_remote_object_from_id(id)}, - {:normalize, nil} <- {:normalize, Object.normalize(data, false)}, + with {_, nil} <- {:fetch_object, Object.get_cached_by_ap_id(id)}, + {_, true} <- {:allowed_depth, Federator.allowed_thread_distance?(options[:depth])}, + {_, {:ok, data}} <- {:fetch, fetch_and_contain_remote_object_from_id(id)}, + {_, nil} <- {:normalize, Object.normalize(data, false)}, params <- prepare_activity_params(data), - {:containment, :ok} <- {:containment, Containment.contain_origin(id, params)}, - {:transmogrifier, {:ok, activity}} <- + {_, :ok} <- {:containment, Containment.contain_origin(id, params)}, + {_, {:ok, activity}} <- {:transmogrifier, Transmogrifier.handle_incoming(params, options)}, - {:object, _data, %Object{} = object} <- + {_, _data, %Object{} = object} <- {:object, data, Object.normalize(activity, false)} do {:ok, object} else + {:allowed_depth, false} -> + {:error, "Max thread distance exceeded."} + {:containment, _} -> {:error, "Object containment failed."} diff --git a/lib/pleroma/stats.ex b/lib/pleroma/stats.ex index cf590fb01..771a06e32 100644 --- a/lib/pleroma/stats.ex +++ b/lib/pleroma/stats.ex @@ -4,6 +4,7 @@ defmodule Pleroma.Stats do import Ecto.Query + alias Pleroma.CounterCache alias Pleroma.Repo alias Pleroma.User @@ -96,4 +97,21 @@ defp get_stat_data do } } end + + def get_status_visibility_count do + counter_cache = + CounterCache.get_as_map([ + "status_visibility_public", + "status_visibility_private", + "status_visibility_unlisted", + "status_visibility_direct" + ]) + + %{ + public: counter_cache["status_visibility_public"] || 0, + unlisted: counter_cache["status_visibility_unlisted"] || 0, + private: counter_cache["status_visibility_private"] || 0, + direct: counter_cache["status_visibility_direct"] || 0 + } + end end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 5ea36fea3..56e599ecc 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -853,14 +853,14 @@ def get_followers_query(user, page) do @spec get_followers_query(User.t()) :: Ecto.Query.t() def get_followers_query(user), do: get_followers_query(user, nil) - @spec get_followers(User.t(), pos_integer()) :: {:ok, list(User.t())} + @spec get_followers(User.t(), pos_integer() | nil) :: {:ok, list(User.t())} def get_followers(user, page \\ nil) do user |> get_followers_query(page) |> Repo.all() end - @spec get_external_followers(User.t(), pos_integer()) :: {:ok, list(User.t())} + @spec get_external_followers(User.t(), pos_integer() | nil) :: {:ok, list(User.t())} def get_external_followers(user, page \\ nil) do user |> get_followers_query(page) @@ -1304,7 +1304,6 @@ def perform(:delete, %User{} = user) do Repo.delete(user) end - @spec perform(atom(), User.t()) :: {:ok, User.t()} def perform(:fetch_initial_posts, %User{} = user) do pages = Pleroma.Config.get!([:fetch_initial_posts, :pages]) @@ -1336,7 +1335,6 @@ def perform(:blocks_import, %User{} = blocker, blocked_identifiers) ) end - @spec perform(atom(), User.t(), list()) :: list() | {:error, any()} def perform(:follow_import, %User{} = follower, followed_identifiers) when is_list(followed_identifiers) do Enum.map( diff --git a/lib/pleroma/user/query.ex b/lib/pleroma/user/query.ex index 364bc1c89..4358907cb 100644 --- a/lib/pleroma/user/query.ex +++ b/lib/pleroma/user/query.ex @@ -48,7 +48,7 @@ defmodule Pleroma.User.Query do followers: User.t(), friends: User.t(), recipients_from_activity: [String.t()], - nickname: [String.t()], + nickname: [String.t()] | String.t(), ap_id: [String.t()], order_by: term(), select: term(), diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex index 6b55df483..1cfecef83 100644 --- a/lib/pleroma/user/search.ex +++ b/lib/pleroma/user/search.ex @@ -33,9 +33,15 @@ defp format_query(query_string) do # Strip the beginning @ off if there is a query query_string = String.trim_leading(query_string, "@") - with [name, domain] <- String.split(query_string, "@"), - formatted_domain <- String.replace(domain, ~r/[!-\-|@|[-`|{-~|\/|:|\s]+/, "") do - name <> "@" <> to_string(:idna.encode(formatted_domain)) + with [name, domain] <- String.split(query_string, "@") do + encoded_domain = + domain + |> String.replace(~r/[!-\-|@|[-`|{-~|\/|:|\s]+/, "") + |> String.to_charlist() + |> :idna.encode() + |> to_string() + + name <> "@" <> encoded_domain else _ -> query_string end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 5c436941a..12695b3f9 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -770,13 +770,18 @@ def fetch_user_activities(user, reading_user, params \\ %{}) do |> Enum.reverse() end - def fetch_instance_activities(params) do + def fetch_statuses(reading_user, params) do params = params |> Map.put("type", ["Create", "Announce"]) - |> Map.put("instance", params["instance"]) - fetch_activities([Pleroma.Constants.as_public()], params, :offset) + recipients = + user_activities_recipients(%{ + "godmode" => params["godmode"], + "reading_user" => reading_user + }) + + fetch_activities(recipients, params, :offset) |> Enum.reverse() end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index a72d8430f..3afc82345 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -156,10 +156,11 @@ def fix_in_reply_to(%{"inReplyTo" => in_reply_to} = object, options) when not is_nil(in_reply_to) do in_reply_to_id = prepare_in_reply_to(in_reply_to) object = Map.put(object, "inReplyToAtomUri", in_reply_to_id) + depth = (options[:depth] || 0) + 1 - if Federator.allowed_incoming_reply_depth?(options[:depth]) do + if Federator.allowed_thread_distance?(depth) do with {:ok, replied_object} <- get_obj_helper(in_reply_to_id, options), - %Activity{} = _ <- Activity.get_create_by_object_ap_id(replied_object.data["id"]) do + %Activity{} <- Activity.get_create_by_object_ap_id(replied_object.data["id"]) do object |> Map.put("inReplyTo", replied_object.data["id"]) |> Map.put("inReplyToAtomUri", object["inReplyToAtomUri"] || in_reply_to_id) @@ -312,7 +313,7 @@ def fix_type(object, options \\ []) def fix_type(%{"inReplyTo" => reply_id, "name" => _} = object, options) when is_binary(reply_id) do - with true <- Federator.allowed_incoming_reply_depth?(options[:depth]), + with true <- Federator.allowed_thread_distance?(options[:depth]), {:ok, %{data: %{"type" => "Question"} = _} = _} <- get_obj_helper(reply_id, options) do Map.put(object, "type", "Answer") else @@ -406,8 +407,7 @@ def handle_incoming( with nil <- Activity.get_create_by_object_ap_id(object["id"]), {:ok, %User{} = user} <- User.get_or_fetch_by_ap_id(data["actor"]) do - options = Keyword.put(options, :depth, (options[:depth] || 0) + 1) - object = fix_object(data["object"], options) + object = fix_object(object, options) params = %{ to: data["to"], @@ -424,7 +424,20 @@ def handle_incoming( ]) } - ActivityPub.create(params) + with {:ok, created_activity} <- ActivityPub.create(params) do + reply_depth = (options[:depth] || 0) + 1 + + if Federator.allowed_thread_distance?(reply_depth) do + for reply_id <- replies(object) do + Pleroma.Workers.RemoteFetcherWorker.enqueue("fetch_remote", %{ + "id" => reply_id, + "depth" => reply_depth + }) + end + end + + {:ok, created_activity} + end else %Activity{} = activity -> {:ok, activity} _e -> :error @@ -442,7 +455,8 @@ def handle_incoming( |> fix_addressing with {:ok, %User{} = user} <- User.get_or_fetch_by_ap_id(data["actor"]) do - options = Keyword.put(options, :depth, (options[:depth] || 0) + 1) + reply_depth = (options[:depth] || 0) + 1 + options = Keyword.put(options, :depth, reply_depth) object = fix_object(object, options) params = %{ @@ -903,6 +917,50 @@ def set_reply_to_uri(%{"inReplyTo" => in_reply_to} = object) when is_binary(in_r def set_reply_to_uri(obj), do: obj + @doc """ + Serialized Mastodon-compatible `replies` collection containing _self-replies_. + Based on Mastodon's ActivityPub::NoteSerializer#replies. + """ + def set_replies(obj_data) do + replies_uris = + with limit when limit > 0 <- + Pleroma.Config.get([:activitypub, :note_replies_output_limit], 0), + %Object{} = object <- Object.get_cached_by_ap_id(obj_data["id"]) do + object + |> Object.self_replies() + |> select([o], fragment("?->>'id'", o.data)) + |> limit(^limit) + |> Repo.all() + else + _ -> [] + end + + set_replies(obj_data, replies_uris) + end + + defp set_replies(obj, []) do + obj + end + + defp set_replies(obj, replies_uris) do + replies_collection = %{ + "type" => "Collection", + "items" => replies_uris + } + + Map.merge(obj, %{"replies" => replies_collection}) + end + + def replies(%{"replies" => %{"first" => %{"items" => items}}}) when not is_nil(items) do + items + end + + def replies(%{"replies" => %{"items" => items}}) when not is_nil(items) do + items + end + + def replies(_), do: [] + # Prepares the object of an outgoing create activity. def prepare_object(object) do object @@ -914,6 +972,7 @@ def prepare_object(object) do |> prepare_attachments |> set_conversation |> set_reply_to_uri + |> set_replies |> strip_internal_fields |> strip_internal_tags |> set_type diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 10ce5eee8..50e076ca4 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -45,8 +45,8 @@ def normalize_params(params) do Map.put(params, "actor", get_ap_id(params["actor"])) end - @spec determine_explicit_mentions(map()) :: map() - def determine_explicit_mentions(%{"tag" => tag} = _) when is_list(tag) do + @spec determine_explicit_mentions(map()) :: [any] + def determine_explicit_mentions(%{"tag" => tag}) when is_list(tag) do Enum.flat_map(tag, fn %{"type" => "Mention", "href" => href} -> [href] _ -> [] @@ -427,7 +427,7 @@ defp fetch_likes(object) do @doc """ Updates a follow activity's state (for locked accounts). """ - @spec update_follow_state_for_all(Activity.t(), String.t()) :: {:ok, Activity} | {:error, any()} + @spec update_follow_state_for_all(Activity.t(), String.t()) :: {:ok, Activity | nil} def update_follow_state_for_all( %Activity{data: %{"actor" => actor, "object" => object}} = activity, state diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex index 67222ebae..8804343b9 100644 --- a/lib/pleroma/web/admin_api/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/admin_api_controller.ex @@ -13,6 +13,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do alias Pleroma.ModerationLog alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.ReportNote + alias Pleroma.Stats alias Pleroma.User alias Pleroma.UserInviteToken alias Pleroma.Web.ActivityPub.ActivityPub @@ -98,7 +99,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do plug( OAuthScopesPlug, %{scopes: ["read"], admin: true} - when action in [:config_show, :list_log] + when action in [:config_show, :list_log, :stats] ) plug( @@ -243,13 +244,15 @@ def user_show(conn, %{"nickname" => nickname}) do end def list_instance_statuses(conn, %{"instance" => instance} = params) do + with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true {page, page_size} = page_params(params) activities = - ActivityPub.fetch_instance_activities(%{ + ActivityPub.fetch_statuses(nil, %{ "instance" => instance, "limit" => page_size, - "offset" => (page - 1) * page_size + "offset" => (page - 1) * page_size, + "exclude_reblogs" => !with_reblogs && "true" }) conn @@ -258,6 +261,7 @@ def list_instance_statuses(conn, %{"instance" => instance} = params) do end def list_user_statuses(conn, %{"nickname" => nickname} = params) do + with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true godmode = params["godmode"] == "true" || params["godmode"] == true with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do @@ -266,7 +270,8 @@ def list_user_statuses(conn, %{"nickname" => nickname} = params) do activities = ActivityPub.fetch_user_activities(user, nil, %{ "limit" => page_size, - "godmode" => godmode + "godmode" => godmode, + "exclude_reblogs" => !with_reblogs && "true" }) conn @@ -740,6 +745,24 @@ def report_notes_delete(%{assigns: %{user: user}} = conn, %{ end end + def list_statuses(%{assigns: %{user: admin}} = conn, params) do + godmode = params["godmode"] == "true" || params["godmode"] == true + local_only = params["local_only"] == "true" || params["local_only"] == true + {page, page_size} = page_params(params) + + activities = + ActivityPub.fetch_statuses(admin, %{ + "godmode" => godmode, + "local_only" => local_only, + "limit" => page_size, + "offset" => (page - 1) * page_size + }) + + conn + |> put_view(Pleroma.Web.AdminAPI.StatusView) + |> render("index.json", %{activities: activities, as: :activity}) + end + def status_update(%{assigns: %{user: admin}} = conn, %{"id" => id} = params) do with {:ok, activity} <- CommonAPI.update_activity_scope(id, params) do {:ok, sensitive} = Ecto.Type.cast(:boolean, params["sensitive"]) @@ -953,6 +976,13 @@ def resend_confirmation_email(%{assigns: %{user: admin}} = conn, %{"nicknames" = conn |> json("") end + def stats(conn, _) do + count = Stats.get_status_visibility_count() + + conn + |> json(%{"status_visibility" => count}) + end + def errors(conn, {:error, :not_found}) do conn |> put_status(:not_found) diff --git a/lib/pleroma/web/admin_api/search.ex b/lib/pleroma/web/admin_api/search.ex index ed919833e..778cf4c36 100644 --- a/lib/pleroma/web/admin_api/search.ex +++ b/lib/pleroma/web/admin_api/search.ex @@ -18,7 +18,11 @@ defmacro not_empty_string(string) do @spec user(map()) :: {:ok, [User.t()], pos_integer()} def user(params \\ %{}) do - query = User.Query.build(params) |> order_by([u], u.nickname) + query = + params + |> Map.drop([:page, :page_size]) + |> User.Query.build() + |> order_by([u], u.nickname) paginated_query = User.Query.paginate(query, params[:page] || 1, params[:page_size] || @page_size) diff --git a/lib/pleroma/web/admin_api/views/status_view.ex b/lib/pleroma/web/admin_api/views/status_view.ex index 6f2b2b09c..8ae8a7afe 100644 --- a/lib/pleroma/web/admin_api/views/status_view.ex +++ b/lib/pleroma/web/admin_api/views/status_view.ex @@ -10,7 +10,7 @@ defmodule Pleroma.Web.AdminAPI.StatusView do alias Pleroma.User def render("index.json", opts) do - render_many(opts.activities, __MODULE__, "show.json", opts) + safe_render_many(opts.activities, __MODULE__, "show.json", opts) end def render("show.json", %{activity: %{data: %{"object" => _object}} = activity} = opts) do diff --git a/lib/pleroma/web/federator/federator.ex b/lib/pleroma/web/federator/federator.ex index f506a7d24..013fb5b70 100644 --- a/lib/pleroma/web/federator/federator.ex +++ b/lib/pleroma/web/federator/federator.ex @@ -15,13 +15,19 @@ defmodule Pleroma.Web.Federator do require Logger - @doc "Addresses [memory leaks on recursive replies fetching](https://git.pleroma.social/pleroma/pleroma/issues/161)" + @doc """ + Returns `true` if the distance to target object does not exceed max configured value. + Serves to prevent fetching of very long threads, especially useful on smaller instances. + Addresses [memory leaks on recursive replies fetching](https://git.pleroma.social/pleroma/pleroma/issues/161). + Applies to fetching of both ancestor (reply-to) and child (reply) objects. + """ # credo:disable-for-previous-line Credo.Check.Readability.MaxLineLength - def allowed_incoming_reply_depth?(depth) do - max_replies_depth = Pleroma.Config.get([:instance, :federation_incoming_replies_max_depth]) + def allowed_thread_distance?(distance) do + max_distance = Pleroma.Config.get([:instance, :federation_incoming_replies_max_depth]) - if max_replies_depth do - (depth || 1) <= max_replies_depth + if max_distance && max_distance >= 0 do + # Default depth is 0 (an object has zero distance from itself in its thread) + (distance || 0) <= max_distance else true end diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex index 333012920..947edd8b7 100644 --- a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex +++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex @@ -92,9 +92,9 @@ def raw_nodeinfo do openRegistrations: Config.get([:instance, :registrations_open]), usage: %{ users: %{ - total: stats.user_count || 0 + total: Map.get(stats, :user_count, 0) }, - localPosts: stats.status_count || 0 + localPosts: Map.get(stats, :status_count, 0) }, metadata: %{ nodeName: Config.get([:instance, :name]), diff --git a/lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex b/lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex index a2f6d2287..03e95e020 100644 --- a/lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex @@ -323,7 +323,7 @@ def delete(conn, %{"name" => name}) do {:ok, _} -> conn |> json("ok") - {:error, _} -> + {:error, _, _} -> conn |> put_status(:internal_server_error) |> json(%{error: "Couldn't delete the pack #{name}"}) diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 9bfe86704..103c638b4 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -192,6 +192,7 @@ defmodule Pleroma.Web.Router do put("/statuses/:id", AdminAPIController, :status_update) delete("/statuses/:id", AdminAPIController, :status_delete) + get("/statuses", AdminAPIController, :list_statuses) get("/config", AdminAPIController, :config_show) post("/config", AdminAPIController, :config_update) @@ -201,6 +202,7 @@ defmodule Pleroma.Web.Router do get("/moderation_log", AdminAPIController, :list_log) post("/reload_emoji", AdminAPIController, :reload_emoji) + get("/stats", AdminAPIController, :stats) end scope "/api/pleroma/emoji", Pleroma.Web.PleromaAPI do diff --git a/lib/pleroma/workers/remote_fetcher_worker.ex b/lib/pleroma/workers/remote_fetcher_worker.ex new file mode 100644 index 000000000..e860ca869 --- /dev/null +++ b/lib/pleroma/workers/remote_fetcher_worker.ex @@ -0,0 +1,20 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Workers.RemoteFetcherWorker do + alias Pleroma.Object.Fetcher + + use Pleroma.Workers.WorkerHelper, queue: "remote_fetcher" + + @impl Oban.Worker + def perform( + %{ + "op" => "fetch_remote", + "id" => id + } = args, + _job + ) do + {:ok, _object} = Fetcher.fetch_object_from_id(id, depth: args["depth"]) + end +end diff --git a/priv/repo/migrations/20200109123126_add_counter_cache_table.exs b/priv/repo/migrations/20200109123126_add_counter_cache_table.exs new file mode 100644 index 000000000..df9e21193 --- /dev/null +++ b/priv/repo/migrations/20200109123126_add_counter_cache_table.exs @@ -0,0 +1,55 @@ +defmodule Pleroma.Repo.Migrations.AddCounterCacheTable do + use Ecto.Migration + + def up do + create_if_not_exists table(:counter_cache) do + add(:name, :string, null: false) + add(:count, :bigint, null: false, default: 0) + end + + create_if_not_exists(unique_index(:counter_cache, [:name])) + + """ + CREATE OR REPLACE FUNCTION update_status_visibility_counter_cache() + RETURNS TRIGGER AS + $$ + DECLARE + BEGIN + IF TG_OP = 'INSERT' THEN + IF NEW.data->>'type' = 'Create' THEN + EXECUTE 'INSERT INTO counter_cache (name, count) VALUES (''status_visibility_' || activity_visibility(NEW.actor, NEW.recipients, NEW.data) || ''', 1) ON CONFLICT (name) DO UPDATE SET count = counter_cache.count + 1'; + END IF; + RETURN NEW; + ELSIF TG_OP = 'UPDATE' THEN + IF (NEW.data->>'type' = 'Create') and (OLD.data->>'type' = 'Create') and activity_visibility(NEW.actor, NEW.recipients, NEW.data) != activity_visibility(OLD.actor, OLD.recipients, OLD.data) THEN + EXECUTE 'INSERT INTO counter_cache (name, count) VALUES (''status_visibility_' || activity_visibility(NEW.actor, NEW.recipients, NEW.data) || ''', 1) ON CONFLICT (name) DO UPDATE SET count = counter_cache.count + 1'; + EXECUTE 'update counter_cache SET count = counter_cache.count - 1 where count > 0 and name = ''status_visibility_' || activity_visibility(OLD.actor, OLD.recipients, OLD.data) || ''';'; + END IF; + RETURN NEW; + ELSIF TG_OP = 'DELETE' THEN + IF OLD.data->>'type' = 'Create' THEN + EXECUTE 'update counter_cache SET count = counter_cache.count - 1 where count > 0 and name = ''status_visibility_' || activity_visibility(OLD.actor, OLD.recipients, OLD.data) || ''';'; + END IF; + RETURN OLD; + END IF; + END; + $$ + LANGUAGE 'plpgsql'; + """ + |> execute() + + """ + CREATE TRIGGER status_visibility_counter_cache_trigger BEFORE INSERT OR UPDATE of recipients, data OR DELETE ON activities + FOR EACH ROW + EXECUTE PROCEDURE update_status_visibility_counter_cache(); + """ + |> execute() + end + + def down do + execute("drop trigger if exists status_visibility_counter_cache_trigger on activities") + execute("drop function if exists update_status_visibility_counter_cache()") + drop_if_exists(unique_index(:counter_cache, [:name])) + drop_if_exists(table(:counter_cache)) + end +end diff --git a/priv/static/adminfe/chunk-03b0.49362218.css b/priv/static/adminfe/chunk-03b0.49362218.css new file mode 100644 index 000000000..e43c776aa Binary files /dev/null and b/priv/static/adminfe/chunk-03b0.49362218.css differ diff --git a/priv/static/adminfe/chunk-06de.3abb5de7.css b/priv/static/adminfe/chunk-06de.3abb5de7.css deleted file mode 100644 index 4fb60b648..000000000 Binary files a/priv/static/adminfe/chunk-06de.3abb5de7.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-15fa.86ad6a40.css b/priv/static/adminfe/chunk-15fa.dc3643e6.css similarity index 100% rename from priv/static/adminfe/chunk-15fa.86ad6a40.css rename to priv/static/adminfe/chunk-15fa.dc3643e6.css diff --git a/priv/static/adminfe/chunk-17a5.edcdbe30.css b/priv/static/adminfe/chunk-17a5.edcdbe30.css new file mode 100644 index 000000000..0b2a3f669 Binary files /dev/null and b/priv/static/adminfe/chunk-17a5.edcdbe30.css differ diff --git a/priv/static/adminfe/chunk-20e0.ee636d82.css b/priv/static/adminfe/chunk-20e0.ee636d82.css deleted file mode 100644 index 567079fed..000000000 Binary files a/priv/static/adminfe/chunk-20e0.ee636d82.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-293a.a8b5ee5b.css b/priv/static/adminfe/chunk-293a.a8b5ee5b.css new file mode 100644 index 000000000..924633a80 Binary files /dev/null and b/priv/static/adminfe/chunk-293a.a8b5ee5b.css differ diff --git a/priv/static/adminfe/chunk-2b8b.0f1ee211.css b/priv/static/adminfe/chunk-2b8b.0f1ee211.css new file mode 100644 index 000000000..2857a9d6e Binary files /dev/null and b/priv/static/adminfe/chunk-2b8b.0f1ee211.css differ diff --git a/priv/static/adminfe/chunk-453a.bbab87da.css b/priv/static/adminfe/chunk-453a.bbab87da.css new file mode 100644 index 000000000..d6cc7d182 Binary files /dev/null and b/priv/static/adminfe/chunk-453a.bbab87da.css differ diff --git a/priv/static/adminfe/chunk-46cf.6dd5bbb7.css b/priv/static/adminfe/chunk-46cf.6dd5bbb7.css new file mode 100644 index 000000000..aa7160528 Binary files /dev/null and b/priv/static/adminfe/chunk-46cf.6dd5bbb7.css differ diff --git a/priv/static/adminfe/chunk-48a4.1bb1db91.css b/priv/static/adminfe/chunk-48a4.1bb1db91.css deleted file mode 100644 index 48784b9d2..000000000 Binary files a/priv/static/adminfe/chunk-48a4.1bb1db91.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-51b0.55057987.css b/priv/static/adminfe/chunk-4e46.ad5e9ff3.css similarity index 100% rename from priv/static/adminfe/chunk-51b0.55057987.css rename to priv/static/adminfe/chunk-4e46.ad5e9ff3.css diff --git a/priv/static/adminfe/chunk-560d.802cfba1.css b/priv/static/adminfe/chunk-560d.802cfba1.css new file mode 100644 index 000000000..a74b42d14 Binary files /dev/null and b/priv/static/adminfe/chunk-560d.802cfba1.css differ diff --git a/priv/static/adminfe/chunk-645e.8bb40e00.css b/priv/static/adminfe/chunk-645e.8bb40e00.css deleted file mode 100644 index 0591e4930..000000000 Binary files a/priv/static/adminfe/chunk-645e.8bb40e00.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-6aa3.fb02ac69.css b/priv/static/adminfe/chunk-6dd6.85f319f7.css similarity index 100% rename from priv/static/adminfe/chunk-6aa3.fb02ac69.css rename to priv/static/adminfe/chunk-6dd6.85f319f7.css diff --git a/priv/static/adminfe/chunk-7f8e.f03bd164.css b/priv/static/adminfe/chunk-7f8e.f03bd164.css deleted file mode 100644 index 6cd674a28..000000000 Binary files a/priv/static/adminfe/chunk-7f8e.f03bd164.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-b4ba.e55f897a.css b/priv/static/adminfe/chunk-b4ba.e55f897a.css deleted file mode 100644 index dadc5cbda..000000000 Binary files a/priv/static/adminfe/chunk-b4ba.e55f897a.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-bb29.61e9e8f2.css b/priv/static/adminfe/chunk-bb29.61e9e8f2.css deleted file mode 100644 index bbab1c2ac..000000000 Binary files a/priv/static/adminfe/chunk-bb29.61e9e8f2.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-cf58.6bdb954d.css b/priv/static/adminfe/chunk-cf58.80435fa1.css similarity index 55% rename from priv/static/adminfe/chunk-cf58.6bdb954d.css rename to priv/static/adminfe/chunk-cf58.80435fa1.css index 69fc0072a..8b0f21153 100644 Binary files a/priv/static/adminfe/chunk-cf58.6bdb954d.css and b/priv/static/adminfe/chunk-cf58.80435fa1.css differ diff --git a/priv/static/adminfe/index.html b/priv/static/adminfe/index.html index 0b08c3290..b0bdb162d 100644 --- a/priv/static/adminfe/index.html +++ b/priv/static/adminfe/index.html @@ -1 +1 @@ -Admin FE
\ No newline at end of file +Admin FE
\ No newline at end of file diff --git a/priv/static/adminfe/static/js/app.30262183.js b/priv/static/adminfe/static/js/app.30262183.js new file mode 100644 index 000000000..c872d448f Binary files /dev/null and b/priv/static/adminfe/static/js/app.30262183.js differ diff --git a/priv/static/adminfe/static/js/app.30262183.js.map b/priv/static/adminfe/static/js/app.30262183.js.map new file mode 100644 index 000000000..3711b8a98 Binary files /dev/null and b/priv/static/adminfe/static/js/app.30262183.js.map differ diff --git a/priv/static/adminfe/static/js/app.5f0094e3.js b/priv/static/adminfe/static/js/app.5f0094e3.js deleted file mode 100644 index e65b2f09c..000000000 Binary files a/priv/static/adminfe/static/js/app.5f0094e3.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/app.5f0094e3.js.map b/priv/static/adminfe/static/js/app.5f0094e3.js.map deleted file mode 100644 index edb94a554..000000000 Binary files a/priv/static/adminfe/static/js/app.5f0094e3.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-03b0.7a203856.js b/priv/static/adminfe/static/js/chunk-03b0.7a203856.js new file mode 100644 index 000000000..43ca0e4e6 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-03b0.7a203856.js differ diff --git a/priv/static/adminfe/static/js/chunk-03b0.7a203856.js.map b/priv/static/adminfe/static/js/chunk-03b0.7a203856.js.map new file mode 100644 index 000000000..697a106ac Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-03b0.7a203856.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-06de.ff4586ab.js b/priv/static/adminfe/static/js/chunk-06de.ff4586ab.js deleted file mode 100644 index c989bed18..000000000 Binary files a/priv/static/adminfe/static/js/chunk-06de.ff4586ab.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-06de.ff4586ab.js.map b/priv/static/adminfe/static/js/chunk-06de.ff4586ab.js.map deleted file mode 100644 index 5652f3192..000000000 Binary files a/priv/static/adminfe/static/js/chunk-06de.ff4586ab.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-15fa.99004e49.js b/priv/static/adminfe/static/js/chunk-15fa.15303f3a.js similarity index 99% rename from priv/static/adminfe/static/js/chunk-15fa.99004e49.js rename to priv/static/adminfe/static/js/chunk-15fa.15303f3a.js index 5ab46f8b9..7d3e0c56e 100644 Binary files a/priv/static/adminfe/static/js/chunk-15fa.99004e49.js and b/priv/static/adminfe/static/js/chunk-15fa.15303f3a.js differ diff --git a/priv/static/adminfe/static/js/chunk-15fa.99004e49.js.map b/priv/static/adminfe/static/js/chunk-15fa.15303f3a.js.map similarity index 99% rename from priv/static/adminfe/static/js/chunk-15fa.99004e49.js.map rename to priv/static/adminfe/static/js/chunk-15fa.15303f3a.js.map index f4b92260a..f08d1dbf9 100644 Binary files a/priv/static/adminfe/static/js/chunk-15fa.99004e49.js.map and b/priv/static/adminfe/static/js/chunk-15fa.15303f3a.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-17a5.13b13757.js b/priv/static/adminfe/static/js/chunk-17a5.13b13757.js new file mode 100644 index 000000000..80e7a8ac7 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-17a5.13b13757.js differ diff --git a/priv/static/adminfe/static/js/chunk-17a5.13b13757.js.map b/priv/static/adminfe/static/js/chunk-17a5.13b13757.js.map new file mode 100644 index 000000000..7da1a0077 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-17a5.13b13757.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-20e0.dc3e8a45.js b/priv/static/adminfe/static/js/chunk-20e0.dc3e8a45.js deleted file mode 100644 index 5fa5107f4..000000000 Binary files a/priv/static/adminfe/static/js/chunk-20e0.dc3e8a45.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-20e0.dc3e8a45.js.map b/priv/static/adminfe/static/js/chunk-20e0.dc3e8a45.js.map deleted file mode 100644 index 2186ce225..000000000 Binary files a/priv/static/adminfe/static/js/chunk-20e0.dc3e8a45.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-293a.a728de01.js b/priv/static/adminfe/static/js/chunk-293a.a728de01.js new file mode 100644 index 000000000..c856e21eb Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-293a.a728de01.js differ diff --git a/priv/static/adminfe/static/js/chunk-293a.a728de01.js.map b/priv/static/adminfe/static/js/chunk-293a.a728de01.js.map new file mode 100644 index 000000000..03f61abcb Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-293a.a728de01.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-2b8b.e3daf966.js b/priv/static/adminfe/static/js/chunk-2b8b.e3daf966.js new file mode 100644 index 000000000..4b100db60 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-2b8b.e3daf966.js differ diff --git a/priv/static/adminfe/static/js/chunk-2b8b.e3daf966.js.map b/priv/static/adminfe/static/js/chunk-2b8b.e3daf966.js.map new file mode 100644 index 000000000..a7282eaf4 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-2b8b.e3daf966.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-48a4.e3d2c4b6.js b/priv/static/adminfe/static/js/chunk-453a.2fcd7192.js similarity index 89% rename from priv/static/adminfe/static/js/chunk-48a4.e3d2c4b6.js rename to priv/static/adminfe/static/js/chunk-453a.2fcd7192.js index 596384cab..b0ee1b6b0 100644 Binary files a/priv/static/adminfe/static/js/chunk-48a4.e3d2c4b6.js and b/priv/static/adminfe/static/js/chunk-453a.2fcd7192.js differ diff --git a/priv/static/adminfe/static/js/chunk-453a.2fcd7192.js.map b/priv/static/adminfe/static/js/chunk-453a.2fcd7192.js.map new file mode 100644 index 000000000..b43d2f571 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-453a.2fcd7192.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-46cf.104380a9.js b/priv/static/adminfe/static/js/chunk-46cf.104380a9.js new file mode 100644 index 000000000..9e1e1520b Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-46cf.104380a9.js differ diff --git a/priv/static/adminfe/static/js/chunk-46cf.104380a9.js.map b/priv/static/adminfe/static/js/chunk-46cf.104380a9.js.map new file mode 100644 index 000000000..b9357ca8f Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-46cf.104380a9.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-48a4.e3d2c4b6.js.map b/priv/static/adminfe/static/js/chunk-48a4.e3d2c4b6.js.map deleted file mode 100644 index f3d7fd870..000000000 Binary files a/priv/static/adminfe/static/js/chunk-48a4.e3d2c4b6.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-51b0.7d1554b1.js b/priv/static/adminfe/static/js/chunk-4e46.d257e435.js similarity index 85% rename from priv/static/adminfe/static/js/chunk-51b0.7d1554b1.js rename to priv/static/adminfe/static/js/chunk-4e46.d257e435.js index a770215ae..39c5dcc4e 100644 Binary files a/priv/static/adminfe/static/js/chunk-51b0.7d1554b1.js and b/priv/static/adminfe/static/js/chunk-4e46.d257e435.js differ diff --git a/priv/static/adminfe/static/js/chunk-51b0.7d1554b1.js.map b/priv/static/adminfe/static/js/chunk-4e46.d257e435.js.map similarity index 98% rename from priv/static/adminfe/static/js/chunk-51b0.7d1554b1.js.map rename to priv/static/adminfe/static/js/chunk-4e46.d257e435.js.map index 9b8014486..75d3554ac 100644 Binary files a/priv/static/adminfe/static/js/chunk-51b0.7d1554b1.js.map and b/priv/static/adminfe/static/js/chunk-4e46.d257e435.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-560d.a8bb8682.js b/priv/static/adminfe/static/js/chunk-560d.a8bb8682.js new file mode 100644 index 000000000..0b03305e9 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-560d.a8bb8682.js differ diff --git a/priv/static/adminfe/static/js/chunk-560d.a8bb8682.js.map b/priv/static/adminfe/static/js/chunk-560d.a8bb8682.js.map new file mode 100644 index 000000000..bfab1ade9 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-560d.a8bb8682.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-645e.ad5c2109.js b/priv/static/adminfe/static/js/chunk-645e.ad5c2109.js deleted file mode 100644 index 1ffacd027..000000000 Binary files a/priv/static/adminfe/static/js/chunk-645e.ad5c2109.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-645e.ad5c2109.js.map b/priv/static/adminfe/static/js/chunk-645e.ad5c2109.js.map deleted file mode 100644 index 47f9e1213..000000000 Binary files a/priv/static/adminfe/static/js/chunk-645e.ad5c2109.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-6aa3.95b2c0b4.js b/priv/static/adminfe/static/js/chunk-6dd6.6c139a9c.js similarity index 97% rename from priv/static/adminfe/static/js/chunk-6aa3.95b2c0b4.js rename to priv/static/adminfe/static/js/chunk-6dd6.6c139a9c.js index 1d44bee16..670016168 100644 Binary files a/priv/static/adminfe/static/js/chunk-6aa3.95b2c0b4.js and b/priv/static/adminfe/static/js/chunk-6dd6.6c139a9c.js differ diff --git a/priv/static/adminfe/static/js/chunk-6aa3.95b2c0b4.js.map b/priv/static/adminfe/static/js/chunk-6dd6.6c139a9c.js.map similarity index 99% rename from priv/static/adminfe/static/js/chunk-6aa3.95b2c0b4.js.map rename to priv/static/adminfe/static/js/chunk-6dd6.6c139a9c.js.map index aa3fa8ee1..b1438722c 100644 Binary files a/priv/static/adminfe/static/js/chunk-6aa3.95b2c0b4.js.map and b/priv/static/adminfe/static/js/chunk-6dd6.6c139a9c.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-7f8e.a4876ede.js b/priv/static/adminfe/static/js/chunk-7f8e.a4876ede.js deleted file mode 100644 index e3025b00f..000000000 Binary files a/priv/static/adminfe/static/js/chunk-7f8e.a4876ede.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-7f8e.a4876ede.js.map b/priv/static/adminfe/static/js/chunk-7f8e.a4876ede.js.map deleted file mode 100644 index c34b1dc46..000000000 Binary files a/priv/static/adminfe/static/js/chunk-7f8e.a4876ede.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-b4ba.f717f3b2.js b/priv/static/adminfe/static/js/chunk-b4ba.f717f3b2.js deleted file mode 100644 index b748c0739..000000000 Binary files a/priv/static/adminfe/static/js/chunk-b4ba.f717f3b2.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-b4ba.f717f3b2.js.map b/priv/static/adminfe/static/js/chunk-b4ba.f717f3b2.js.map deleted file mode 100644 index 2871c747d..000000000 Binary files a/priv/static/adminfe/static/js/chunk-b4ba.f717f3b2.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-bb29.6468c7fe.js b/priv/static/adminfe/static/js/chunk-bb29.6468c7fe.js deleted file mode 100644 index 866a07448..000000000 Binary files a/priv/static/adminfe/static/js/chunk-bb29.6468c7fe.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-bb29.6468c7fe.js.map b/priv/static/adminfe/static/js/chunk-bb29.6468c7fe.js.map deleted file mode 100644 index 27274eaec..000000000 Binary files a/priv/static/adminfe/static/js/chunk-bb29.6468c7fe.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-cf58.438233c4.js.map b/priv/static/adminfe/static/js/chunk-cf58.438233c4.js.map deleted file mode 100644 index dd70f756c..000000000 Binary files a/priv/static/adminfe/static/js/chunk-cf58.438233c4.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-cf58.438233c4.js b/priv/static/adminfe/static/js/chunk-cf58.e52693b3.js similarity index 99% rename from priv/static/adminfe/static/js/chunk-cf58.438233c4.js rename to priv/static/adminfe/static/js/chunk-cf58.e52693b3.js index 5c22b4ba4..b74c20373 100644 Binary files a/priv/static/adminfe/static/js/chunk-cf58.438233c4.js and b/priv/static/adminfe/static/js/chunk-cf58.e52693b3.js differ diff --git a/priv/static/adminfe/static/js/chunk-cf58.e52693b3.js.map b/priv/static/adminfe/static/js/chunk-cf58.e52693b3.js.map new file mode 100644 index 000000000..0f3f15299 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-cf58.e52693b3.js.map differ diff --git a/priv/static/adminfe/static/js/runtime.dfdeb6eb.js b/priv/static/adminfe/static/js/runtime.ae93ea9f.js similarity index 54% rename from priv/static/adminfe/static/js/runtime.dfdeb6eb.js rename to priv/static/adminfe/static/js/runtime.ae93ea9f.js index 418b2c4de..ebda2acde 100644 Binary files a/priv/static/adminfe/static/js/runtime.dfdeb6eb.js and b/priv/static/adminfe/static/js/runtime.ae93ea9f.js differ diff --git a/priv/static/adminfe/static/js/runtime.dfdeb6eb.js.map b/priv/static/adminfe/static/js/runtime.ae93ea9f.js.map similarity index 89% rename from priv/static/adminfe/static/js/runtime.dfdeb6eb.js.map rename to priv/static/adminfe/static/js/runtime.ae93ea9f.js.map index 6728ad670..6392c981a 100644 Binary files a/priv/static/adminfe/static/js/runtime.dfdeb6eb.js.map and b/priv/static/adminfe/static/js/runtime.ae93ea9f.js.map differ diff --git a/priv/static/index.html b/priv/static/index.html index 6e1f751ce..557ee5849 100644 --- a/priv/static/index.html +++ b/priv/static/index.html @@ -1 +1 @@ -Pleroma
\ No newline at end of file +Pleroma
\ No newline at end of file diff --git a/priv/static/static/css/app.ae04505b31bb0ee2765e.css b/priv/static/static/css/app.1055039ce3f2fe4dd110.css similarity index 90% rename from priv/static/static/css/app.ae04505b31bb0ee2765e.css rename to priv/static/static/css/app.1055039ce3f2fe4dd110.css index 05e3f2087..1867ca81a 100644 Binary files a/priv/static/static/css/app.ae04505b31bb0ee2765e.css and b/priv/static/static/css/app.1055039ce3f2fe4dd110.css differ diff --git a/priv/static/static/css/app.1055039ce3f2fe4dd110.css.map b/priv/static/static/css/app.1055039ce3f2fe4dd110.css.map new file mode 100644 index 000000000..861ee8313 --- /dev/null +++ b/priv/static/static/css/app.1055039ce3f2fe4dd110.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/hocs/with_load_more/with_load_more.scss","webpack:///./src/components/tab_switcher/tab_switcher.scss","webpack:///./src/hocs/with_subscription/with_subscription.scss"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA,C","file":"static/css/app.1055039ce3f2fe4dd110.css","sourcesContent":[".with-load-more-footer {\n padding: 10px;\n text-align: center;\n border-top: 1px solid;\n border-top-color: #222;\n border-top-color: var(--border, #222);\n}\n.with-load-more-footer .error {\n font-size: 14px;\n}",".tab-switcher {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-direction: column;\n flex-direction: column;\n}\n.tab-switcher .contents {\n -ms-flex: 1 0 auto;\n flex: 1 0 auto;\n min-height: 0px;\n}\n.tab-switcher .contents .hidden {\n display: none;\n}\n.tab-switcher .contents.scrollable-tabs {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n overflow-y: auto;\n}\n.tab-switcher .tabs {\n display: -ms-flexbox;\n display: flex;\n position: relative;\n width: 100%;\n overflow-y: hidden;\n overflow-x: auto;\n padding-top: 5px;\n box-sizing: border-box;\n}\n.tab-switcher .tabs::after, .tab-switcher .tabs::before {\n display: block;\n content: \"\";\n -ms-flex: 1 1 auto;\n flex: 1 1 auto;\n border-bottom: 1px solid;\n border-bottom-color: #222;\n border-bottom-color: var(--border, #222);\n}\n.tab-switcher .tabs .tab-wrapper {\n height: 28px;\n position: relative;\n display: -ms-flexbox;\n display: flex;\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n}\n.tab-switcher .tabs .tab-wrapper .tab {\n width: 100%;\n min-width: 1px;\n position: relative;\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n padding: 6px 1em;\n padding-bottom: 99px;\n margin-bottom: -93px;\n white-space: nowrap;\n color: #b9b9ba;\n color: var(--tabText, #b9b9ba);\n background-color: #182230;\n background-color: var(--tab, #182230);\n}\n.tab-switcher .tabs .tab-wrapper .tab:not(.active) {\n z-index: 4;\n}\n.tab-switcher .tabs .tab-wrapper .tab:not(.active):hover {\n z-index: 6;\n}\n.tab-switcher .tabs .tab-wrapper .tab.active {\n background: transparent;\n z-index: 5;\n color: #b9b9ba;\n color: var(--tabActiveText, #b9b9ba);\n}\n.tab-switcher .tabs .tab-wrapper .tab img {\n max-height: 26px;\n vertical-align: top;\n margin-top: -5px;\n}\n.tab-switcher .tabs .tab-wrapper:not(.active)::after {\n content: \"\";\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 7;\n border-bottom: 1px solid;\n border-bottom-color: #222;\n border-bottom-color: var(--border, #222);\n}",".with-subscription-loading {\n padding: 10px;\n text-align: center;\n}\n.with-subscription-loading .error {\n font-size: 14px;\n}"],"sourceRoot":""} \ No newline at end of file diff --git a/priv/static/static/css/app.ae04505b31bb0ee2765e.css.map b/priv/static/static/css/app.ae04505b31bb0ee2765e.css.map deleted file mode 100644 index 72f33316e..000000000 --- a/priv/static/static/css/app.ae04505b31bb0ee2765e.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///./src/hocs/with_load_more/with_load_more.scss","webpack:///./src/components/tab_switcher/tab_switcher.scss","webpack:///./src/hocs/with_subscription/with_subscription.scss"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;AClFA;AACA;AACA;AACA;AACA;AACA;AACA,C","file":"static/css/app.ae04505b31bb0ee2765e.css","sourcesContent":[".with-load-more-footer {\n padding: 10px;\n text-align: center;\n border-top: 1px solid;\n border-top-color: #222;\n border-top-color: var(--border, #222);\n}\n.with-load-more-footer .error {\n font-size: 14px;\n}",".tab-switcher {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-direction: column;\n flex-direction: column;\n}\n.tab-switcher .contents {\n -ms-flex: 1 0 auto;\n flex: 1 0 auto;\n min-height: 0px;\n}\n.tab-switcher .contents .hidden {\n display: none;\n}\n.tab-switcher .contents.scrollable-tabs {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n overflow-y: auto;\n}\n.tab-switcher .tabs {\n display: -ms-flexbox;\n display: flex;\n position: relative;\n width: 100%;\n overflow-y: hidden;\n overflow-x: auto;\n padding-top: 5px;\n box-sizing: border-box;\n}\n.tab-switcher .tabs::after, .tab-switcher .tabs::before {\n display: block;\n content: \"\";\n -ms-flex: 1 1 auto;\n flex: 1 1 auto;\n border-bottom: 1px solid;\n border-bottom-color: #222;\n border-bottom-color: var(--border, #222);\n}\n.tab-switcher .tabs .tab-wrapper {\n height: 28px;\n position: relative;\n display: -ms-flexbox;\n display: flex;\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n}\n.tab-switcher .tabs .tab-wrapper .tab {\n width: 100%;\n min-width: 1px;\n position: relative;\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n padding: 6px 1em;\n padding-bottom: 99px;\n margin-bottom: -93px;\n white-space: nowrap;\n}\n.tab-switcher .tabs .tab-wrapper .tab:not(.active) {\n z-index: 4;\n}\n.tab-switcher .tabs .tab-wrapper .tab:not(.active):hover {\n z-index: 6;\n}\n.tab-switcher .tabs .tab-wrapper .tab.active {\n background: transparent;\n z-index: 5;\n}\n.tab-switcher .tabs .tab-wrapper .tab img {\n max-height: 26px;\n vertical-align: top;\n margin-top: -5px;\n}\n.tab-switcher .tabs .tab-wrapper:not(.active)::after {\n content: \"\";\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 7;\n border-bottom: 1px solid;\n border-bottom-color: #222;\n border-bottom-color: var(--border, #222);\n}",".with-subscription-loading {\n padding: 10px;\n text-align: center;\n}\n.with-subscription-loading .error {\n font-size: 14px;\n}"],"sourceRoot":""} \ No newline at end of file diff --git a/priv/static/static/css/base16-3024.css b/priv/static/static/css/base16-3024.css deleted file mode 100644 index 91859e272..000000000 Binary files a/priv/static/static/css/base16-3024.css and /dev/null differ diff --git a/priv/static/static/css/base16-apathy.css b/priv/static/static/css/base16-apathy.css deleted file mode 100644 index 2e99ba1f0..000000000 Binary files a/priv/static/static/css/base16-apathy.css and /dev/null differ diff --git a/priv/static/static/css/base16-ashes.css b/priv/static/static/css/base16-ashes.css deleted file mode 100644 index d10e1918e..000000000 Binary files a/priv/static/static/css/base16-ashes.css and /dev/null differ diff --git a/priv/static/static/css/base16-atelier-cave.css b/priv/static/static/css/base16-atelier-cave.css deleted file mode 100644 index 5ac17f97e..000000000 Binary files a/priv/static/static/css/base16-atelier-cave.css and /dev/null differ diff --git a/priv/static/static/css/base16-atelier-dune.css b/priv/static/static/css/base16-atelier-dune.css deleted file mode 100644 index cfb2d9a1e..000000000 Binary files a/priv/static/static/css/base16-atelier-dune.css and /dev/null differ diff --git a/priv/static/static/css/base16-atelier-estuary.css b/priv/static/static/css/base16-atelier-estuary.css deleted file mode 100644 index 76d82c754..000000000 Binary files a/priv/static/static/css/base16-atelier-estuary.css and /dev/null differ diff --git a/priv/static/static/css/base16-atelier-forest.css b/priv/static/static/css/base16-atelier-forest.css deleted file mode 100644 index 8108ed8f6..000000000 Binary files a/priv/static/static/css/base16-atelier-forest.css and /dev/null differ diff --git a/priv/static/static/css/base16-atelier-heath.css b/priv/static/static/css/base16-atelier-heath.css deleted file mode 100644 index 8858cb807..000000000 Binary files a/priv/static/static/css/base16-atelier-heath.css and /dev/null differ diff --git a/priv/static/static/css/base16-atelier-lakeside.css b/priv/static/static/css/base16-atelier-lakeside.css deleted file mode 100644 index 77d44c5fa..000000000 Binary files a/priv/static/static/css/base16-atelier-lakeside.css and /dev/null differ diff --git a/priv/static/static/css/base16-atelier-plateau.css b/priv/static/static/css/base16-atelier-plateau.css deleted file mode 100644 index a7445030b..000000000 Binary files a/priv/static/static/css/base16-atelier-plateau.css and /dev/null differ diff --git a/priv/static/static/css/base16-atelier-savanna.css b/priv/static/static/css/base16-atelier-savanna.css deleted file mode 100644 index be728d07d..000000000 Binary files a/priv/static/static/css/base16-atelier-savanna.css and /dev/null differ diff --git a/priv/static/static/css/base16-atelier-seaside.css b/priv/static/static/css/base16-atelier-seaside.css deleted file mode 100644 index 8b3914669..000000000 Binary files a/priv/static/static/css/base16-atelier-seaside.css and /dev/null differ diff --git a/priv/static/static/css/base16-atelier-sulphurpool.css b/priv/static/static/css/base16-atelier-sulphurpool.css deleted file mode 100644 index fb44d6e0f..000000000 Binary files a/priv/static/static/css/base16-atelier-sulphurpool.css and /dev/null differ diff --git a/priv/static/static/css/base16-bespin.css b/priv/static/static/css/base16-bespin.css deleted file mode 100644 index 48a9dcf76..000000000 Binary files a/priv/static/static/css/base16-bespin.css and /dev/null differ diff --git a/priv/static/static/css/base16-brewer.css b/priv/static/static/css/base16-brewer.css deleted file mode 100644 index c88f219b7..000000000 Binary files a/priv/static/static/css/base16-brewer.css and /dev/null differ diff --git a/priv/static/static/css/base16-bright.css b/priv/static/static/css/base16-bright.css deleted file mode 100644 index c2333b8d1..000000000 Binary files a/priv/static/static/css/base16-bright.css and /dev/null differ diff --git a/priv/static/static/css/base16-chalk.css b/priv/static/static/css/base16-chalk.css deleted file mode 100644 index e3cb3c20c..000000000 Binary files a/priv/static/static/css/base16-chalk.css and /dev/null differ diff --git a/priv/static/static/css/base16-codeschool.css b/priv/static/static/css/base16-codeschool.css deleted file mode 100644 index 00194bbfc..000000000 Binary files a/priv/static/static/css/base16-codeschool.css and /dev/null differ diff --git a/priv/static/static/css/base16-darktooth.css b/priv/static/static/css/base16-darktooth.css deleted file mode 100644 index 534487064..000000000 Binary files a/priv/static/static/css/base16-darktooth.css and /dev/null differ diff --git a/priv/static/static/css/base16-default-dark.css b/priv/static/static/css/base16-default-dark.css deleted file mode 100644 index 3cd7e860c..000000000 Binary files a/priv/static/static/css/base16-default-dark.css and /dev/null differ diff --git a/priv/static/static/css/base16-default-light.css b/priv/static/static/css/base16-default-light.css deleted file mode 100644 index 7e660c302..000000000 Binary files a/priv/static/static/css/base16-default-light.css and /dev/null differ diff --git a/priv/static/static/css/base16-eighties.css b/priv/static/static/css/base16-eighties.css deleted file mode 100644 index 8ffcf04d9..000000000 Binary files a/priv/static/static/css/base16-eighties.css and /dev/null differ diff --git a/priv/static/static/css/base16-embers.css b/priv/static/static/css/base16-embers.css deleted file mode 100644 index 74e9b7693..000000000 Binary files a/priv/static/static/css/base16-embers.css and /dev/null differ diff --git a/priv/static/static/css/base16-flat.css b/priv/static/static/css/base16-flat.css deleted file mode 100644 index 72918a5df..000000000 Binary files a/priv/static/static/css/base16-flat.css and /dev/null differ diff --git a/priv/static/static/css/base16-github.css b/priv/static/static/css/base16-github.css deleted file mode 100644 index 080ed34ce..000000000 Binary files a/priv/static/static/css/base16-github.css and /dev/null differ diff --git a/priv/static/static/css/base16-google-dark.css b/priv/static/static/css/base16-google-dark.css deleted file mode 100644 index 988eac51d..000000000 Binary files a/priv/static/static/css/base16-google-dark.css and /dev/null differ diff --git a/priv/static/static/css/base16-google-light.css b/priv/static/static/css/base16-google-light.css deleted file mode 100644 index 2ee2a6069..000000000 Binary files a/priv/static/static/css/base16-google-light.css and /dev/null differ diff --git a/priv/static/static/css/base16-grayscale-dark.css b/priv/static/static/css/base16-grayscale-dark.css deleted file mode 100644 index dc0dd03a0..000000000 Binary files a/priv/static/static/css/base16-grayscale-dark.css and /dev/null differ diff --git a/priv/static/static/css/base16-grayscale-light.css b/priv/static/static/css/base16-grayscale-light.css deleted file mode 100644 index f9fd213ae..000000000 Binary files a/priv/static/static/css/base16-grayscale-light.css and /dev/null differ diff --git a/priv/static/static/css/base16-green-screen.css b/priv/static/static/css/base16-green-screen.css deleted file mode 100644 index 205efeaec..000000000 Binary files a/priv/static/static/css/base16-green-screen.css and /dev/null differ diff --git a/priv/static/static/css/base16-harmonic16-dark.css b/priv/static/static/css/base16-harmonic16-dark.css deleted file mode 100644 index 0c2c7ce42..000000000 Binary files a/priv/static/static/css/base16-harmonic16-dark.css and /dev/null differ diff --git a/priv/static/static/css/base16-harmonic16-light.css b/priv/static/static/css/base16-harmonic16-light.css deleted file mode 100644 index 37bb7679a..000000000 Binary files a/priv/static/static/css/base16-harmonic16-light.css and /dev/null differ diff --git a/priv/static/static/css/base16-hopscotch.css b/priv/static/static/css/base16-hopscotch.css deleted file mode 100644 index f2ad232c5..000000000 Binary files a/priv/static/static/css/base16-hopscotch.css and /dev/null differ diff --git a/priv/static/static/css/base16-ir-black.css b/priv/static/static/css/base16-ir-black.css deleted file mode 100644 index 8d14ab9b8..000000000 Binary files a/priv/static/static/css/base16-ir-black.css and /dev/null differ diff --git a/priv/static/static/css/base16-isotope.css b/priv/static/static/css/base16-isotope.css deleted file mode 100644 index f7a4a0b4b..000000000 Binary files a/priv/static/static/css/base16-isotope.css and /dev/null differ diff --git a/priv/static/static/css/base16-london-tube.css b/priv/static/static/css/base16-london-tube.css deleted file mode 100644 index 0537d1ad5..000000000 Binary files a/priv/static/static/css/base16-london-tube.css and /dev/null differ diff --git a/priv/static/static/css/base16-macintosh.css b/priv/static/static/css/base16-macintosh.css deleted file mode 100644 index d5969fec2..000000000 Binary files a/priv/static/static/css/base16-macintosh.css and /dev/null differ diff --git a/priv/static/static/css/base16-marrakesh.css b/priv/static/static/css/base16-marrakesh.css deleted file mode 100644 index 91f0471fc..000000000 Binary files a/priv/static/static/css/base16-marrakesh.css and /dev/null differ diff --git a/priv/static/static/css/base16-materia.css b/priv/static/static/css/base16-materia.css deleted file mode 100644 index 41d935dd1..000000000 Binary files a/priv/static/static/css/base16-materia.css and /dev/null differ diff --git a/priv/static/static/css/base16-mexico-light.css b/priv/static/static/css/base16-mexico-light.css deleted file mode 100644 index 1916c67bc..000000000 Binary files a/priv/static/static/css/base16-mexico-light.css and /dev/null differ diff --git a/priv/static/static/css/base16-mocha.css b/priv/static/static/css/base16-mocha.css deleted file mode 100644 index 6cb2fb580..000000000 Binary files a/priv/static/static/css/base16-mocha.css and /dev/null differ diff --git a/priv/static/static/css/base16-monokai.css b/priv/static/static/css/base16-monokai.css deleted file mode 100644 index fc7ccf471..000000000 Binary files a/priv/static/static/css/base16-monokai.css and /dev/null differ diff --git a/priv/static/static/css/base16-ocean.css b/priv/static/static/css/base16-ocean.css deleted file mode 100644 index 8622d17e0..000000000 Binary files a/priv/static/static/css/base16-ocean.css and /dev/null differ diff --git a/priv/static/static/css/base16-oceanicnext.css b/priv/static/static/css/base16-oceanicnext.css deleted file mode 100644 index df4d9ef5e..000000000 Binary files a/priv/static/static/css/base16-oceanicnext.css and /dev/null differ diff --git a/priv/static/static/css/base16-paraiso.css b/priv/static/static/css/base16-paraiso.css deleted file mode 100644 index b68c94071..000000000 Binary files a/priv/static/static/css/base16-paraiso.css and /dev/null differ diff --git a/priv/static/static/css/base16-phd.css b/priv/static/static/css/base16-phd.css deleted file mode 100644 index 54276ab11..000000000 Binary files a/priv/static/static/css/base16-phd.css and /dev/null differ diff --git a/priv/static/static/css/base16-pico.css b/priv/static/static/css/base16-pico.css deleted file mode 100644 index 86482b72d..000000000 Binary files a/priv/static/static/css/base16-pico.css and /dev/null differ diff --git a/priv/static/static/css/base16-pleroma-dark.css b/priv/static/static/css/base16-pleroma-dark.css deleted file mode 100644 index e1d46f927..000000000 Binary files a/priv/static/static/css/base16-pleroma-dark.css and /dev/null differ diff --git a/priv/static/static/css/base16-pleroma-light.css b/priv/static/static/css/base16-pleroma-light.css deleted file mode 100644 index 1a85689aa..000000000 Binary files a/priv/static/static/css/base16-pleroma-light.css and /dev/null differ diff --git a/priv/static/static/css/base16-pop.css b/priv/static/static/css/base16-pop.css deleted file mode 100644 index 14acac171..000000000 Binary files a/priv/static/static/css/base16-pop.css and /dev/null differ diff --git a/priv/static/static/css/base16-railscasts.css b/priv/static/static/css/base16-railscasts.css deleted file mode 100644 index 18f43bfd6..000000000 Binary files a/priv/static/static/css/base16-railscasts.css and /dev/null differ diff --git a/priv/static/static/css/base16-seti-ui.css b/priv/static/static/css/base16-seti-ui.css deleted file mode 100644 index bd4f9cc42..000000000 Binary files a/priv/static/static/css/base16-seti-ui.css and /dev/null differ diff --git a/priv/static/static/css/base16-shapeshifter.css b/priv/static/static/css/base16-shapeshifter.css deleted file mode 100644 index ded180691..000000000 Binary files a/priv/static/static/css/base16-shapeshifter.css and /dev/null differ diff --git a/priv/static/static/css/base16-solar-flare.css b/priv/static/static/css/base16-solar-flare.css deleted file mode 100644 index 7d1d38624..000000000 Binary files a/priv/static/static/css/base16-solar-flare.css and /dev/null differ diff --git a/priv/static/static/css/base16-solarized-dark.css b/priv/static/static/css/base16-solarized-dark.css deleted file mode 100644 index ac16f12c9..000000000 Binary files a/priv/static/static/css/base16-solarized-dark.css and /dev/null differ diff --git a/priv/static/static/css/base16-solarized-light.css b/priv/static/static/css/base16-solarized-light.css deleted file mode 100644 index 7164cb046..000000000 Binary files a/priv/static/static/css/base16-solarized-light.css and /dev/null differ diff --git a/priv/static/static/css/base16-spacemacs.css b/priv/static/static/css/base16-spacemacs.css deleted file mode 100644 index 487376500..000000000 Binary files a/priv/static/static/css/base16-spacemacs.css and /dev/null differ diff --git a/priv/static/static/css/base16-summerfruit-dark.css b/priv/static/static/css/base16-summerfruit-dark.css deleted file mode 100644 index 1c8f2332e..000000000 Binary files a/priv/static/static/css/base16-summerfruit-dark.css and /dev/null differ diff --git a/priv/static/static/css/base16-summerfruit-light.css b/priv/static/static/css/base16-summerfruit-light.css deleted file mode 100644 index cb54d4c54..000000000 Binary files a/priv/static/static/css/base16-summerfruit-light.css and /dev/null differ diff --git a/priv/static/static/css/base16-tomorrow-night.css b/priv/static/static/css/base16-tomorrow-night.css deleted file mode 100644 index 09ecf08ef..000000000 Binary files a/priv/static/static/css/base16-tomorrow-night.css and /dev/null differ diff --git a/priv/static/static/css/base16-tomorrow.css b/priv/static/static/css/base16-tomorrow.css deleted file mode 100644 index f14868230..000000000 Binary files a/priv/static/static/css/base16-tomorrow.css and /dev/null differ diff --git a/priv/static/static/css/base16-twilight.css b/priv/static/static/css/base16-twilight.css deleted file mode 100644 index c8dfda3f8..000000000 Binary files a/priv/static/static/css/base16-twilight.css and /dev/null differ diff --git a/priv/static/static/css/base16-unikitty-dark.css b/priv/static/static/css/base16-unikitty-dark.css deleted file mode 100644 index e6ef32e33..000000000 Binary files a/priv/static/static/css/base16-unikitty-dark.css and /dev/null differ diff --git a/priv/static/static/css/base16-unikitty-light.css b/priv/static/static/css/base16-unikitty-light.css deleted file mode 100644 index 7e4c51b7a..000000000 Binary files a/priv/static/static/css/base16-unikitty-light.css and /dev/null differ diff --git a/priv/static/static/css/themes.json b/priv/static/static/css/themes.json deleted file mode 100644 index ea8e5a0c4..000000000 --- a/priv/static/static/css/themes.json +++ /dev/null @@ -1,66 +0,0 @@ -[ -"base16-pleroma-dark.css", -"base16-pleroma-light.css", -"base16-3024.css", -"base16-apathy.css", -"base16-ashes.css", -"base16-atelier-cave.css", -"base16-atelier-dune.css", -"base16-atelier-estuary.css", -"base16-atelier-forest.css", -"base16-atelier-heath.css", -"base16-atelier-lakeside.css", -"base16-atelier-plateau.css", -"base16-atelier-savanna.css", -"base16-atelier-seaside.css", -"base16-atelier-sulphurpool.css", -"base16-bespin.css", -"base16-brewer.css", -"base16-bright.css", -"base16-chalk.css", -"base16-codeschool.css", -"base16-darktooth.css", -"base16-default-dark.css", -"base16-default-light.css", -"base16-eighties.css", -"base16-embers.css", -"base16-flat.css", -"base16-github.css", -"base16-google-dark.css", -"base16-google-light.css", -"base16-grayscale-dark.css", -"base16-grayscale-light.css", -"base16-green-screen.css", -"base16-harmonic16-dark.css", -"base16-harmonic16-light.css", -"base16-hopscotch.css", -"base16-ir-black.css", -"base16-isotope.css", -"base16-london-tube.css", -"base16-macintosh.css", -"base16-marrakesh.css", -"base16-materia.css", -"base16-mexico-light.css", -"base16-mocha.css", -"base16-monokai.css", -"base16-ocean.css", -"base16-oceanicnext.css", -"base16-paraiso.css", -"base16-phd.css", -"base16-pico.css", -"base16-pop.css", -"base16-railscasts.css", -"base16-seti-ui.css", -"base16-shapeshifter.css", -"base16-solar-flare.css", -"base16-solarized-dark.css", -"base16-solarized-light.css", -"base16-spacemacs.css", -"base16-summerfruit-dark.css", -"base16-summerfruit-light.css", -"base16-tomorrow-night.css", -"base16-tomorrow.css", -"base16-twilight.css", -"base16-unikitty-dark.css", -"base16-unikitty-light.css" -] diff --git a/priv/static/static/font/fontello.1581425930672.woff2 b/priv/static/static/font/fontello.1581425930672.woff2 deleted file mode 100644 index 81a10daee..000000000 Binary files a/priv/static/static/font/fontello.1581425930672.woff2 and /dev/null differ diff --git a/priv/static/static/font/fontello.1581425930672.eot b/priv/static/static/font/fontello.1582927362782.eot similarity index 98% rename from priv/static/static/font/fontello.1581425930672.eot rename to priv/static/static/font/fontello.1582927362782.eot index 0de06da29..bd848d613 100644 Binary files a/priv/static/static/font/fontello.1581425930672.eot and b/priv/static/static/font/fontello.1582927362782.eot differ diff --git a/priv/static/static/font/fontello.1581425930672.svg b/priv/static/static/font/fontello.1582927362782.svg similarity index 100% rename from priv/static/static/font/fontello.1581425930672.svg rename to priv/static/static/font/fontello.1582927362782.svg diff --git a/priv/static/static/font/fontello.1581425930672.ttf b/priv/static/static/font/fontello.1582927362782.ttf similarity index 99% rename from priv/static/static/font/fontello.1581425930672.ttf rename to priv/static/static/font/fontello.1582927362782.ttf index 5a9cefeec..82691040e 100644 Binary files a/priv/static/static/font/fontello.1581425930672.ttf and b/priv/static/static/font/fontello.1582927362782.ttf differ diff --git a/priv/static/static/font/fontello.1581425930672.woff b/priv/static/static/font/fontello.1582927362782.woff similarity index 98% rename from priv/static/static/font/fontello.1581425930672.woff rename to priv/static/static/font/fontello.1582927362782.woff index 28f4dda9d..8c8b4043d 100644 Binary files a/priv/static/static/font/fontello.1581425930672.woff and b/priv/static/static/font/fontello.1582927362782.woff differ diff --git a/priv/static/static/font/fontello.1582927362782.woff2 b/priv/static/static/font/fontello.1582927362782.woff2 new file mode 100644 index 000000000..147707460 Binary files /dev/null and b/priv/static/static/font/fontello.1582927362782.woff2 differ diff --git a/priv/static/static/fontello.1582927362782.css b/priv/static/static/fontello.1582927362782.css new file mode 100644 index 000000000..1889379ff Binary files /dev/null and b/priv/static/static/fontello.1582927362782.css differ diff --git a/priv/static/static/js/2.9be9f9ec29f7536c73c3.js b/priv/static/static/js/2.9be9f9ec29f7536c73c3.js deleted file mode 100644 index d464dbf74..000000000 Binary files a/priv/static/static/js/2.9be9f9ec29f7536c73c3.js and /dev/null differ diff --git a/priv/static/static/js/2.f158cbd2b8770e467dfe.js b/priv/static/static/js/2.f158cbd2b8770e467dfe.js new file mode 100644 index 000000000..24f80fe7b Binary files /dev/null and b/priv/static/static/js/2.f158cbd2b8770e467dfe.js differ diff --git a/priv/static/static/js/2.9be9f9ec29f7536c73c3.js.map b/priv/static/static/js/2.f158cbd2b8770e467dfe.js.map similarity index 50% rename from priv/static/static/js/2.9be9f9ec29f7536c73c3.js.map rename to priv/static/static/js/2.f158cbd2b8770e467dfe.js.map index 21efd7ec8..94ca6f090 100644 Binary files a/priv/static/static/js/2.9be9f9ec29f7536c73c3.js.map and b/priv/static/static/js/2.f158cbd2b8770e467dfe.js.map differ diff --git a/priv/static/static/js/app.128bd8b808a3b5b6da6b.js b/priv/static/static/js/app.128bd8b808a3b5b6da6b.js new file mode 100644 index 000000000..8d36b0c36 Binary files /dev/null and b/priv/static/static/js/app.128bd8b808a3b5b6da6b.js differ diff --git a/priv/static/static/js/app.128bd8b808a3b5b6da6b.js.map b/priv/static/static/js/app.128bd8b808a3b5b6da6b.js.map new file mode 100644 index 000000000..e53b74277 Binary files /dev/null and b/priv/static/static/js/app.128bd8b808a3b5b6da6b.js.map differ diff --git a/priv/static/static/js/app.f8af8a9b83e330e80903.js b/priv/static/static/js/app.f8af8a9b83e330e80903.js deleted file mode 100644 index f755c141a..000000000 Binary files a/priv/static/static/js/app.f8af8a9b83e330e80903.js and /dev/null differ diff --git a/priv/static/static/js/app.f8af8a9b83e330e80903.js.map b/priv/static/static/js/app.f8af8a9b83e330e80903.js.map deleted file mode 100644 index 106368819..000000000 Binary files a/priv/static/static/js/app.f8af8a9b83e330e80903.js.map and /dev/null differ diff --git a/priv/static/static/js/vendors~app.52ac194cbc427f97f06e.js b/priv/static/static/js/vendors~app.52ac194cbc427f97f06e.js deleted file mode 100644 index f59457df6..000000000 Binary files a/priv/static/static/js/vendors~app.52ac194cbc427f97f06e.js and /dev/null differ diff --git a/priv/static/static/js/vendors~app.52ac194cbc427f97f06e.js.map b/priv/static/static/js/vendors~app.52ac194cbc427f97f06e.js.map deleted file mode 100644 index b0ccd82fb..000000000 Binary files a/priv/static/static/js/vendors~app.52ac194cbc427f97f06e.js.map and /dev/null differ diff --git a/priv/static/static/js/vendors~app.c5bbd3734647f0cc7eef.js b/priv/static/static/js/vendors~app.c5bbd3734647f0cc7eef.js new file mode 100644 index 000000000..8964180cd Binary files /dev/null and b/priv/static/static/js/vendors~app.c5bbd3734647f0cc7eef.js differ diff --git a/priv/static/static/js/vendors~app.c5bbd3734647f0cc7eef.js.map b/priv/static/static/js/vendors~app.c5bbd3734647f0cc7eef.js.map new file mode 100644 index 000000000..fab720d23 Binary files /dev/null and b/priv/static/static/js/vendors~app.c5bbd3734647f0cc7eef.js.map differ diff --git a/priv/static/static/styles.json b/priv/static/static/styles.json index 23508970d..23f57c65e 100644 --- a/priv/static/static/styles.json +++ b/priv/static/static/styles.json @@ -1,6 +1,6 @@ { - "pleroma-dark": [ "Pleroma Dark", "#121a24", "#182230", "#b9b9ba", "#d8a070", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ], - "pleroma-light": [ "Pleroma Light", "#f2f4f6", "#dbe0e8", "#304055", "#f86f0f", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ], + "pleroma-dark": "/static/themes/pleroma-dark.json", + "pleroma-light": "/static/themes/pleroma-light.json", "pleroma-amoled": [ "Pleroma Dark AMOLED", "#000000", "#111111", "#b0b0b1", "#d8a070", "#aa0000", "#0fa00f", "#0095ff", "#d59500"], "classic-dark": [ "Classic Dark", "#161c20", "#282e32", "#b9b9b9", "#baaa9c", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ], "bird": [ "Bird", "#f8fafd", "#e6ecf0", "#14171a", "#0084b8", "#e0245e", "#17bf63", "#1b95e0", "#fab81e"], @@ -12,5 +12,6 @@ "redmond-xxi": "/static/themes/redmond-xxi.json", "breezy-dark": "/static/themes/breezy-dark.json", "breezy-light": "/static/themes/breezy-light.json", - "mammal": "/static/themes/mammal.json" + "mammal": "/static/themes/mammal.json", + "paper": "/static/themes/paper.json" } diff --git a/priv/static/static/terms-of-service.html b/priv/static/static/terms-of-service.html index c02cb7198..a6da539e4 100644 --- a/priv/static/static/terms-of-service.html +++ b/priv/static/static/terms-of-service.html @@ -1,7 +1,4 @@

Terms of Service

-

This is a placeholder ToS.

- -

Edit "/static/terms-of-service.html" to make it fit the needs of your instance.

-
- +

This is a placeholder ToS. Edit "/static/terms-of-service.html" to make it fit the needs of your instance.

+ diff --git a/priv/static/static/themes/breezy-dark.json b/priv/static/static/themes/breezy-dark.json index 6119bf887..76b962c56 100644 --- a/priv/static/static/themes/breezy-dark.json +++ b/priv/static/static/themes/breezy-dark.json @@ -1,7 +1,9 @@ { "_pleroma_theme_version": 2, "name": "Breezy Dark (beta)", - "theme": { + "source": { + "themeEngineVersion": 3, + "fonts": {}, "shadows": { "panel": [ { @@ -19,7 +21,7 @@ "y": "0", "blur": "0", "spread": "1", - "color": "#ffffff", + "color": "--btn,900", "alpha": "0.15", "inset": true }, @@ -40,7 +42,7 @@ "blur": "40", "spread": "-40", "inset": true, - "color": "#ffffff", + "color": "--panel,900", "alpha": "0.1" } ], @@ -50,8 +52,8 @@ "y": "0", "blur": 0, "spread": "1", - "color": "--link", - "alpha": "0.3", + "color": "--accent", + "alpha": "1", "inset": true }, { @@ -65,21 +67,12 @@ } ], "buttonPressed": [ - { - "x": 0, - "y": 0, - "blur": "0", - "spread": "50", - "color": "--faint", - "alpha": 1, - "inset": true - }, { "x": 0, "y": "0", "blur": 0, "spread": "1", - "color": "#ffffff", + "color": "--btn,900", "alpha": 0.2, "inset": true }, @@ -99,31 +92,30 @@ "y": "0", "blur": 0, "spread": "1", - "color": "#FFFFFF", + "color": "--input,900", "alpha": "0.2", "inset": true } ] }, - "fonts": {}, - "opacity": { - "input": "1", - "panel": "0" - }, + "opacity": {}, "colors": { "bg": "#31363b", "text": "#eff0f1", "link": "#3daee9", "fg": "#31363b", - "panel": "#31363b", - "input": "#232629", - "topBarLink": "#eff0f1", - "btn": "#31363b", + "panel": "transparent", + "input": "--bg,-6.47", + "topBarLink": "--topBarText", + "btn": "--bg", "border": "#4c545b", "cRed": "#da4453", "cBlue": "#3daee9", "cGreen": "#27ae60", - "cOrange": "#f67400" + "cOrange": "#f67400", + "btnPressed": "--accent", + "selectedMenu": "--accent", + "selectedMenuPopover": "--accent" }, "radii": { "btn": "2", diff --git a/priv/static/static/themes/breezy-light.json b/priv/static/static/themes/breezy-light.json index becf704fc..0968fff0c 100644 --- a/priv/static/static/themes/breezy-light.json +++ b/priv/static/static/themes/breezy-light.json @@ -1,7 +1,9 @@ { "_pleroma_theme_version": 2, "name": "Breezy Light (beta)", - "theme": { + "source": { + "themeEngineVersion": 3, + "fonts": {}, "shadows": { "panel": [ { @@ -19,7 +21,7 @@ "y": "0", "blur": "0", "spread": "1", - "color": "#000000", + "color": "--btn,900", "alpha": "0.3", "inset": true }, @@ -40,7 +42,7 @@ "blur": "40", "spread": "-40", "inset": true, - "color": "#ffffff", + "color": "--panel,900", "alpha": "0.1" } ], @@ -50,8 +52,8 @@ "y": "0", "blur": 0, "spread": "1", - "color": "--link", - "alpha": "0.3", + "color": "--accent", + "alpha": "1", "inset": true }, { @@ -65,21 +67,12 @@ } ], "buttonPressed": [ - { - "x": 0, - "y": 0, - "blur": "0", - "spread": "50", - "color": "--faint", - "alpha": 1, - "inset": true - }, { "x": 0, "y": "0", "blur": 0, "spread": "1", - "color": "#ffffff", + "color": "--btn,900", "alpha": 0.2, "inset": true }, @@ -99,31 +92,30 @@ "y": "0", "blur": 0, "spread": "1", - "color": "#000000", + "color": "--input,900", "alpha": "0.2", "inset": true } ] }, - "fonts": {}, "opacity": { "input": "1" }, "colors": { "bg": "#eff0f1", "text": "#232627", - "link": "#2980b9", - "fg": "#bcc2c7", - "panel": "#475057", - "panelText": "#fcfcfc", - "input": "#fcfcfc", - "topBar": "#475057", - "topBarLink": "#eff0f1", - "btn": "#eff0f1", + "fg": "#475057", + "accent": "#2980b9", + "input": "--bg,-6.47", + "topBarLink": "--topBarText", + "btn": "--bg", "cRed": "#da4453", "cBlue": "#2980b9", "cGreen": "#27ae60", - "cOrange": "#f67400" + "cOrange": "#f67400", + "btnPressed": "--accent", + "selectedMenu": "--accent", + "selectedMenuPopover": "--accent" }, "radii": { "btn": "2", diff --git a/priv/static/static/themes/paper.json b/priv/static/static/themes/paper.json new file mode 100644 index 000000000..a3b90a0a1 --- /dev/null +++ b/priv/static/static/themes/paper.json @@ -0,0 +1,172 @@ +{ + "_pleroma_theme_version": 2, + "name": "Paper", + "source": { + "themeEngineVersion": 3, + "fonts": {}, + "shadows": { + "panel": [ + { + "x": "0", + "y": "2", + "blur": "9", + "spread": 0, + "inset": false, + "color": "#668bb2", + "alpha": "0.1" + }, + { + "x": "0", + "y": "1", + "blur": "2", + "spread": "-1", + "inset": false, + "color": "#668bb2", + "alpha": "0.1" + } + ], + "topBar": [ + { + "x": 0, + "y": "3", + "blur": "8", + "spread": 0, + "inset": false, + "color": "#3e618e", + "alpha": "0.1" + }, + { + "x": 0, + "y": "1", + "blur": "4", + "spread": 0, + "inset": false, + "color": "#3e618e", + "alpha": "0.1" + } + ], + "button": [ + { + "x": 0, + "y": "2", + "blur": "5", + "spread": 0, + "color": "#463f78", + "alpha": "0.1", + "inset": false + } + ], + "input": [ + { + "x": 0, + "y": "1", + "blur": "2", + "spread": 0, + "inset": true, + "color": "#6277b7", + "alpha": "0.1" + } + ], + "buttonHover": [ + { + "x": 0, + "y": "2", + "blur": "5", + "spread": 0, + "color": "#494949", + "alpha": "0.1" + }, + { + "x": 0, + "y": "2", + "blur": "0", + "spread": "20", + "color": "#ffffff", + "alpha": "1", + "inset": true + } + ], + "buttonPressed": [ + { + "x": 0, + "y": 0, + "blur": "4", + "spread": "0", + "color": "#494949", + "alpha": "0.8", + "inset": false + } + ], + "avatarStatus": [ + { + "x": "0", + "y": "2", + "blur": "4", + "spread": "0", + "inset": false, + "color": "#3e618e", + "alpha": "0.1" + } + ], + "avatar": [ + { + "x": 0, + "y": "2", + "blur": "5", + "spread": "0", + "color": "#3e618e", + "alpha": "0.9" + } + ], + "popup": [ + { + "x": "0", + "y": "3", + "blur": "11", + "spread": 0, + "color": "#668bb2", + "alpha": "0.2" + }, + { + "x": "0", + "y": "2", + "blur": "3", + "spread": "-1", + "color": "#668bb2", + "alpha": "0.2" + } + ] + }, + "opacity": { + "underlay": "1", + "border": "0" + }, + "colors": { + "bg": "#ffffff", + "fg": "#f6f6f6", + "text": "#494949", + "underlay": "#ffffff", + "link": "#788ca1", + "accent": "#97a0aa", + "cBlue": "#788ca1", + "cRed": "#eed7ce", + "cGreen": "#788ca1", + "cOrange": "#788ca1", + "postLink": "#788ca1", + "border": "#ffffff", + "icon": "#b6c9c4", + "panel": "#ffffff", + "topBarText": "#4b4b4b" + }, + "radii": { + "btn": "0", + "input": "0", + "checkbox": "0", + "panel": "0", + "avatar": "2", + "avatarAlt": "2", + "tooltip": "0", + "attachment": "0" + } + } +} diff --git a/priv/static/static/themes/pleroma-dark.json b/priv/static/static/themes/pleroma-dark.json new file mode 100644 index 000000000..2703fba11 --- /dev/null +++ b/priv/static/static/themes/pleroma-dark.json @@ -0,0 +1,191 @@ +{ + "_pleroma_theme_version": 2, + "name": "Pleroma Dark", + "source": { + "themeEngineVersion": 3, + "fonts": {}, + "shadows": { + "buttonHover": [ + { + "x": 0, + "y": 0, + "blur": "1", + "spread": "2", + "color": "#b9b9ba", + "alpha": "0.4", + "inset": true + }, + { + "x": 0, + "y": 1, + "blur": 0, + "spread": 0, + "color": "#FFFFFF", + "alpha": 0.2, + "inset": true + }, + { + "x": 0, + "y": -1, + "blur": 0, + "spread": 0, + "color": "#000000", + "alpha": 0.2, + "inset": true + } + ], + "buttonPressed": [ + { + "x": 0, + "y": 0, + "blur": 4, + "spread": 0, + "color": "#000000", + "alpha": 1, + "inset": true + }, + { + "x": 0, + "y": 1, + "blur": 0, + "spread": 0, + "color": "#000000", + "alpha": 0.2, + "inset": true + }, + { + "x": 0, + "y": -1, + "blur": 0, + "spread": 0, + "color": "#FFFFFF", + "alpha": 0.2, + "inset": true + }, + { + "x": 0, + "y": 0, + "blur": "2", + "spread": 0, + "inset": false, + "color": "#000000", + "alpha": 1 + } + ], + "panelHeader": [ + { + "x": 0, + "y": "1", + "blur": "3", + "spread": 0, + "inset": false, + "color": "#000000", + "alpha": "0.4" + }, + { + "x": "0", + "y": "1", + "blur": "0", + "spread": 0, + "inset": true, + "color": "#ffffff", + "alpha": "0.2" + } + ], + "panel": [ + { + "x": "0", + "y": "0", + "blur": "3", + "spread": 0, + "color": "#000000", + "alpha": "0.5" + }, + { + "x": "0", + "y": "4", + "blur": "6", + "spread": "3", + "inset": false, + "color": "#000000", + "alpha": "0.3" + } + ], + "button": [ + { + "x": 0, + "y": 0, + "blur": 2, + "spread": 0, + "color": "#000000", + "alpha": 1 + }, + { + "x": 0, + "y": 1, + "blur": 0, + "spread": 0, + "color": "#FFFFFF", + "alpha": 0.2, + "inset": true + }, + { + "x": 0, + "y": -1, + "blur": 0, + "spread": 0, + "color": "#000000", + "alpha": 0.2, + "inset": true + } + ], + "topBar": [ + { + "x": 0, + "y": "1", + "blur": 4, + "spread": 0, + "color": "#000000", + "alpha": "0.4" + }, + { + "x": 0, + "y": "2", + "blur": "7", + "spread": 0, + "inset": false, + "color": "#000000", + "alpha": "0.3" + } + ] + }, + "opacity": { + "underlay": "0.6" + }, + "colors": { + "bg": "#0f161e", + "fg": "#151e2b", + "text": "#b9b9ba", + "underlay": "#090e14", + "accent": "#e2b188", + "cBlue": "#81beea", + "cRed": "#d31014", + "cGreen": "#5dc94a", + "cOrange": "#ffc459", + "border": "--fg,3", + "topBarText": "--text,-9.75", + "topBarLink": "--topBarText", + "btnToggled": "--accent,-24.2", + "alertErrorText": "--text,21.2", + "badgeNotification": "#e15932", + "badgeNotificationText": "#ffffff" + }, + "radii": { + "btn": "3", + "input": "3", + "panel": "3", + "avatar": "3", + "attachment": "3" + } + } +} diff --git a/priv/static/static/themes/pleroma-light.json b/priv/static/static/themes/pleroma-light.json new file mode 100644 index 000000000..05fc300aa --- /dev/null +++ b/priv/static/static/themes/pleroma-light.json @@ -0,0 +1,219 @@ +{ + "_pleroma_theme_version": 2, + "name": "Pleroma Light", + "source": { + "themeEngineVersion": 3, + "fonts": {}, + "shadows": { + "button": [ + { + "x": 0, + "y": 0, + "blur": 2, + "spread": 0, + "color": "#000000", + "alpha": "0.2" + }, + { + "x": 0, + "y": 1, + "blur": 0, + "spread": 0, + "color": "#FFFFFF", + "alpha": "0.5", + "inset": true + }, + { + "x": 0, + "y": -1, + "blur": 0, + "spread": 0, + "color": "#000000", + "alpha": 0.2, + "inset": true + } + ], + "buttonHover": [ + { + "x": 0, + "y": 0, + "blur": "2", + "spread": 0, + "color": "#000000", + "alpha": "0.2" + }, + { + "x": 0, + "y": "0", + "blur": "1", + "spread": "2", + "color": "#ffc39f", + "alpha": "1", + "inset": true + }, + { + "x": 0, + "y": -1, + "blur": 0, + "spread": 0, + "color": "#000000", + "alpha": 0.2, + "inset": true + } + ], + "input": [ + { + "x": 0, + "y": 1, + "blur": 0, + "spread": 0, + "color": "#000000", + "alpha": 0.2, + "inset": true + }, + { + "x": 0, + "y": -1, + "blur": 0, + "spread": 0, + "color": "#FFFFFF", + "alpha": 0.2, + "inset": true + }, + { + "x": 0, + "y": 0, + "blur": "2", + "inset": true, + "spread": 0, + "color": "#000000", + "alpha": "0.15" + } + ], + "panel": [ + { + "x": "0", + "y": 1, + "blur": "3", + "spread": 0, + "color": "#000000", + "alpha": "0.5" + }, + { + "x": "0", + "y": "3", + "blur": "6", + "spread": "1", + "inset": false, + "color": "#000000", + "alpha": "0.2" + } + ], + "panelHeader": [ + { + "x": 0, + "y": "1", + "blur": 0, + "spread": 0, + "inset": true, + "color": "#ffffff", + "alpha": "0.5" + }, + { + "x": 0, + "y": "1", + "blur": "3", + "spread": 0, + "inset": false, + "color": "#000000", + "alpha": "0.3" + } + ], + "buttonPressed": [ + { + "x": 0, + "y": 0, + "blur": 4, + "spread": 0, + "color": "#000000", + "alpha": "0.2" + }, + { + "x": 0, + "y": 1, + "blur": "1", + "spread": "2", + "color": "#000000", + "alpha": "0.3", + "inset": true + }, + { + "x": 0, + "y": -1, + "blur": 0, + "spread": 0, + "color": "#FFFFFF", + "alpha": 0.2, + "inset": true + } + ], + "popup": [ + { + "x": "1", + "y": "2", + "blur": "2", + "spread": 0, + "color": "#000000", + "alpha": "0.2" + }, + { + "x": "1", + "y": "3", + "blur": "7", + "spread": "0", + "inset": false, + "color": "#000000", + "alpha": "0.2" + } + ], + "avatarStatus": [ + { + "x": 0, + "y": "1", + "blur": "4", + "spread": "0", + "inset": false, + "color": "#000000", + "alpha": "0.2" + } + ] + }, + "opacity": { + "underlay": "0.4" + }, + "colors": { + "bg": "#f2f6f9", + "fg": "#d6dfed", + "text": "#304055", + "underlay": "#5d6086", + "accent": "#f55b1b", + "cBlue": "#0095ff", + "cRed": "#d31014", + "cGreen": "#0fa00f", + "cOrange": "#ffa500", + "border": "#d8e6f9", + "topBarText": "#304055", + "topBarLink": "--topBarText", + "btnToggled": "--accent,-24.2", + "input": "#dee3ed", + "badgeNotification": "#e83802" + }, + "radii": { + "btn": "3", + "input": "3", + "panel": "3", + "avatar": "3", + "attachment": "3" + } + } +} diff --git a/priv/static/static/themes/redmond-xx-se.json b/priv/static/static/themes/redmond-xx-se.json index 70ee89d1b..7a4a29da3 100644 --- a/priv/static/static/themes/redmond-xx-se.json +++ b/priv/static/static/themes/redmond-xx-se.json @@ -1,7 +1,8 @@ { "_pleroma_theme_version": 2, "name": "Redmond XX SE", - "theme": { + "source": { + "themeEngineVersion": 3, "shadows": { "panel": [ { @@ -268,6 +269,7 @@ "bg": "#c0c0c0", "text": "#000000", "link": "#0000ff", + "accent": "#000080", "fg": "#c0c0c0", "panel": "#000080", "panelFaint": "#c0c0c0", @@ -275,13 +277,16 @@ "topBar": "#000080", "topBarLink": "#ffffff", "btn": "#c0c0c0", + "btnToggled": "--btn", "faint": "#3f3f3f", "faintLink": "#404080", "border": "#808080", "cRed": "#FF0000", "cBlue": "#008080", "cGreen": "#008000", - "cOrange": "#808000" + "cOrange": "#808000", + "highlight": "--accent", + "selectedPost": "--bg,-10" }, "radii": { "btn": "0", diff --git a/priv/static/static/themes/redmond-xx.json b/priv/static/static/themes/redmond-xx.json index 4fd6a3691..ff95b1e06 100644 --- a/priv/static/static/themes/redmond-xx.json +++ b/priv/static/static/themes/redmond-xx.json @@ -1,7 +1,8 @@ { "_pleroma_theme_version": 2, "name": "Redmond XX", - "theme": { + "source": { + "themeEngineVersion": 3, "shadows": { "panel": [ { @@ -259,6 +260,7 @@ "bg": "#c0c0c0", "text": "#000000", "link": "#0000ff", + "accent": "#000080", "fg": "#c0c0c0", "panel": "#000080", "panelFaint": "#c0c0c0", @@ -266,13 +268,16 @@ "topBar": "#000080", "topBarLink": "#ffffff", "btn": "#c0c0c0", + "btnToggled": "--btn", "faint": "#3f3f3f", "faintLink": "#404080", "border": "#808080", "cRed": "#FF0000", "cBlue": "#008080", "cGreen": "#008000", - "cOrange": "#808000" + "cOrange": "#808000", + "highlight": "--accent", + "selectedPost": "--bg,-10" }, "radii": { "btn": "0", diff --git a/priv/static/static/themes/redmond-xxi.json b/priv/static/static/themes/redmond-xxi.json index d10bf138f..f788bdb83 100644 --- a/priv/static/static/themes/redmond-xxi.json +++ b/priv/static/static/themes/redmond-xxi.json @@ -1,7 +1,8 @@ { "_pleroma_theme_version": 2, "name": "Redmond XXI", - "theme": { + "source": { + "themeEngineVersion": 3, "shadows": { "panel": [ { @@ -241,6 +242,7 @@ "bg": "#d6d6ce", "text": "#000000", "link": "#0000ff", + "accent": "#0a246a", "fg": "#d6d6ce", "panel": "#042967", "panelFaint": "#FFFFFF", @@ -248,13 +250,16 @@ "topBar": "#042967", "topBarLink": "#ffffff", "btn": "#d6d6ce", + "btnToggled": "--btn", "faint": "#3f3f3f", "faintLink": "#404080", "border": "#808080", "cRed": "#c42726", "cBlue": "#6699cc", "cGreen": "#669966", - "cOrange": "#cc6633" + "cOrange": "#cc6633", + "highlight": "--accent", + "selectedPost": "--bg,-10" }, "radii": { "btn": "0", diff --git a/priv/static/sw-pleroma.js b/priv/static/sw-pleroma.js index 42ef52ad4..87455aa6a 100644 Binary files a/priv/static/sw-pleroma.js and b/priv/static/sw-pleroma.js differ diff --git a/test/captcha_test.exs b/test/captcha_test.exs index 393c8219e..5e29b48b0 100644 --- a/test/captcha_test.exs +++ b/test/captcha_test.exs @@ -1,17 +1,20 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors +# Copyright © 2017-2020 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.CaptchaTest do - use ExUnit.Case + use Pleroma.DataCase import Tesla.Mock + alias Pleroma.Captcha alias Pleroma.Captcha.Kocaptcha alias Pleroma.Captcha.Native @ets_options [:ordered_set, :private, :named_table, {:read_concurrency, true}] + clear_config([Pleroma.Captcha, :enabled]) + describe "Kocaptcha" do setup do ets_name = Kocaptcha.Ets @@ -31,17 +34,18 @@ defmodule Pleroma.CaptchaTest do test "new and validate" do new = Kocaptcha.new() - assert new[:type] == :kocaptcha - assert new[:token] == "afa1815e14e29355e6c8f6b143a39fa2" - assert new[:url] == - "https://captcha.kotobank.ch/captchas/afa1815e14e29355e6c8f6b143a39fa2.png" + token = "afa1815e14e29355e6c8f6b143a39fa2" + url = "https://captcha.kotobank.ch/captchas/afa1815e14e29355e6c8f6b143a39fa2.png" - assert Kocaptcha.validate( - new[:token], - "7oEy8c", - new[:answer_data] - ) == :ok + assert %{ + answer_data: answer, + token: ^token, + url: ^url, + type: :kocaptcha + } = new + + assert Kocaptcha.validate(token, "7oEy8c", answer) == :ok end end @@ -61,4 +65,52 @@ test "new and validate" do assert {:error, "Invalid CAPTCHA"} == Native.validate(token, answer, answer <> "foobar") end end + + describe "Captcha Wrapper" do + test "validate" do + Pleroma.Config.put([Pleroma.Captcha, :enabled], true) + + new = Captcha.new() + + assert %{ + answer_data: answer, + token: token + } = new + + assert is_binary(answer) + assert :ok = Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", answer) + end + + test "doesn't validate invalid answer" do + Pleroma.Config.put([Pleroma.Captcha, :enabled], true) + + new = Captcha.new() + + assert %{ + answer_data: answer, + token: token + } = new + + assert is_binary(answer) + + assert {:error, "Invalid answer data"} = + Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", answer <> "foobar") + end + + test "nil answer_data" do + Pleroma.Config.put([Pleroma.Captcha, :enabled], true) + + new = Captcha.new() + + assert %{ + answer_data: answer, + token: token + } = new + + assert is_binary(answer) + + assert {:error, "Invalid answer data"} = + Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", nil) + end + end end diff --git a/test/fixtures/mastodon-post-activity.json b/test/fixtures/mastodon-post-activity.json index b91263431..5c3d22722 100644 --- a/test/fixtures/mastodon-post-activity.json +++ b/test/fixtures/mastodon-post-activity.json @@ -35,6 +35,19 @@ "inReplyTo": null, "inReplyToAtomUri": null, "published": "2018-02-12T14:08:20Z", + "replies": { + "id": "http://mastodon.example.org/users/admin/statuses/99512778738411822/replies", + "type": "Collection", + "first": { + "type": "CollectionPage", + "next": "http://mastodon.example.org/users/admin/statuses/99512778738411822/replies?min_id=99512778738411824&page=true", + "partOf": "http://mastodon.example.org/users/admin/statuses/99512778738411822/replies", + "items": [ + "http://mastodon.example.org/users/admin/statuses/99512778738411823", + "http://mastodon.example.org/users/admin/statuses/99512778738411824" + ] + } + }, "sensitive": true, "summary": "cw", "tag": [ diff --git a/test/object/fetcher_test.exs b/test/object/fetcher_test.exs index 2aad7a588..3afd35648 100644 --- a/test/object/fetcher_test.exs +++ b/test/object/fetcher_test.exs @@ -26,6 +26,31 @@ defmodule Pleroma.Object.FetcherTest do :ok end + describe "max thread distance restriction" do + @ap_id "http://mastodon.example.org/@admin/99541947525187367" + + clear_config([:instance, :federation_incoming_replies_max_depth]) + + test "it returns thread depth exceeded error if thread depth is exceeded" do + Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0) + + assert {:error, "Max thread distance exceeded."} = + Fetcher.fetch_object_from_id(@ap_id, depth: 1) + end + + test "it fetches object if max thread depth is restricted to 0 and depth is not specified" do + Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0) + + assert {:ok, _} = Fetcher.fetch_object_from_id(@ap_id) + end + + test "it fetches object if requested depth does not exceed max thread depth" do + Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 10) + + assert {:ok, _} = Fetcher.fetch_object_from_id(@ap_id, depth: 10) + end + end + describe "actor origin containment" do test "it rejects objects with a bogus origin" do {:error, _} = Fetcher.fetch_object_from_id("https://info.pleroma.site/activity.json") diff --git a/test/stat_test.exs b/test/stat_test.exs new file mode 100644 index 000000000..1f0c6199a --- /dev/null +++ b/test/stat_test.exs @@ -0,0 +1,70 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.StateTest do + use Pleroma.DataCase + import Pleroma.Factory + alias Pleroma.Web.CommonAPI + + describe "status visibility count" do + test "on new status" do + user = insert(:user) + other_user = insert(:user) + + CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"}) + + Enum.each(0..1, fn _ -> + CommonAPI.post(user, %{ + "visibility" => "unlisted", + "status" => "hey" + }) + end) + + Enum.each(0..2, fn _ -> + CommonAPI.post(user, %{ + "visibility" => "direct", + "status" => "hey @#{other_user.nickname}" + }) + end) + + Enum.each(0..3, fn _ -> + CommonAPI.post(user, %{ + "visibility" => "private", + "status" => "hey" + }) + end) + + assert %{direct: 3, private: 4, public: 1, unlisted: 2} = + Pleroma.Stats.get_status_visibility_count() + end + + test "on status delete" do + user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"}) + assert %{public: 1} = Pleroma.Stats.get_status_visibility_count() + CommonAPI.delete(activity.id, user) + assert %{public: 0} = Pleroma.Stats.get_status_visibility_count() + end + + test "on status visibility update" do + user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"}) + assert %{public: 1, private: 0} = Pleroma.Stats.get_status_visibility_count() + {:ok, _} = CommonAPI.update_activity_scope(activity.id, %{"visibility" => "private"}) + assert %{public: 0, private: 1} = Pleroma.Stats.get_status_visibility_count() + end + + test "doesn't count unrelated activities" do + user = insert(:user) + other_user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"}) + _ = CommonAPI.follow(user, other_user) + CommonAPI.favorite(activity.id, other_user) + CommonAPI.repeat(activity.id, other_user) + + assert %{direct: 0, private: 0, public: 1, unlisted: 0} = + Pleroma.Stats.get_status_visibility_count() + end + end +end diff --git a/test/support/captcha_mock.ex b/test/support/captcha_mock.ex index 65ca6b3bd..6dae94edf 100644 --- a/test/support/captcha_mock.ex +++ b/test/support/captcha_mock.ex @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors +# Copyright © 2017-2020 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Captcha.Mock do @@ -7,8 +7,17 @@ defmodule Pleroma.Captcha.Mock do @behaviour Service @impl Service - def new, do: %{type: :mock} + def new, + do: %{ + type: :mock, + token: "afa1815e14e29355e6c8f6b143a39fa2", + answer_data: "63615261b77f5354fb8c4e4986477555", + url: "https://example.org/captcha.png" + } @impl Service - def validate(_token, _captcha, _data), do: :ok + def validate(_token, captcha, captcha) when not is_nil(captcha), do: :ok + + def validate(_token, captcha, answer), + do: {:error, "Invalid CAPTCHA captcha: #{inspect(captcha)} ; answer: #{inspect(answer)}"} end diff --git a/test/support/oban_helpers.ex b/test/support/oban_helpers.ex index 72792c064..0e3b654df 100644 --- a/test/support/oban_helpers.ex +++ b/test/support/oban_helpers.ex @@ -9,6 +9,10 @@ defmodule Pleroma.Tests.ObanHelpers do alias Pleroma.Repo + def wipe_all do + Repo.delete_all(Oban.Job) + end + def perform_all do Oban.Job |> Repo.all() diff --git a/test/tasks/instance_test.exs b/test/tasks/instance_test.exs index d69275726..a0cc5d7c7 100644 --- a/test/tasks/instance_test.exs +++ b/test/tasks/instance_test.exs @@ -3,7 +3,7 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.InstanceTest do - use ExUnit.Case, async: true + use ExUnit.Case setup do File.mkdir_p!(tmp_path()) @@ -15,6 +15,8 @@ defmodule Pleroma.InstanceTest do if File.exists?(static_dir) do File.rm_rf(Path.join(static_dir, "robots.txt")) end + + Pleroma.Config.put([:instance, :static_dir], static_dir) end) :ok diff --git a/test/tasks/refresh_counter_cache_test.exs b/test/tasks/refresh_counter_cache_test.exs new file mode 100644 index 000000000..47367af94 --- /dev/null +++ b/test/tasks/refresh_counter_cache_test.exs @@ -0,0 +1,43 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.RefreshCounterCacheTest do + use Pleroma.DataCase + alias Pleroma.Web.CommonAPI + import ExUnit.CaptureIO, only: [capture_io: 1] + import Pleroma.Factory + + test "counts statuses" do + user = insert(:user) + other_user = insert(:user) + + CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"}) + + Enum.each(0..1, fn _ -> + CommonAPI.post(user, %{ + "visibility" => "unlisted", + "status" => "hey" + }) + end) + + Enum.each(0..2, fn _ -> + CommonAPI.post(user, %{ + "visibility" => "direct", + "status" => "hey @#{other_user.nickname}" + }) + end) + + Enum.each(0..3, fn _ -> + CommonAPI.post(user, %{ + "visibility" => "private", + "status" => "hey" + }) + end) + + assert capture_io(fn -> Mix.Tasks.Pleroma.RefreshCounterCache.run([]) end) =~ "Done\n" + + assert %{direct: 3, private: 4, public: 1, unlisted: 2} = + Pleroma.Stats.get_status_visibility_count() + end +end diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 1b12ee3a9..937f78cbe 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -3,7 +3,9 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do + use Oban.Testing, repo: Pleroma.Repo use Pleroma.DataCase + alias Pleroma.Activity alias Pleroma.Object alias Pleroma.Object.Fetcher @@ -40,7 +42,7 @@ test "it ignores an incoming notice if we already have it" do end @tag capture_log: true - test "it fetches replied-to activities if we don't have them" do + test "it fetches reply-to activities if we don't have them" do data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!() @@ -61,7 +63,7 @@ test "it fetches replied-to activities if we don't have them" do assert returned_object.data["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873" end - test "it does not fetch replied-to activities beyond max_replies_depth" do + test "it does not fetch reply-to activities beyond max replies depth limit" do data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!() @@ -73,7 +75,7 @@ test "it does not fetch replied-to activities beyond max_replies_depth" do data = Map.put(data, "object", object) with_mock Pleroma.Web.Federator, - allowed_incoming_reply_depth?: fn _ -> false end do + allowed_thread_distance?: fn _ -> false end do {:ok, returned_activity} = Transmogrifier.handle_incoming(data) returned_object = Object.normalize(returned_activity, false) @@ -1348,6 +1350,101 @@ test "it accepts Move activities" do end end + describe "`handle_incoming/2`, Mastodon format `replies` handling" do + clear_config([:activitypub, :note_replies_output_limit]) do + Pleroma.Config.put([:activitypub, :note_replies_output_limit], 5) + end + + clear_config([:instance, :federation_incoming_replies_max_depth]) + + setup do + data = + "test/fixtures/mastodon-post-activity.json" + |> File.read!() + |> Poison.decode!() + + items = get_in(data, ["object", "replies", "first", "items"]) + assert length(items) > 0 + + %{data: data, items: items} + end + + test "schedules background fetching of `replies` items if max thread depth limit allows", %{ + data: data, + items: items + } do + Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 10) + + {:ok, _activity} = Transmogrifier.handle_incoming(data) + + for id <- items do + job_args = %{"op" => "fetch_remote", "id" => id, "depth" => 1} + assert_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker, args: job_args) + end + end + + test "does NOT schedule background fetching of `replies` beyond max thread depth limit allows", + %{data: data} do + Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0) + + {:ok, _activity} = Transmogrifier.handle_incoming(data) + + assert all_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker) == [] + end + end + + describe "`handle_incoming/2`, Pleroma format `replies` handling" do + clear_config([:activitypub, :note_replies_output_limit]) do + Pleroma.Config.put([:activitypub, :note_replies_output_limit], 5) + end + + clear_config([:instance, :federation_incoming_replies_max_depth]) + + setup do + user = insert(:user) + + {:ok, activity} = CommonAPI.post(user, %{"status" => "post1"}) + + {:ok, reply1} = + CommonAPI.post(user, %{"status" => "reply1", "in_reply_to_status_id" => activity.id}) + + {:ok, reply2} = + CommonAPI.post(user, %{"status" => "reply2", "in_reply_to_status_id" => activity.id}) + + replies_uris = Enum.map([reply1, reply2], fn a -> a.object.data["id"] end) + + {:ok, federation_output} = Transmogrifier.prepare_outgoing(activity.data) + + Repo.delete(activity.object) + Repo.delete(activity) + + %{federation_output: federation_output, replies_uris: replies_uris} + end + + test "schedules background fetching of `replies` items if max thread depth limit allows", %{ + federation_output: federation_output, + replies_uris: replies_uris + } do + Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 1) + + {:ok, _activity} = Transmogrifier.handle_incoming(federation_output) + + for id <- replies_uris do + job_args = %{"op" => "fetch_remote", "id" => id, "depth" => 1} + assert_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker, args: job_args) + end + end + + test "does NOT schedule background fetching of `replies` beyond max thread depth limit allows", + %{federation_output: federation_output} do + Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0) + + {:ok, _activity} = Transmogrifier.handle_incoming(federation_output) + + assert all_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker) == [] + end + end + describe "prepare outgoing" do test "it inlines private announced objects" do user = insert(:user) @@ -2046,4 +2143,49 @@ test "returns object with emoji when object contains map tag" do } end end + + describe "set_replies/1" do + clear_config([:activitypub, :note_replies_output_limit]) do + Pleroma.Config.put([:activitypub, :note_replies_output_limit], 2) + end + + test "returns unmodified object if activity doesn't have self-replies" do + data = Poison.decode!(File.read!("test/fixtures/mastodon-post-activity.json")) + assert Transmogrifier.set_replies(data) == data + end + + test "sets `replies` collection with a limited number of self-replies" do + [user, another_user] = insert_list(2, :user) + + {:ok, %{id: id1} = activity} = CommonAPI.post(user, %{"status" => "1"}) + + {:ok, %{id: id2} = self_reply1} = + CommonAPI.post(user, %{"status" => "self-reply 1", "in_reply_to_status_id" => id1}) + + {:ok, self_reply2} = + CommonAPI.post(user, %{"status" => "self-reply 2", "in_reply_to_status_id" => id1}) + + # Assuming to _not_ be present in `replies` due to :note_replies_output_limit is set to 2 + {:ok, _} = + CommonAPI.post(user, %{"status" => "self-reply 3", "in_reply_to_status_id" => id1}) + + {:ok, _} = + CommonAPI.post(user, %{ + "status" => "self-reply to self-reply", + "in_reply_to_status_id" => id2 + }) + + {:ok, _} = + CommonAPI.post(another_user, %{ + "status" => "another user's reply", + "in_reply_to_status_id" => id1 + }) + + object = Object.normalize(activity) + replies_uris = Enum.map([self_reply1, self_reply2], fn a -> a.object.data["id"] end) + + assert %{"type" => "Collection", "items" => ^replies_uris} = + Transmogrifier.set_replies(object.data)["replies"] + end + end end diff --git a/test/web/activity_pub/views/object_view_test.exs b/test/web/activity_pub/views/object_view_test.exs index 13447dc29..acc855b98 100644 --- a/test/web/activity_pub/views/object_view_test.exs +++ b/test/web/activity_pub/views/object_view_test.exs @@ -36,6 +36,26 @@ test "renders a note activity" do assert result["@context"] end + describe "note activity's `replies` collection rendering" do + clear_config([:activitypub, :note_replies_output_limit]) do + Pleroma.Config.put([:activitypub, :note_replies_output_limit], 5) + end + + test "renders `replies` collection for a note activity" do + user = insert(:user) + activity = insert(:note_activity, user: user) + + {:ok, self_reply1} = + CommonAPI.post(user, %{"status" => "self-reply 1", "in_reply_to_status_id" => activity.id}) + + replies_uris = [self_reply1.object.data["id"]] + result = ObjectView.render("object.json", %{object: refresh_record(activity)}) + + assert %{"type" => "Collection", "items" => ^replies_uris} = + get_in(result, ["object", "replies"]) + end + end + test "renders a like activity" do note = insert(:note_activity) object = Object.normalize(note) diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs index 0cab546ac..7add75263 100644 --- a/test/web/admin_api/admin_api_controller_test.exs +++ b/test/web/admin_api/admin_api_controller_test.exs @@ -3064,6 +3064,52 @@ test "pleroma restarts", %{conn: conn} do end end + describe "GET /api/pleroma/admin/statuses" do + test "returns all public, unlisted, and direct statuses", %{conn: conn, admin: admin} do + blocked = insert(:user) + user = insert(:user) + User.block(admin, blocked) + + {:ok, _} = + CommonAPI.post(user, %{"status" => "@#{admin.nickname}", "visibility" => "direct"}) + + {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"}) + {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"}) + {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"}) + {:ok, _} = CommonAPI.post(blocked, %{"status" => ".", "visibility" => "public"}) + + response = + conn + |> get("/api/pleroma/admin/statuses") + |> json_response(200) + + refute "private" in Enum.map(response, & &1["visibility"]) + assert length(response) == 4 + end + + test "returns only local statuses with local_only on", %{conn: conn} do + user = insert(:user) + remote_user = insert(:user, local: false, nickname: "archaeme@archae.me") + insert(:note_activity, user: user, local: true) + insert(:note_activity, user: remote_user, local: false) + + response = + conn + |> get("/api/pleroma/admin/statuses?local_only=true") + |> json_response(200) + + assert length(response) == 1 + end + + test "returns private statuses with godmode on", %{conn: conn} do + user = insert(:user) + {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"}) + {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"}) + conn = get(conn, "/api/pleroma/admin/statuses?godmode=true") + assert json_response(conn, 200) |> length() == 2 + end + end + describe "GET /api/pleroma/admin/users/:nickname/statuses" do setup do user = insert(:user) @@ -3114,6 +3160,20 @@ test "returns private statuses with godmode on", %{conn: conn, user: user} do assert json_response(conn, 200) |> length() == 5 end + + test "excludes reblogs by default", %{conn: conn, user: user} do + other_user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{"status" => "."}) + {:ok, %Activity{}, _} = CommonAPI.repeat(activity.id, other_user) + + conn_res = get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses") + assert json_response(conn_res, 200) |> length() == 0 + + conn_res = + get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses?with_reblogs=true") + + assert json_response(conn_res, 200) |> length() == 1 + end end describe "GET /api/pleroma/admin/moderation_log" do @@ -3396,7 +3456,7 @@ test "GET /instances/:instance/statuses", %{conn: conn} do user = insert(:user, local: false, nickname: "archaeme@archae.me") user2 = insert(:user, local: false, nickname: "test@test.com") insert_pair(:note_activity, user: user) - insert(:note_activity, user: user2) + activity = insert(:note_activity, user: user2) ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses") @@ -3415,6 +3475,16 @@ test "GET /instances/:instance/statuses", %{conn: conn} do response = json_response(ret_conn, 200) assert Enum.empty?(response) + + CommonAPI.repeat(activity.id, user) + + ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses") + response = json_response(ret_conn, 200) + assert length(response) == 2 + + ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true") + response = json_response(ret_conn, 200) + assert length(response) == 3 end end @@ -3544,6 +3614,25 @@ test "GET /api/pleroma/admin/config/descriptions", %{conn: conn} do assert String.starts_with?(child["group"], ":") assert child["description"] end + + describe "/api/pleroma/admin/stats" do + test "status visibility count", %{conn: conn} do + admin = insert(:user, is_admin: true) + user = insert(:user) + CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"}) + CommonAPI.post(user, %{"visibility" => "unlisted", "status" => "hey"}) + CommonAPI.post(user, %{"visibility" => "unlisted", "status" => "hey"}) + + response = + conn + |> assign(:user, admin) + |> get("/api/pleroma/admin/stats") + |> json_response(200) + + assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 2} = + response["status_visibility"] + end + end end # Needed for testing diff --git a/test/web/push/impl_test.exs b/test/web/push/impl_test.exs index 737976f1f..9f931c941 100644 --- a/test/web/push/impl_test.exs +++ b/test/web/push/impl_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors +# Copyright © 2017-2020 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.Push.ImplTest do @@ -98,6 +98,14 @@ test "delete subscription if result send message between 400..500" do refute Pleroma.Repo.get(Subscription, subscription.id) end + test "deletes subscription when token has been deleted" do + subscription = insert(:push_subscription) + + Pleroma.Repo.delete(subscription.token) + + refute Pleroma.Repo.get(Subscription, subscription.id) + end + test "renders title and body for create activity" do user = insert(:user, nickname: "Bob")