diff options
27 files changed, 242 insertions, 555 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b70415ac6..8daa9f434 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -31,6 +31,7 @@ stages: - deploy - release - docker + - docker-combine before_script: - echo $MIX_ENV @@ -375,104 +376,167 @@ arm64-musl: before_script: *before-release-musl script: *release -docker: +.kaniko: stage: docker - image: docker:latest + image: + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] cache: {} dependencies: [] - variables: &docker-variables - DOCKER_DRIVER: overlay2 - DOCKER_HOST: unix:///var/run/docker.sock - IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA - IMAGE_TAG_SLUG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG - IMAGE_TAG_LATEST: $CI_REGISTRY_IMAGE:latest - IMAGE_TAG_LATEST_STABLE: $CI_REGISTRY_IMAGE:latest-stable - DOCKER_BUILDX_URL: https://github.com/docker/buildx/releases/download/v0.6.3/buildx-v0.6.3.linux-amd64 - DOCKER_BUILDX_HASH: 980e6b9655f971991fbbb5fd6cd19f1672386195 - before_script: &before-docker - - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - - docker pull $IMAGE_TAG_SLUG || true + before_script: &before-kaniko - export CI_JOB_TIMESTAMP=$(date --utc -Iseconds) - export CI_VCS_REF=$CI_COMMIT_SHORT_SHA - allow_failure: true - script: - - mkdir -p /root/.docker/cli-plugins - - wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx - - echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c - - chmod +x ~/.docker/cli-plugins/docker-buildx - - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes - - docker buildx create --name mbuilder --driver docker-container --use - - docker buildx inspect --bootstrap - - docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST . - tags: - - dind + - export IMAGE_TAG=$CI_REGISTRY_IMAGE/$BUILD_ARCH_IMG_SUFFIX:$CI_COMMIT_SHORT_SHA + - export IMAGE_TAG_SLUG=$CI_REGISTRY_IMAGE/$BUILD_ARCH_IMG_SUFFIX:$CI_COMMIT_REF_SLUG + - export IMAGE_TAG_LATEST=$CI_REGISTRY_IMAGE/$BUILD_ARCH_IMG_SUFFIX:latest + - export IMAGE_TAG_LATEST_STABLE=$CI_REGISTRY_IMAGE/$BUILD_ARCH_IMG_SUFFIX:latest-stable + - mkdir -p /kaniko/.docker + - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json + +.kaniko-latest: + extends: .kaniko only: - develop@pleroma/pleroma - -docker-stable: - stage: docker - image: docker:latest - cache: {} - dependencies: [] - variables: *docker-variables - before_script: *before-docker - allow_failure: true script: - - mkdir -p /root/.docker/cli-plugins - - wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx - - echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c - - chmod +x ~/.docker/cli-plugins/docker-buildx - - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes - - docker buildx create --name mbuilder --driver docker-container --use - - docker buildx inspect --bootstrap - - docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST_STABLE . - tags: - - dind + - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --custom-platform=$BUILD_ARCH --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP --build-arg ELIXIR_IMG=$ELIXIR_IMG --destination $IMAGE_TAG --destination $IMAGE_TAG_SLUG --destination $IMAGE_TAG_LATEST + +.kaniko-stable: + extends: .kaniko only: - stable@pleroma/pleroma + script: + - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --custom-platform=$BUILD_ARCH --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP --build-arg ELIXIR_IMG=$ELIXIR_IMG --destination $IMAGE_TAG --destination $IMAGE_TAG_SLUG --destination $IMAGE_TAG_LATEST_STABLE -docker-release: - stage: docker - image: docker:latest - cache: {} - dependencies: [] - variables: *docker-variables - before_script: *before-docker - allow_failure: true +.kaniko-release: + extends: .kaniko + only: + - /^release/.*$/@pleroma/pleroma script: + - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --custom-platform=$BUILD_ARCH --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP --build-arg ELIXIR_IMG=$ELIXIR_IMG --destination $IMAGE_TAG --destination $IMAGE_TAG_SLUG + +.kaniko-adhoc: + extends: .kaniko + only: + - /^build-docker/.*$/@pleroma/pleroma script: - - mkdir -p /root/.docker/cli-plugins - - wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx - - echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c - - chmod +x ~/.docker/cli-plugins/docker-buildx - - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes - - docker buildx create --name mbuilder --driver docker-container --use - - docker buildx inspect --bootstrap - - docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG . + - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --custom-platform=$BUILD_ARCH --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP --build-arg ELIXIR_IMG=$ELIXIR_IMG --destination $IMAGE_TAG --destination $IMAGE_TAG_SLUG + +.kaniko:linux/amd64: + variables: + BUILD_ARCH: linux/amd64 + BUILD_ARCH_IMG_SUFFIX: linux-amd64 + ELIXIR_IMG: hexpm/elixir tags: - - dind - only: - - /^release/.*$/@pleroma/pleroma + - amd64 -docker-adhoc: - stage: docker - image: docker:latest +.kaniko:linux/arm64: + variables: + BUILD_ARCH: linux/arm64/v8 + BUILD_ARCH_IMG_SUFFIX: linux-arm64-v8 + ELIXIR_IMG: hexpm/elixir + tags: + - arm + +.kaniko:linux/arm: + variables: + BUILD_ARCH: linux/arm/v7 + BUILD_ARCH_IMG_SUFFIX: linux-arm-v7 + ELIXIR_IMG: git.pleroma.social:5050/pleroma/ci-image/elixir-linux-arm-v7 + tags: + - arm32-specified + +kaniko-latest:linux/amd64: + extends: + - .kaniko-latest + - .kaniko:linux/amd64 + +kaniko-latest:linux/arm64: + extends: + - .kaniko-latest + - .kaniko:linux/arm64 + +kaniko-latest:linux/arm: + extends: + - .kaniko-latest + - .kaniko:linux/arm + +kaniko-stable:linux/amd64: + extends: + - .kaniko-stable + - .kaniko:linux/amd64 + +kaniko-stable:linux/arm64: + extends: + - .kaniko-stable + - .kaniko:linux/arm64 + +kaniko-stable:linux/arm: + extends: + - .kaniko-stable + - .kaniko:linux/arm + +kaniko-release:linux/amd64: + extends: + - .kaniko-release + - .kaniko:linux/amd64 + +kaniko-release:linux/arm64: + extends: + - .kaniko-release + - .kaniko:linux/arm64 + +kaniko-release:linux/arm: + extends: + - .kaniko-release + - .kaniko:linux/arm + +.docker-combine: + stage: docker-combine + image: docker:cli cache: {} - dependencies: [] - variables: *docker-variables - before_script: *before-docker - allow_failure: true + before_script: + - 'BUILD_ARCHES="linux-amd64 linux-arm64-v8 linux-arm-v7"' + - export IMAGE_TAG=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA + - export IMAGE_TAG_SLUG=$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG + - export IMAGE_TAG_LATEST=$CI_REGISTRY_IMAGE:latest + - export IMAGE_TAG_LATEST_STABLE=$CI_REGISTRY_IMAGE:latest-stable + - 'IMAGES=; for arch in $BUILD_ARCHES; do IMAGES="$IMAGES $CI_REGISTRY_IMAGE/$arch:$CI_COMMIT_SHORT_SHA"; done' + - 'IMAGES_SLUG=; for arch in $BUILD_ARCHES; do IMAGES_SLUG="$IMAGES_SLUG $CI_REGISTRY_IMAGE/$arch:$CI_COMMIT_REF_SLUG"; done' + - 'IMAGES_LATEST=; for arch in $BUILD_ARCHES; do IMAGES_LATEST="$IMAGES_LATEST $CI_REGISTRY_IMAGE/$arch:latest"; done' + - 'IMAGES_LATEST_STABLE=; for arch in $BUILD_ARCHES; do IMAGES_LATEST_STABLE="$IMAGES_LATEST_STABLE $CI_REGISTRY_IMAGE/$arch:latest"; done' + - mkdir -p ~/.docker + - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > ~/.docker/config.json + +docker-combine:latest: + extends: .docker-combine + only: + - develop@pleroma/pleroma script: + - 'docker manifest create $IMAGE_TAG $IMAGES' + - 'docker manifest push $IMAGE_TAG' + - 'docker manifest create $IMAGE_TAG_SLUG $IMAGES_SLUG' + - 'docker manifest push $IMAGE_TAG_SLUG' + - 'docker manifest create $IMAGE_TAG_LATEST $IMAGES_LATEST' + - 'docker manifest push $IMAGE_TAG_LATEST' + +docker-combine:stable: + extends: .docker-combine + only: + - stable@pleroma/pleroma script: - - mkdir -p /root/.docker/cli-plugins - - wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx - - echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c - - chmod +x ~/.docker/cli-plugins/docker-buildx - - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes - - docker buildx create --name mbuilder --driver docker-container --use - - docker buildx inspect --bootstrap - - docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG . - tags: - - dind + - 'docker manifest create $IMAGE_TAG $IMAGES' + - 'docker manifest push $IMAGE_TAG' + - 'docker manifest create $IMAGE_TAG_SLUG $IMAGES_SLUG' + - 'docker manifest push $IMAGE_TAG_SLUG' + - 'docker manifest create $IMAGE_TAG_LATEST_STABLE $IMAGES_LATEST_STABLE' + - 'docker manifest push $IMAGE_TAG_LATEST_STABLE' + +docker-combine:release: + extends: .docker-combine only: - - /^build-docker/.*$/@pleroma/pleroma + - /^release/.*$/@pleroma/pleroma + script: + - 'docker manifest create $IMAGE_TAG $IMAGES' + - 'docker manifest push $IMAGE_TAG' + - 'docker manifest create $IMAGE_TAG_SLUG $IMAGES_SLUG' + - 'docker manifest push $IMAGE_TAG_SLUG' diff --git a/Dockerfile b/Dockerfile index 8c3ff3ac5..310d18104 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,9 @@ +ARG ELIXIR_IMG=hexpm/elixir ARG ELIXIR_VER=1.11.4 ARG ERLANG_VER=24.2.1 ARG ALPINE_VER=3.17.0 -FROM hexpm/elixir:${ELIXIR_VER}-erlang-${ERLANG_VER}-alpine-${ALPINE_VER} as build +FROM ${ELIXIR_IMG}:${ELIXIR_VER}-erlang-${ERLANG_VER}-alpine-${ALPINE_VER} as build COPY . . diff --git a/changelog.d/3870.skip b/changelog.d/3870.skip new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/changelog.d/3870.skip diff --git a/changelog.d/3872.remove b/changelog.d/3872.remove new file mode 100644 index 000000000..54cbb660e --- /dev/null +++ b/changelog.d/3872.remove @@ -0,0 +1 @@ +remove BBS/SSH feature, replaced by an external bridge.
\ No newline at end of file diff --git a/changelog.d/3873.fix b/changelog.d/3873.fix new file mode 100644 index 000000000..4699f7b58 --- /dev/null +++ b/changelog.d/3873.fix @@ -0,0 +1 @@ +UploadedMedia: Add missing disposition_type to Content-Disposition
\ No newline at end of file diff --git a/changelog.d/3876.skip b/changelog.d/3876.skip new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/changelog.d/3876.skip diff --git a/changelog.d/3877.skip b/changelog.d/3877.skip new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/changelog.d/3877.skip diff --git a/changelog.d/3878.skip b/changelog.d/3878.skip new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/changelog.d/3878.skip diff --git a/changelog.d/3882.add b/changelog.d/3882.add new file mode 100644 index 000000000..4712de1dc --- /dev/null +++ b/changelog.d/3882.add @@ -0,0 +1 @@ +Allow lang attribute in status text diff --git a/config/config.exs b/config/config.exs index e41ec2f91..178b6be99 100644 --- a/config/config.exs +++ b/config/config.exs @@ -617,9 +617,6 @@ config :pleroma, :ldap, base: System.get_env("LDAP_BASE") || "dc=example,dc=com", uid: System.get_env("LDAP_UID") || "cn" -config :esshd, - enabled: false - oauth_consumer_strategies = System.get_env("OAUTH_CONSUMER_STRATEGIES") |> to_string() diff --git a/config/description.exs b/config/description.exs index 78dc8770d..5f8add8a4 100644 --- a/config/description.exs +++ b/config/description.exs @@ -2629,45 +2629,6 @@ config :pleroma, :config_description, [ ] }, %{ - group: :esshd, - label: "ESSHD", - type: :group, - description: - "Before enabling this you must add :esshd to mix.exs as one of the extra_applications " <> - "and generate host keys in your priv dir with ssh-keygen -m PEM -N \"\" -b 2048 -t rsa -f ssh_host_rsa_key", - children: [ - %{ - key: :enabled, - type: :boolean, - description: "Enables SSH" - }, - %{ - key: :priv_dir, - type: :string, - description: "Dir with SSH keys", - suggestions: ["/some/path/ssh_keys"] - }, - %{ - key: :handler, - type: :string, - description: "Handler module", - suggestions: ["Pleroma.BBS.Handler"] - }, - %{ - key: :port, - type: :integer, - description: "Port to connect", - suggestions: [10_022] - }, - %{ - key: :password_authenticator, - type: :string, - description: "Authenticator module", - suggestions: ["Pleroma.BBS.Authenticator"] - } - ] - }, - %{ group: :mime, label: "Mime Types", type: :group, diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md index bbdf30a0f..70abe3e0c 100644 --- a/docs/configuration/cheatsheet.md +++ b/docs/configuration/cheatsheet.md @@ -873,21 +873,8 @@ This will probably take a long time. ### BBS / SSH access -To enable simple command line interface accessible over ssh, add a setting like this to your configuration file: - -```exs -app_dir = File.cwd! -priv_dir = Path.join([app_dir, "priv/ssh_keys"]) - -config :esshd, - enabled: true, - priv_dir: priv_dir, - handler: "Pleroma.BBS.Handler", - port: 10_022, - password_authenticator: "Pleroma.BBS.Authenticator" -``` - -Feel free to adjust the priv_dir and port number. Then you will have to create the key for the keys (in the example `priv/ssh_keys`) and create the host keys with `ssh-keygen -m PEM -N "" -b 2048 -t rsa -f ssh_host_rsa_key`. After restarting, you should be able to connect to your Pleroma instance with `ssh username@server -p $PORT` +This feature has been removed from Pleroma core. +However, a client has been made and is available at https://git.pleroma.social/Duponin/sshocial. ### :gopher * `enabled`: Enables the gopher interface diff --git a/docs/development/API/admin_api.md b/docs/development/API/admin_api.md index f6e9f7d2a..7d31ee262 100644 --- a/docs/development/API/admin_api.md +++ b/docs/development/API/admin_api.md @@ -1585,6 +1585,7 @@ Returns the content of the document "build_url": "https://git.pleroma.social/pleroma/fedi-fe/-/jobs/artifacts/${ref}/download?job=build", "git": "https://git.pleroma.social/pleroma/fedi-fe", "installed": true, + "installed_refs": ["master"], "name": "fedi-fe", "ref": "master" }, @@ -1592,6 +1593,7 @@ Returns the content of the document "build_url": "https://git.pleroma.social/lambadalambda/kenoma/-/jobs/artifacts/${ref}/download?job=build", "git": "https://git.pleroma.social/lambadalambda/kenoma", "installed": false, + "installed_refs": [], "name": "kenoma", "ref": "master" } diff --git a/lib/pleroma/bbs/authenticator.ex b/lib/pleroma/bbs/authenticator.ex deleted file mode 100644 index 0f7543ff5..000000000 --- a/lib/pleroma/bbs/authenticator.ex +++ /dev/null @@ -1,20 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.BBS.Authenticator do - use Sshd.PasswordAuthenticator - alias Pleroma.User - alias Pleroma.Web.Plugs.AuthenticationPlug - - def authenticate(username, password) do - username = to_string(username) - password = to_string(password) - - with %User{} = user <- User.get_by_nickname(username) do - AuthenticationPlug.checkpw(password, user.password_hash) - else - _e -> false - end - end -end diff --git a/lib/pleroma/bbs/handler.ex b/lib/pleroma/bbs/handler.ex deleted file mode 100644 index 27799338f..000000000 --- a/lib/pleroma/bbs/handler.ex +++ /dev/null @@ -1,246 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.BBS.Handler do - use Sshd.ShellHandler - alias Pleroma.Activity - alias Pleroma.HTML - alias Pleroma.Web.ActivityPub.ActivityPub - alias Pleroma.Web.CommonAPI - - def on_shell(username, _pubkey, _ip, _port) do - :ok = IO.puts("Welcome to #{Pleroma.Config.get([:instance, :name])}!") - user = Pleroma.User.get_cached_by_nickname(to_string(username)) - Logger.debug("#{inspect(user)}") - loop(run_state(user: user)) - end - - def on_connect(username, ip, port, method) do - Logger.debug(fn -> - """ - Incoming SSH shell #{inspect(self())} requested for #{username} from #{inspect(ip)}:#{inspect(port)} using #{inspect(method)} - """ - end) - end - - def on_disconnect(username, ip, port) do - Logger.debug(fn -> - "Disconnecting SSH shell for #{username} from #{inspect(ip)}:#{inspect(port)}" - end) - end - - defp loop(state) do - self_pid = self() - counter = state.counter - prefix = state.prefix - user = state.user - - input = spawn(fn -> io_get(self_pid, prefix, counter, user.nickname) end) - wait_input(state, input) - end - - def puts_activity(activity) do - status = Pleroma.Web.MastodonAPI.StatusView.render("show.json", %{activity: activity}) - - IO.puts("-- #{status.id} by #{status.account.display_name} (#{status.account.acct})") - - status.content - |> String.split("<br/>") - |> Enum.map(&HTML.strip_tags/1) - |> Enum.map(&HtmlEntities.decode/1) - |> Enum.map(&IO.puts/1) - end - - def puts_notification(activity, user) do - notification = - Pleroma.Web.MastodonAPI.NotificationView.render("show.json", %{ - notification: activity, - for: user - }) - - IO.puts( - "== (#{notification.type}) #{notification.status.id} by #{notification.account.display_name} (#{notification.account.acct})" - ) - - notification.status.content - |> String.split("<br/>") - |> Enum.map(&HTML.strip_tags/1) - |> Enum.map(&HtmlEntities.decode/1) - |> (fn x -> - case x do - [content] -> - "> " <> content - - [head | _tail] -> - # "> " <> hd <> "..." - head - |> String.slice(1, 80) - |> (fn x -> "> " <> x <> "..." end).() - end - end).() - |> IO.puts() - - IO.puts("") - end - - def handle_command(state, "help") do - IO.puts("Available commands:") - IO.puts("help - This help") - IO.puts("home - Show the home timeline") - IO.puts("p <text> - Post the given text") - IO.puts("r <id> <text> - Reply to the post with the given id") - IO.puts("t <id> - Show a thread from the given id") - IO.puts("n - Show notifications") - IO.puts("n read - Mark all notifactions as read") - IO.puts("f <id> - Favourites the post with the given id") - IO.puts("R <id> - Repeat the post with the given id") - IO.puts("quit - Quit") - - state - end - - def handle_command(%{user: user} = state, "r " <> text) do - text = String.trim(text) - [activity_id, rest] = String.split(text, " ", parts: 2) - - with %Activity{} <- Activity.get_by_id(activity_id), - {:ok, _activity} <- - CommonAPI.post(user, %{status: rest, in_reply_to_status_id: activity_id}) do - IO.puts("Replied!") - else - _e -> IO.puts("Could not reply...") - end - - state - end - - def handle_command(%{user: user} = state, "t " <> activity_id) do - with %Activity{} = activity <- Activity.get_by_id(activity_id) do - activities = - ActivityPub.fetch_activities_for_context(activity.data["context"], %{ - blocking_user: user, - user: user, - exclude_id: activity.id - }) - - case activities do - [] -> - activity_id - |> Activity.get_by_id() - |> puts_activity() - - _ -> - activities - |> Enum.reverse() - |> Enum.each(&puts_activity/1) - end - else - _e -> IO.puts("Could not show this thread...") - end - - state - end - - def handle_command(%{user: user} = state, "n read") do - Pleroma.Notification.clear(user) - IO.puts("All notifications were marked as read") - - state - end - - def handle_command(%{user: user} = state, "n") do - user - |> Pleroma.Web.MastodonAPI.MastodonAPI.get_notifications(%{}) - |> Enum.each(&puts_notification(&1, user)) - - state - end - - def handle_command(%{user: user} = state, "p " <> text) do - text = String.trim(text) - - with {:ok, activity} <- CommonAPI.post(user, %{status: text}) do - IO.puts("Posted! ID: #{activity.id}") - else - _e -> IO.puts("Could not post...") - end - - state - end - - def handle_command(%{user: user} = state, "f " <> id) do - id = String.trim(id) - - with %Activity{} = activity <- Activity.get_by_id(id), - {:ok, _activity} <- CommonAPI.favorite(user, activity) do - IO.puts("Favourited!") - else - _e -> IO.puts("Could not Favourite...") - end - - state - end - - def handle_command(state, "home") do - user = state.user - - params = - %{} - |> Map.put(:type, ["Create"]) - |> Map.put(:blocking_user, user) - |> Map.put(:muting_user, user) - |> Map.put(:user, user) - - activities = - [user.ap_id | Pleroma.User.following(user)] - |> ActivityPub.fetch_activities(params) - - Enum.each(activities, fn activity -> - puts_activity(activity) - end) - - state - end - - def handle_command(state, command) do - IO.puts("Unknown command '#{command}'") - state - end - - defp wait_input(state, input) do - receive do - {:input, ^input, "quit\n"} -> - IO.puts("Exiting...") - - {:input, ^input, code} when is_binary(code) -> - code = String.trim(code) - - state = handle_command(state, code) - - loop(%{state | counter: state.counter + 1}) - - {:input, ^input, {:error, :interrupted}} -> - IO.puts("Caught Ctrl+C...") - loop(%{state | counter: state.counter + 1}) - - {:input, ^input, msg} -> - :ok = Logger.warn("received unknown message: #{inspect(msg)}") - loop(%{state | counter: state.counter + 1}) - end - end - - defp run_state(opts) do - %{prefix: "pleroma", counter: 1, user: opts[:user]} - end - - defp io_get(pid, prefix, counter, username) do - prompt = prompt(prefix, counter, username) - send(pid, {:input, self(), IO.gets(:stdio, prompt)}) - end - - defp prompt(prefix, counter, username) do - prompt = "#{username}@#{prefix}:#{counter}>" - prompt <> " " - end -end diff --git a/lib/pleroma/web/admin_api/controllers/frontend_controller.ex b/lib/pleroma/web/admin_api/controllers/frontend_controller.ex index b4dbb82fe..9e2ed4aac 100644 --- a/lib/pleroma/web/admin_api/controllers/frontend_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/frontend_controller.ex @@ -18,13 +18,24 @@ defmodule Pleroma.Web.AdminAPI.FrontendController do def index(conn, _params) do installed = installed() + # FIrst get frontends from config, + # then add frontends that are installed but not in the config frontends = - [:frontends, :available] - |> Config.get([]) + Config.get([:frontends, :available], []) |> Enum.map(fn {name, desc} -> - Map.put(desc, "installed", name in installed) + desc + |> Map.put("installed", name in installed) + |> Map.put("installed_refs", installed_refs(name)) end) + frontends = + frontends ++ + (installed + |> Enum.filter(fn n -> not Enum.any?(frontends, fn f -> f["name"] == n end) end) + |> Enum.map(fn name -> + %{"name" => name, "installed" => true, "installed_refs" => installed_refs(name)} + end)) + render(conn, "index.json", frontends: frontends) end @@ -43,4 +54,12 @@ defmodule Pleroma.Web.AdminAPI.FrontendController do [] end end + + def installed_refs(name) do + if name in installed() do + File.ls!(Path.join(Pleroma.Frontend.dir(), name)) + else + [] + end + end end diff --git a/lib/pleroma/web/admin_api/views/frontend_view.ex b/lib/pleroma/web/admin_api/views/frontend_view.ex index 0ca3d67cb..ae4016581 100644 --- a/lib/pleroma/web/admin_api/views/frontend_view.ex +++ b/lib/pleroma/web/admin_api/views/frontend_view.ex @@ -15,7 +15,8 @@ defmodule Pleroma.Web.AdminAPI.FrontendView do git: frontend["git"], build_url: frontend["build_url"], ref: frontend["ref"], - installed: frontend["installed"] + installed: frontend["installed"], + installed_refs: frontend["installed_refs"] } end end diff --git a/lib/pleroma/web/api_spec/operations/admin/frontend_operation.ex b/lib/pleroma/web/api_spec/operations/admin/frontend_operation.ex index 4bfe5ac5a..3e85c44d2 100644 --- a/lib/pleroma/web/api_spec/operations/admin/frontend_operation.ex +++ b/lib/pleroma/web/api_spec/operations/admin/frontend_operation.ex @@ -51,8 +51,9 @@ defmodule Pleroma.Web.ApiSpec.Admin.FrontendOperation do name: %Schema{type: :string}, git: %Schema{type: :string, format: :uri, nullable: true}, build_url: %Schema{type: :string, format: :uri, nullable: true}, - ref: %Schema{type: :string}, - installed: %Schema{type: :boolean} + ref: %Schema{type: :string, nullable: true}, + installed: %Schema{type: :boolean}, + installed_refs: %Schema{type: :array, items: %Schema{type: :string}} } } } diff --git a/lib/pleroma/web/plugs/uploaded_media.ex b/lib/pleroma/web/plugs/uploaded_media.ex index ad8143234..8b3bc9acb 100644 --- a/lib/pleroma/web/plugs/uploaded_media.ex +++ b/lib/pleroma/web/plugs/uploaded_media.ex @@ -35,9 +35,9 @@ defmodule Pleroma.Web.Plugs.UploadedMedia do conn = case fetch_query_params(conn) do %{query_params: %{"name" => name}} = conn -> - name = String.replace(name, "\"", "\\\"") + name = String.replace(name, ~s["], ~s[\\"]) - put_resp_header(conn, "content-disposition", "filename=\"#{name}\"") + put_resp_header(conn, "content-disposition", ~s[inline; filename="#{name}"]) conn -> conn @@ -78,8 +78,7 @@ defmodule Pleroma.Mixfile do :comeonin, :fast_sanitize, :os_mon, - :ssl, - :esshd + :ssl ], included_applications: [:ex_syslogger] ] @@ -181,7 +180,6 @@ defmodule Pleroma.Mixfile do {:joken, "~> 2.0"}, {:benchee, "~> 1.0"}, {:pot, "~> 1.0"}, - {:esshd, "~> 0.1.0", runtime: Application.get_env(:esshd, :enabled, false)}, {:ex_const, "~> 0.2"}, {:plug_static_index_html, "~> 1.0.0"}, {:flake_id, "~> 0.1.0"}, @@ -35,7 +35,6 @@ "eimp": {:hex, :eimp, "1.0.14", "fc297f0c7e2700457a95a60c7010a5f1dcb768a083b6d53f49cd94ab95a28f22", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "501133f3112079b92d9e22da8b88bf4f0e13d4d67ae9c15c42c30bd25ceb83b6"}, "elixir_make": {:hex, :elixir_make, "0.6.3", "bc07d53221216838d79e03a8019d0839786703129599e9619f4ab74c8c096eac", [:mix], [], "hexpm", "f5cbd651c5678bcaabdbb7857658ee106b12509cd976c2c2fca99688e1daf716"}, "esbuild": {:hex, :esbuild, "0.5.0", "d5bb08ff049d7880ee3609ed5c4b864bd2f46445ea40b16b4acead724fb4c4a3", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "f183a0b332d963c4cfaf585477695ea59eef9a6f2204fdd0efa00e099694ffe5"}, - "esshd": {:hex, :esshd, "0.1.1", "d4dd4c46698093a40a56afecce8a46e246eb35463c457c246dacba2e056f31b5", [:mix], [], "hexpm", "d73e341e3009d390aa36387dc8862860bf9f874c94d9fd92ade2926376f49981"}, "eternal": {:hex, :eternal, "1.2.2", "d1641c86368de99375b98d183042dd6c2b234262b8d08dfd72b9eeaafc2a1abd", [:mix], [], "hexpm", "2c9fe32b9c3726703ba5e1d43a1d255a4f3f2d8f8f9bc19f094c7cb1a7a9e782"}, "ex_aws": {:hex, :ex_aws, "2.1.9", "dc4865ecc20a05190a34a0ac5213e3e5e2b0a75a0c2835e923ae7bfeac5e3c31", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "3e6c776703c9076001fbe1f7c049535f042cb2afa0d2cbd3b47cbc4e92ac0d10"}, "ex_aws_s3": {:hex, :ex_aws_s3, "2.4.0", "ce8decb6b523381812798396bc0e3aaa62282e1b40520125d1f4eff4abdff0f4", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "85dda6e27754d94582869d39cba3241d9ea60b6aa4167f9c88e309dc687e56bb"}, diff --git a/priv/scrubbers/default.ex b/priv/scrubbers/default.ex index e10e3ec87..d1215d2e0 100644 --- a/priv/scrubbers/default.ex +++ b/priv/scrubbers/default.ex @@ -33,35 +33,35 @@ defmodule Pleroma.HTML.Scrubber.Default do "ugc" ]) - Meta.allow_tag_with_these_attributes(:a, ["name", "title"]) - - Meta.allow_tag_with_these_attributes(:abbr, ["title"]) - - Meta.allow_tag_with_these_attributes(:b, []) - Meta.allow_tag_with_these_attributes(:blockquote, []) - Meta.allow_tag_with_these_attributes(:br, []) - Meta.allow_tag_with_these_attributes(:code, []) - Meta.allow_tag_with_these_attributes(:del, []) - Meta.allow_tag_with_these_attributes(:em, []) - Meta.allow_tag_with_these_attributes(:hr, []) - Meta.allow_tag_with_these_attributes(:i, []) - Meta.allow_tag_with_these_attributes(:li, []) - Meta.allow_tag_with_these_attributes(:ol, []) - Meta.allow_tag_with_these_attributes(:p, []) - Meta.allow_tag_with_these_attributes(:pre, []) - Meta.allow_tag_with_these_attributes(:strong, []) - Meta.allow_tag_with_these_attributes(:sub, []) - Meta.allow_tag_with_these_attributes(:sup, []) - Meta.allow_tag_with_these_attributes(:ruby, []) - Meta.allow_tag_with_these_attributes(:rb, []) - Meta.allow_tag_with_these_attributes(:rp, []) - Meta.allow_tag_with_these_attributes(:rt, []) - Meta.allow_tag_with_these_attributes(:rtc, []) - Meta.allow_tag_with_these_attributes(:u, []) - Meta.allow_tag_with_these_attributes(:ul, []) + Meta.allow_tag_with_these_attributes(:a, ["name", "title", "lang"]) + + Meta.allow_tag_with_these_attributes(:abbr, ["title", "lang"]) + + Meta.allow_tag_with_these_attributes(:b, ["lang"]) + Meta.allow_tag_with_these_attributes(:blockquote, ["lang"]) + Meta.allow_tag_with_these_attributes(:br, ["lang"]) + Meta.allow_tag_with_these_attributes(:code, ["lang"]) + Meta.allow_tag_with_these_attributes(:del, ["lang"]) + Meta.allow_tag_with_these_attributes(:em, ["lang"]) + Meta.allow_tag_with_these_attributes(:hr, ["lang"]) + Meta.allow_tag_with_these_attributes(:i, ["lang"]) + Meta.allow_tag_with_these_attributes(:li, ["lang"]) + Meta.allow_tag_with_these_attributes(:ol, ["lang"]) + Meta.allow_tag_with_these_attributes(:p, ["lang"]) + Meta.allow_tag_with_these_attributes(:pre, ["lang"]) + Meta.allow_tag_with_these_attributes(:strong, ["lang"]) + Meta.allow_tag_with_these_attributes(:sub, ["lang"]) + Meta.allow_tag_with_these_attributes(:sup, ["lang"]) + Meta.allow_tag_with_these_attributes(:ruby, ["lang"]) + Meta.allow_tag_with_these_attributes(:rb, ["lang"]) + Meta.allow_tag_with_these_attributes(:rp, ["lang"]) + Meta.allow_tag_with_these_attributes(:rt, ["lang"]) + Meta.allow_tag_with_these_attributes(:rtc, ["lang"]) + Meta.allow_tag_with_these_attributes(:u, ["lang"]) + Meta.allow_tag_with_these_attributes(:ul, ["lang"]) Meta.allow_tag_with_this_attribute_values(:span, "class", ["h-card", "recipients-inline"]) - Meta.allow_tag_with_these_attributes(:span, []) + Meta.allow_tag_with_these_attributes(:span, ["lang"]) Meta.allow_tag_with_this_attribute_values(:code, "class", ["inline"]) @@ -77,29 +77,30 @@ defmodule Pleroma.HTML.Scrubber.Default do "width", "height", "title", - "alt" + "alt", + "lang" ]) end if Pleroma.Config.get([:markup, :allow_tables]) do - Meta.allow_tag_with_these_attributes(:table, []) - Meta.allow_tag_with_these_attributes(:tbody, []) - Meta.allow_tag_with_these_attributes(:td, []) - Meta.allow_tag_with_these_attributes(:th, []) - Meta.allow_tag_with_these_attributes(:thead, []) - Meta.allow_tag_with_these_attributes(:tr, []) + Meta.allow_tag_with_these_attributes(:table, ["lang"]) + Meta.allow_tag_with_these_attributes(:tbody, ["lang"]) + Meta.allow_tag_with_these_attributes(:td, ["lang"]) + Meta.allow_tag_with_these_attributes(:th, ["lang"]) + Meta.allow_tag_with_these_attributes(:thead, ["lang"]) + Meta.allow_tag_with_these_attributes(:tr, ["lang"]) end if Pleroma.Config.get([:markup, :allow_headings]) do - Meta.allow_tag_with_these_attributes(:h1, []) - Meta.allow_tag_with_these_attributes(:h2, []) - Meta.allow_tag_with_these_attributes(:h3, []) - Meta.allow_tag_with_these_attributes(:h4, []) - Meta.allow_tag_with_these_attributes(:h5, []) + Meta.allow_tag_with_these_attributes(:h1, ["lang"]) + Meta.allow_tag_with_these_attributes(:h2, ["lang"]) + Meta.allow_tag_with_these_attributes(:h3, ["lang"]) + Meta.allow_tag_with_these_attributes(:h4, ["lang"]) + Meta.allow_tag_with_these_attributes(:h5, ["lang"]) end if Pleroma.Config.get([:markup, :allow_fonts]) do - Meta.allow_tag_with_these_attributes(:font, ["face"]) + Meta.allow_tag_with_these_attributes(:font, ["face", "lang"]) end Meta.strip_everything_not_covered() diff --git a/test/pleroma/bbs/handler_test.exs b/test/pleroma/bbs/handler_test.exs deleted file mode 100644 index aea3b6ead..000000000 --- a/test/pleroma/bbs/handler_test.exs +++ /dev/null @@ -1,89 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.BBS.HandlerTest do - use Pleroma.DataCase, async: true - alias Pleroma.Activity - alias Pleroma.BBS.Handler - alias Pleroma.Object - alias Pleroma.Repo - alias Pleroma.User - alias Pleroma.Web.CommonAPI - - import ExUnit.CaptureIO - import Pleroma.Factory - import Ecto.Query - - test "getting the home timeline" do - user = insert(:user) - followed = insert(:user) - - {:ok, user, followed} = User.follow(user, followed) - - {:ok, _first} = CommonAPI.post(user, %{status: "hey"}) - {:ok, _second} = CommonAPI.post(followed, %{status: "hello"}) - - output = - capture_io(fn -> - Handler.handle_command(%{user: user}, "home") - end) - - assert output =~ user.nickname - assert output =~ followed.nickname - - assert output =~ "hey" - assert output =~ "hello" - end - - test "posting" do - user = insert(:user) - - output = - capture_io(fn -> - Handler.handle_command(%{user: user}, "p this is a test post") - end) - - assert output =~ "Posted" - - activity = - Repo.one( - from(a in Activity, - where: fragment("?->>'type' = ?", a.data, "Create") - ) - ) - - assert activity.actor == user.ap_id - object = Object.normalize(activity, fetch: false) - assert object.data["content"] == "this is a test post" - end - - test "replying" do - user = insert(:user) - another_user = insert(:user) - - {:ok, activity} = CommonAPI.post(another_user, %{status: "this is a test post"}) - activity_object = Object.normalize(activity, fetch: false) - - output = - capture_io(fn -> - Handler.handle_command(%{user: user}, "r #{activity.id} this is a reply") - end) - - assert output =~ "Replied" - - reply = - Repo.one( - from(a in Activity, - where: fragment("?->>'type' = ?", a.data, "Create"), - where: a.actor == ^user.ap_id - ) - ) - - assert reply.actor == user.ap_id - - reply_object_data = Object.normalize(reply, fetch: false).data - assert reply_object_data["content"] == "this is a reply" - assert reply_object_data["inReplyTo"] == activity_object.data["id"] - end -end diff --git a/test/pleroma/web/admin_api/controllers/config_controller_test.exs b/test/pleroma/web/admin_api/controllers/config_controller_test.exs index 9fb5fb520..19ce3681c 100644 --- a/test/pleroma/web/admin_api/controllers/config_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/config_controller_test.exs @@ -1502,15 +1502,14 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do clear_config(:database_config_whitelist, [ {:pleroma, :instance}, {:pleroma, :activitypub}, - {:pleroma, Pleroma.Upload}, - {:esshd} + {:pleroma, Pleroma.Upload} ]) conn = get(conn, "/api/pleroma/admin/config/descriptions") children = json_response_and_validate_schema(conn, 200) - assert length(children) == 4 + assert length(children) == 3 assert Enum.count(children, fn c -> c["group"] == ":pleroma" end) == 3 @@ -1522,9 +1521,6 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do web_endpoint = Enum.find(children, fn c -> c["key"] == "Pleroma.Upload" end) assert web_endpoint["children"] - - esshd = Enum.find(children, fn c -> c["group"] == ":esshd" end) - assert esshd["children"] end end end diff --git a/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs b/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs index 38a23b224..0d1a4999e 100644 --- a/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs @@ -89,6 +89,7 @@ defmodule Pleroma.Web.AdminAPI.FrontendControllerTest do "build_url" => "http://gensokyo.2hu/builds/${ref}", "git" => nil, "installed" => true, + "installed_refs" => ["fantasy"], "name" => "pleroma", "ref" => "fantasy" } diff --git a/test/pleroma/web/common_api_test.exs b/test/pleroma/web/common_api_test.exs index 5c9103e9f..968d826a2 100644 --- a/test/pleroma/web/common_api_test.exs +++ b/test/pleroma/web/common_api_test.exs @@ -527,6 +527,17 @@ defmodule Pleroma.Web.CommonAPITest do assert Object.tags(object) == ["ساٴينس"] end + test "allows lang attribute" do + user = insert(:user) + text = ~s{<span lang="en">something</span><p lang="diaetuitech_rpyhpgc">random</p>} + + {:ok, activity} = CommonAPI.post(user, %{status: text, content_type: "text/html"}) + + object = Object.normalize(activity, fetch: false) + + assert object.data["content"] == text + end + test "double dot in link is allowed" do user = insert(:user) text = "https://example.to/something..mp3" diff --git a/test/pleroma/web/plugs/uploaded_media_plug_test.exs b/test/pleroma/web/plugs/uploaded_media_plug_test.exs index ec46b0537..8323ff6ab 100644 --- a/test/pleroma/web/plugs/uploaded_media_plug_test.exs +++ b/test/pleroma/web/plugs/uploaded_media_plug_test.exs @@ -33,11 +33,11 @@ defmodule Pleroma.Web.Plugs.UploadedMediaPlugTest do test "sends Content-Disposition header when name param is set", %{ attachment_url: attachment_url } do - conn = get(build_conn(), attachment_url <> "?name=\"cofe\".gif") + conn = get(build_conn(), attachment_url <> ~s[?name="cofe".gif]) assert Enum.any?( conn.resp_headers, - &(&1 == {"content-disposition", "filename=\"\\\"cofe\\\".gif\""}) + &(&1 == {"content-disposition", ~s[inline; filename="\\"cofe\\".gif"]}) ) end end |