Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into unused_indexes
This commit is contained in:
commit
175ee9e6fe
272
.gitlab-ci.yml
272
.gitlab-ci.yml
@ -31,6 +31,7 @@ stages:
|
||||
- deploy
|
||||
- release
|
||||
- docker
|
||||
- docker-combine
|
||||
|
||||
before_script:
|
||||
- echo $MIX_ENV
|
||||
@ -44,28 +45,36 @@ check-changelog:
|
||||
stage: check-changelog
|
||||
image: alpine
|
||||
rules:
|
||||
- if: $CI_MERGE_REQUEST_SOURCE_PROJECT_PATH == 'pleroma/pleroma' && $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == 'weblate-extract'
|
||||
when: never
|
||||
- if: $CI_MERGE_REQUEST_SOURCE_PROJECT_PATH == 'pleroma/pleroma' && $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == 'weblate'
|
||||
when: never
|
||||
- if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop"
|
||||
before_script: ''
|
||||
after_script: ''
|
||||
cache: {}
|
||||
script:
|
||||
- apk add git
|
||||
- sh ./tools/check-changelog
|
||||
|
||||
build:
|
||||
stage: build
|
||||
only:
|
||||
changes: &build_changes_policy
|
||||
.build_changes_policy:
|
||||
rules:
|
||||
- changes:
|
||||
- ".gitlab-ci.yml"
|
||||
- "**/*.ex"
|
||||
- "**/*.exs"
|
||||
- "mix.lock"
|
||||
|
||||
build:
|
||||
extends: .build_changes_policy
|
||||
stage: build
|
||||
script:
|
||||
- mix compile --force
|
||||
|
||||
spec-build:
|
||||
stage: test
|
||||
only:
|
||||
changes:
|
||||
rules:
|
||||
- changes:
|
||||
- ".gitlab-ci.yml"
|
||||
- "lib/pleroma/web/api_spec/**/*.ex"
|
||||
- "lib/pleroma/web/api_spec.ex"
|
||||
@ -90,9 +99,8 @@ benchmark:
|
||||
- mix pleroma.load_testing
|
||||
|
||||
unit-testing:
|
||||
extends: .build_changes_policy
|
||||
stage: test
|
||||
only:
|
||||
changes: *build_changes_policy
|
||||
cache: &testing_cache_policy
|
||||
<<: *global_cache_policy
|
||||
policy: pull
|
||||
@ -113,11 +121,10 @@ unit-testing:
|
||||
path: coverage.xml
|
||||
|
||||
unit-testing-erratic:
|
||||
extends: .build_changes_policy
|
||||
stage: test
|
||||
retry: 2
|
||||
allow_failure: true
|
||||
only:
|
||||
changes: *build_changes_policy
|
||||
cache: &testing_cache_policy
|
||||
<<: *global_cache_policy
|
||||
policy: pull
|
||||
@ -148,9 +155,8 @@ unit-testing-erratic:
|
||||
# - mix test --trace --only federated
|
||||
|
||||
unit-testing-rum:
|
||||
extends: .build_changes_policy
|
||||
stage: test
|
||||
only:
|
||||
changes: *build_changes_policy
|
||||
cache: *testing_cache_policy
|
||||
services:
|
||||
- name: minibikini/postgres-with-rum:12
|
||||
@ -166,10 +172,9 @@ unit-testing-rum:
|
||||
- mix test --preload-modules
|
||||
|
||||
lint:
|
||||
extends: .build_changes_policy
|
||||
image: ¤t_elixir elixir:1.12-alpine
|
||||
stage: test
|
||||
only:
|
||||
changes: *build_changes_policy
|
||||
cache: *testing_cache_policy
|
||||
before_script: ¤t_bfr_script
|
||||
- apk update
|
||||
@ -181,18 +186,16 @@ lint:
|
||||
- mix format --check-formatted
|
||||
|
||||
analysis:
|
||||
extends: .build_changes_policy
|
||||
stage: test
|
||||
only:
|
||||
changes: *build_changes_policy
|
||||
cache: *testing_cache_policy
|
||||
script:
|
||||
- mix credo --strict --only=warnings,todo,fixme,consistency,readability
|
||||
|
||||
cycles:
|
||||
extends: .build_changes_policy
|
||||
image: *current_elixir
|
||||
stage: test
|
||||
only:
|
||||
changes: *build_changes_policy
|
||||
cache: {}
|
||||
before_script: *current_bfr_script
|
||||
script:
|
||||
@ -373,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
|
||||
script:
|
||||
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
|
||||
.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
|
||||
|
||||
docker-adhoc:
|
||||
stage: docker
|
||||
image: docker:latest
|
||||
cache: {}
|
||||
dependencies: []
|
||||
variables: *docker-variables
|
||||
before_script: *before-docker
|
||||
allow_failure: true
|
||||
script:
|
||||
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
|
||||
.kaniko-adhoc:
|
||||
extends: .kaniko
|
||||
only:
|
||||
- /^build-docker/.*$/@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:linux/amd64:
|
||||
variables:
|
||||
BUILD_ARCH: linux/amd64
|
||||
BUILD_ARCH_IMG_SUFFIX: linux-amd64
|
||||
ELIXIR_IMG: hexpm/elixir
|
||||
tags:
|
||||
- amd64
|
||||
|
||||
.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: {}
|
||||
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:
|
||||
- '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:
|
||||
- /^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'
|
||||
|
10
.gitlab/merge_request_templates/Default.md
Normal file
10
.gitlab/merge_request_templates/Default.md
Normal file
@ -0,0 +1,10 @@
|
||||
### Checklist
|
||||
- [ ] Adding a changelog: In the `changelog.d` directory, create a file named `<code>.<type>`.
|
||||
|
||||
`<code>` can be anything, but we recommend using a more or less unique identifier to avoid collisions, such as the branch name.
|
||||
|
||||
`<type>` can be `add`, `remove`, `fix`, `security` or `skip`. `skip` is only used if there is no user-visible change in the MR (for example, only editing comments in the code). Otherwise, choose a type that corresponds to your change.
|
||||
|
||||
In the file, write the changelog entry. For example, if an MR adds group functionality, we can create a file named `group.add` and write `Add group functionality` in it.
|
||||
|
||||
If one changelog entry is not enough, you may add more. But that might mean you can split it into two MRs. Only use more than one changelog entry if you really need to (for example, when one change in the code fix two different bugs, or when refactoring).
|
20
CHANGELOG.md
20
CHANGELOG.md
@ -18,6 +18,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
### Removed
|
||||
- BREAKING: Support for passwords generated with `crypt(3)` (Gnu Social migration artifact)
|
||||
|
||||
## 2.5.2
|
||||
|
||||
### Security
|
||||
- `/proxy` endpoint now sets a Content-Security-Policy (sandbox)
|
||||
- WebSocket endpoint now respects unauthenticated restrictions for streams of public posts
|
||||
- OEmbed HTML tags are now filtered
|
||||
|
||||
### Changed
|
||||
- docs: Be more explicit about the level of compatibility of OTP releases
|
||||
- Set default background worker timeout to 15 minutes
|
||||
|
||||
### Fixed
|
||||
- Atom/RSS formatting (HTML truncation, published, missing summary)
|
||||
- Remove `static_fe` pipeline for `/users/:nickname/feed`
|
||||
- Stop oban from retrying if validating errors occur when processing incoming data
|
||||
- Make sure object refetching as used by already received polls follows MRF rules
|
||||
|
||||
### Removed
|
||||
- BREAKING: Support for passwords generated with `crypt(3)` (Gnu Social migration artifact)
|
||||
|
||||
## 2.5.1
|
||||
|
||||
### Added
|
||||
|
@ -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 . .
|
||||
|
||||
|
1
changelog.d/3126.fix
Normal file
1
changelog.d/3126.fix
Normal file
@ -0,0 +1 @@
|
||||
MediaProxy responses now return a sandbox CSP header
|
0
changelog.d/3831.skip
Normal file
0
changelog.d/3831.skip
Normal file
1
changelog.d/3848.add
Normal file
1
changelog.d/3848.add
Normal file
@ -0,0 +1 @@
|
||||
Add OAuth scope descriptions
|
0
changelog.d/3870.skip
Normal file
0
changelog.d/3870.skip
Normal file
1
changelog.d/3872.remove
Normal file
1
changelog.d/3872.remove
Normal file
@ -0,0 +1 @@
|
||||
remove BBS/SSH feature, replaced by an external bridge.
|
1
changelog.d/3873.fix
Normal file
1
changelog.d/3873.fix
Normal file
@ -0,0 +1 @@
|
||||
UploadedMedia: Add missing disposition_type to Content-Disposition
|
0
changelog.d/3876.skip
Normal file
0
changelog.d/3876.skip
Normal file
0
changelog.d/3877.skip
Normal file
0
changelog.d/3877.skip
Normal file
0
changelog.d/3878.skip
Normal file
0
changelog.d/3878.skip
Normal file
1
changelog.d/3880.remove
Normal file
1
changelog.d/3880.remove
Normal file
@ -0,0 +1 @@
|
||||
Cleanup OStatus-era user upgrades and ap_enabled indicator
|
1
changelog.d/3882.add
Normal file
1
changelog.d/3882.add
Normal file
@ -0,0 +1 @@
|
||||
Allow lang attribute in status text
|
1
changelog.d/3883.fix
Normal file
1
changelog.d/3883.fix
Normal file
@ -0,0 +1 @@
|
||||
Fix abnormal behaviour when refetching a poll
|
1
changelog.d/3884.fix
Normal file
1
changelog.d/3884.fix
Normal file
@ -0,0 +1 @@
|
||||
Allow non-HTTP(s) URIs in "url" fields for compatibility with "FEP-fffd: Proxy Objects"
|
1
changelog.d/3885.fix
Normal file
1
changelog.d/3885.fix
Normal file
@ -0,0 +1 @@
|
||||
Fix opengraph and twitter card meta tags
|
1
changelog.d/3891.fix
Normal file
1
changelog.d/3891.fix
Normal file
@ -0,0 +1 @@
|
||||
OEmbed HTML tags are now filtered
|
0
changelog.d/3893.skip
Normal file
0
changelog.d/3893.skip
Normal file
1
changelog.d/3896.add
Normal file
1
changelog.d/3896.add
Normal file
@ -0,0 +1 @@
|
||||
Validate Host header for Uploads and return a 302 if the base_url has changed
|
1
changelog.d/3897.add
Normal file
1
changelog.d/3897.add
Normal file
@ -0,0 +1 @@
|
||||
OnlyMedia Upload Filter
|
0
changelog.d/3899.skip
Normal file
0
changelog.d/3899.skip
Normal file
1
changelog.d/3901.security
Normal file
1
changelog.d/3901.security
Normal file
@ -0,0 +1 @@
|
||||
Preload: Make generated JSON html-safe. It already was html safe because it only consists of config data that is base64 encoded, but this will keep it safe it that ever changes.
|
0
changelog.d/3902.skip
Normal file
0
changelog.d/3902.skip
Normal file
0
changelog.d/changelog-improve.skip
Normal file
0
changelog.d/changelog-improve.skip
Normal file
0
changelog.d/distro-docs-elixir-1.11.skip
Normal file
0
changelog.d/distro-docs-elixir-1.11.skip
Normal file
1
changelog.d/fix-object-test.fix
Normal file
1
changelog.d/fix-object-test.fix
Normal file
@ -0,0 +1 @@
|
||||
Correctly handle the situation when a poll has both "anyOf" and "oneOf" but one of them being empty
|
@ -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()
|
||||
|
@ -2628,45 +2628,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",
|
||||
|
@ -671,6 +671,12 @@ This filter reads the ImageDescription and iptc:Caption-Abstract fields with Exi
|
||||
|
||||
No specific configuration.
|
||||
|
||||
#### Pleroma.Upload.Filter.OnlyMedia
|
||||
|
||||
This filter rejects uploads that are not identified with Content-Type matching audio/\*, image/\*, or video/\*
|
||||
|
||||
No specific configuration.
|
||||
|
||||
#### Pleroma.Upload.Filter.Mogrify
|
||||
|
||||
* `args`: List of actions for the `mogrify` command like `"strip"` or `["strip", "auto-orient", {"implode", "1"}]`.
|
||||
@ -873,21 +879,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
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
## Installation
|
||||
|
||||
This guide will assume you are on Debian 11 (“bullseye”) or later. This guide should also work with Ubuntu 18.04 (“Bionic Beaver”) and later. It also assumes that you have administrative rights, either as root or a user with [sudo permissions](https://www.digitalocean.com/community/tutorials/how-to-add-delete-and-grant-sudo-privileges-to-users-on-a-debian-vps). If you want to run this guide with root, ignore the `sudo` at the beginning of the lines, unless it calls a user like `sudo -Hu pleroma`; in this case, use `su <username> -s $SHELL -c 'command'` instead.
|
||||
This guide will assume you are on Debian 12 (“bookworm”) or later. This guide should also work with Ubuntu 22.04 (“jammy”) and later. It also assumes that you have administrative rights, either as root or a user with [sudo permissions](https://www.digitalocean.com/community/tutorials/how-to-add-delete-and-grant-sudo-privileges-to-users-on-a-debian-vps). If you want to run this guide with root, ignore the `sudo` at the beginning of the lines, unless it calls a user like `sudo -Hu pleroma`; in this case, use `su <username> -s $SHELL -c 'command'` instead.
|
||||
|
||||
{! backend/installation/generic_dependencies.include !}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
## インストール
|
||||
|
||||
このガイドはDebian Stretchを利用することを想定しています。Ubuntu 16.04や18.04でもおそらく動作します。また、ユーザはrootもしくはsudoにより管理者権限を持っていることを前提とします。もし、以下の操作をrootユーザで行う場合は、 `sudo` を無視してください。ただし、`sudo -Hu pleroma` のようにユーザを指定している場合には `su <username> -s $SHELL -c 'command'` を代わりに使ってください。
|
||||
このガイドはDebian Bookwormを利用することを想定しています。Ubuntu 22.04でもおそらく動作します。また、ユーザはrootもしくはsudoにより管理者権限を持っていることを前提とします。もし、以下の操作をrootユーザで行う場合は、 `sudo` を無視してください。ただし、`sudo -Hu pleroma` のようにユーザを指定している場合には `su <username> -s $SHELL -c 'command'` を代わりに使ってください。
|
||||
|
||||
### 必要なソフトウェア
|
||||
|
||||
|
@ -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
|
@ -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
|
@ -0,0 +1,23 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.BareUri do
|
||||
use Ecto.Type
|
||||
|
||||
def type, do: :string
|
||||
|
||||
def cast(uri) when is_binary(uri) do
|
||||
case URI.parse(uri) do
|
||||
%URI{scheme: nil} -> :error
|
||||
%URI{} -> {:ok, uri}
|
||||
_ -> :error
|
||||
end
|
||||
end
|
||||
|
||||
def cast(_), do: :error
|
||||
|
||||
def dump(data), do: {:ok, data}
|
||||
|
||||
def load(data), do: {:ok, data}
|
||||
end
|
@ -8,77 +8,30 @@ defmodule Pleroma.Object.Fetcher do
|
||||
alias Pleroma.Maps
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Object.Containment
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Signature
|
||||
alias Pleroma.Web.ActivityPub.InternalFetchActor
|
||||
alias Pleroma.Web.ActivityPub.MRF
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidator
|
||||
alias Pleroma.Web.ActivityPub.Pipeline
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.Federator
|
||||
|
||||
require Logger
|
||||
require Pleroma.Constants
|
||||
|
||||
defp touch_changeset(changeset) do
|
||||
updated_at =
|
||||
NaiveDateTime.utc_now()
|
||||
|> NaiveDateTime.truncate(:second)
|
||||
|
||||
Ecto.Changeset.put_change(changeset, :updated_at, updated_at)
|
||||
end
|
||||
|
||||
defp maybe_reinject_internal_fields(%{data: %{} = old_data}, new_data) do
|
||||
has_history? = fn
|
||||
%{"formerRepresentations" => %{"orderedItems" => list}} when is_list(list) -> true
|
||||
_ -> false
|
||||
end
|
||||
|
||||
internal_fields = Map.take(old_data, Pleroma.Constants.object_internal_fields())
|
||||
|
||||
remote_history_exists? = has_history?.(new_data)
|
||||
|
||||
# If the remote history exists, we treat that as the only source of truth.
|
||||
new_data =
|
||||
if has_history?.(old_data) and not remote_history_exists? do
|
||||
Map.put(new_data, "formerRepresentations", old_data["formerRepresentations"])
|
||||
else
|
||||
new_data
|
||||
end
|
||||
|
||||
# If the remote does not have history information, we need to manage it ourselves
|
||||
new_data =
|
||||
if not remote_history_exists? do
|
||||
changed? =
|
||||
Pleroma.Constants.status_updatable_fields()
|
||||
|> Enum.any?(fn field -> Map.get(old_data, field) != Map.get(new_data, field) end)
|
||||
|
||||
%{updated_object: updated_object} =
|
||||
new_data
|
||||
|> Object.Updater.maybe_update_history(old_data,
|
||||
updated: changed?,
|
||||
use_history_in_new_object?: false
|
||||
)
|
||||
|
||||
updated_object
|
||||
else
|
||||
new_data
|
||||
end
|
||||
|
||||
Map.merge(new_data, internal_fields)
|
||||
end
|
||||
|
||||
defp maybe_reinject_internal_fields(_, new_data), do: new_data
|
||||
|
||||
@spec reinject_object(struct(), map()) :: {:ok, Object.t()} | {:error, any()}
|
||||
defp reinject_object(%Object{data: %{"type" => "Question"}} = object, new_data) do
|
||||
defp reinject_object(%Object{data: %{}} = object, new_data) do
|
||||
Logger.debug("Reinjecting object #{new_data["id"]}")
|
||||
|
||||
with data <- maybe_reinject_internal_fields(object, new_data),
|
||||
{:ok, data, _} <- ObjectValidator.validate(data, %{}),
|
||||
changeset <- Object.change(object, %{data: data}),
|
||||
changeset <- touch_changeset(changeset),
|
||||
{:ok, object} <- Repo.insert_or_update(changeset),
|
||||
{:ok, object} <- Object.set_cache(object) do
|
||||
{:ok, object}
|
||||
with {:ok, new_data, _} <- ObjectValidator.validate(new_data, %{}),
|
||||
{:ok, new_data} <- MRF.filter(new_data),
|
||||
{:ok, new_object, _} <-
|
||||
Object.Updater.do_update_and_invalidate_cache(
|
||||
object,
|
||||
new_data,
|
||||
_touch_changeset? = true
|
||||
) do
|
||||
{:ok, new_object}
|
||||
else
|
||||
e ->
|
||||
Logger.error("Error while processing object: #{inspect(e)}")
|
||||
@ -86,20 +39,11 @@ defmodule Pleroma.Object.Fetcher do
|
||||
end
|
||||
end
|
||||
|
||||
defp reinject_object(%Object{} = object, new_data) do
|
||||
Logger.debug("Reinjecting object #{new_data["id"]}")
|
||||
|
||||
with new_data <- Transmogrifier.fix_object(new_data),
|
||||
data <- maybe_reinject_internal_fields(object, new_data),
|
||||
changeset <- Object.change(object, %{data: data}),
|
||||
changeset <- touch_changeset(changeset),
|
||||
{:ok, object} <- Repo.insert_or_update(changeset),
|
||||
{:ok, object} <- Object.set_cache(object) do
|
||||
defp reinject_object(_, new_data) do
|
||||
with {:ok, object, _} <- Pipeline.common_pipeline(new_data, local: false) do
|
||||
{:ok, object}
|
||||
else
|
||||
e ->
|
||||
Logger.error("Error while processing object: #{inspect(e)}")
|
||||
{:error, e}
|
||||
e -> e
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -5,6 +5,9 @@
|
||||
defmodule Pleroma.Object.Updater do
|
||||
require Pleroma.Constants
|
||||
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
|
||||
def update_content_fields(orig_object_data, updated_object) do
|
||||
Pleroma.Constants.status_updatable_fields()
|
||||
|> Enum.reduce(
|
||||
@ -97,12 +100,14 @@ defmodule Pleroma.Object.Updater do
|
||||
end
|
||||
|
||||
defp maybe_update_poll(to_be_updated, updated_object) do
|
||||
choice_key = fn data ->
|
||||
if Map.has_key?(data, "anyOf"), do: "anyOf", else: "oneOf"
|
||||
choice_key = fn
|
||||
%{"anyOf" => [_ | _]} -> "anyOf"
|
||||
%{"oneOf" => [_ | _]} -> "oneOf"
|
||||
_ -> nil
|
||||
end
|
||||
|
||||
with true <- to_be_updated["type"] == "Question",
|
||||
key <- choice_key.(updated_object),
|
||||
key when not is_nil(key) <- choice_key.(updated_object),
|
||||
true <- key == choice_key.(to_be_updated),
|
||||
orig_choices <- to_be_updated[key] |> Enum.map(&Map.drop(&1, ["replies"])),
|
||||
new_choices <- updated_object[key] |> Enum.map(&Map.drop(&1, ["replies"])),
|
||||
@ -237,4 +242,49 @@ defmodule Pleroma.Object.Updater do
|
||||
{:history_items, e} -> e
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_touch_changeset(changeset, true) do
|
||||
updated_at =
|
||||
NaiveDateTime.utc_now()
|
||||
|> NaiveDateTime.truncate(:second)
|
||||
|
||||
Ecto.Changeset.put_change(changeset, :updated_at, updated_at)
|
||||
end
|
||||
|
||||
defp maybe_touch_changeset(changeset, _), do: changeset
|
||||
|
||||
def do_update_and_invalidate_cache(orig_object, updated_object, touch_changeset? \\ false) do
|
||||
orig_object_ap_id = updated_object["id"]
|
||||
orig_object_data = orig_object.data
|
||||
|
||||
%{
|
||||
updated_data: updated_object_data,
|
||||
updated: updated,
|
||||
used_history_in_new_object?: used_history_in_new_object?
|
||||
} = make_new_object_data_from_update_object(orig_object_data, updated_object)
|
||||
|
||||
changeset =
|
||||
orig_object
|
||||
|> Repo.preload(:hashtags)
|
||||
|> Object.change(%{data: updated_object_data})
|
||||
|> maybe_touch_changeset(touch_changeset?)
|
||||
|
||||
with {:ok, new_object} <- Repo.update(changeset),
|
||||
{:ok, _} <- Object.invalid_object_cache(new_object),
|
||||
{:ok, _} <- Object.set_cache(new_object),
|
||||
# The metadata/utils.ex uses the object id for the cache.
|
||||
{:ok, _} <- Pleroma.Activity.HTML.invalidate_cache_for(new_object.id) do
|
||||
if used_history_in_new_object? do
|
||||
with create_activity when not is_nil(create_activity) <-
|
||||
Pleroma.Activity.get_create_by_object_ap_id(orig_object_ap_id),
|
||||
{:ok, _} <- Pleroma.Activity.HTML.invalidate_cache_for(create_activity.id) do
|
||||
nil
|
||||
else
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
|
||||
{:ok, new_object, updated}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -38,9 +38,9 @@ defmodule Pleroma.Upload.Filter do
|
||||
{:ok, :noop} ->
|
||||
filter(rest, upload)
|
||||
|
||||
error ->
|
||||
Logger.error("#{__MODULE__}: Filter #{filter} failed: #{inspect(error)}")
|
||||
error
|
||||
{:error, e} ->
|
||||
Logger.error("#{__MODULE__}: Filter #{filter} failed: #{inspect(e)}")
|
||||
{:error, e}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
20
lib/pleroma/upload/filter/only_media.ex
Normal file
20
lib/pleroma/upload/filter/only_media.ex
Normal file
@ -0,0 +1,20 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Upload.Filter.OnlyMedia do
|
||||
@behaviour Pleroma.Upload.Filter
|
||||
alias Pleroma.Upload
|
||||
|
||||
def filter(%Upload{content_type: content_type}) do
|
||||
[type, _subtype] = String.split(content_type, "/")
|
||||
|
||||
if type in ["image", "video", "audio"] do
|
||||
{:ok, :noop}
|
||||
else
|
||||
{:error, "Disallowed content-type: #{content_type}"}
|
||||
end
|
||||
end
|
||||
|
||||
def filter(_), do: {:ok, :noop}
|
||||
end
|
@ -124,7 +124,6 @@ defmodule Pleroma.User do
|
||||
field(:domain_blocks, {:array, :string}, default: [])
|
||||
field(:is_active, :boolean, default: true)
|
||||
field(:no_rich_text, :boolean, default: false)
|
||||
field(:ap_enabled, :boolean, default: false)
|
||||
field(:is_moderator, :boolean, default: false)
|
||||
field(:is_admin, :boolean, default: false)
|
||||
field(:show_role, :boolean, default: true)
|
||||
@ -488,7 +487,6 @@ defmodule Pleroma.User do
|
||||
:nickname,
|
||||
:public_key,
|
||||
:avatar,
|
||||
:ap_enabled,
|
||||
:banner,
|
||||
:is_locked,
|
||||
:last_refreshed_at,
|
||||
@ -1061,12 +1059,8 @@ defmodule Pleroma.User do
|
||||
end
|
||||
|
||||
def maybe_direct_follow(%User{} = follower, %User{} = followed) do
|
||||
if not ap_enabled?(followed) do
|
||||
follow(follower, followed)
|
||||
else
|
||||
{:ok, follower, followed}
|
||||
end
|
||||
end
|
||||
|
||||
@doc "A mass follow for local users. Respects blocks in both directions but does not create activities."
|
||||
@spec follow_all(User.t(), list(User.t())) :: {atom(), User.t()}
|
||||
@ -1898,7 +1892,6 @@ defmodule Pleroma.User do
|
||||
confirmation_token: nil,
|
||||
domain_blocks: [],
|
||||
is_active: false,
|
||||
ap_enabled: false,
|
||||
is_moderator: false,
|
||||
is_admin: false,
|
||||
mascot: nil,
|
||||
@ -2151,10 +2144,6 @@ defmodule Pleroma.User do
|
||||
end
|
||||
end
|
||||
|
||||
def ap_enabled?(%User{local: true}), do: true
|
||||
def ap_enabled?(%User{ap_enabled: ap_enabled}), do: ap_enabled
|
||||
def ap_enabled?(_), do: false
|
||||
|
||||
@doc "Gets or fetch a user by uri or nickname."
|
||||
@spec get_or_fetch(String.t()) :: {:ok, User.t()} | {:error, String.t()}
|
||||
def get_or_fetch("http://" <> _host = uri), do: get_or_fetch_by_ap_id(uri)
|
||||
|
@ -1547,7 +1547,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||
%{
|
||||
ap_id: data["id"],
|
||||
uri: get_actor_url(data["url"]),
|
||||
ap_enabled: true,
|
||||
banner: normalize_image(data["image"]),
|
||||
fields: fields,
|
||||
emoji: emojis,
|
||||
@ -1668,7 +1667,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_and_prepare_user_from_ap_id(ap_id, additional \\ []) do
|
||||
defp fetch_and_prepare_user_from_ap_id(ap_id, additional) do
|
||||
with {:ok, data} <- Fetcher.fetch_and_contain_remote_object_from_id(ap_id),
|
||||
{:ok, data} <- user_data_from_user_object(data, additional) do
|
||||
{:ok, maybe_update_follow_information(data)}
|
||||
@ -1751,9 +1750,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||
def make_user_from_ap_id(ap_id, additional \\ []) do
|
||||
user = User.get_cached_by_ap_id(ap_id)
|
||||
|
||||
if user && !User.ap_enabled?(user) do
|
||||
Transmogrifier.upgrade_user_from_ap_id(ap_id)
|
||||
else
|
||||
with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id, additional) do
|
||||
{:ok, _pid} = Task.start(fn -> pinned_fetch_task(data) end)
|
||||
|
||||
@ -1771,7 +1767,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def make_user_from_nickname(nickname) do
|
||||
with {:ok, %{"ap_id" => ap_id, "subject" => "acct:" <> acct}} when not is_nil(ap_id) <-
|
||||
|
@ -73,6 +73,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AddRemoveValidator do
|
||||
end
|
||||
|
||||
defp maybe_refetch_user(%User{ap_id: ap_id}) do
|
||||
Pleroma.Web.ActivityPub.Transmogrifier.upgrade_user_from_ap_id(ap_id)
|
||||
# Maybe it could use User.get_or_fetch_by_ap_id to avoid refreshing too often
|
||||
User.fetch_by_ap_id(ap_id)
|
||||
end
|
||||
end
|
||||
|
@ -58,7 +58,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFields do
|
||||
field(:like_count, :integer, default: 0)
|
||||
field(:announcement_count, :integer, default: 0)
|
||||
field(:inReplyTo, ObjectValidators.ObjectID)
|
||||
field(:url, ObjectValidators.Uri)
|
||||
field(:url, ObjectValidators.BareUri)
|
||||
|
||||
field(:likes, {:array, ObjectValidators.ObjectID}, default: [])
|
||||
field(:announcements, {:array, ObjectValidators.ObjectID}, default: [])
|
||||
|
@ -68,6 +68,12 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.TagValidator do
|
||||
|> validate_required([:type, :name, :icon])
|
||||
end
|
||||
|
||||
def changeset(struct, %{"type" => _} = data) do
|
||||
struct
|
||||
|> cast(data, [])
|
||||
|> Map.put(:action, :ignore)
|
||||
end
|
||||
|
||||
def icon_changeset(struct, data) do
|
||||
struct
|
||||
|> cast(data, [:type, :url])
|
||||
|
@ -199,7 +199,6 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
||||
|
||||
inboxes =
|
||||
recipients
|
||||
|> Enum.filter(&User.ap_enabled?/1)
|
||||
|> Enum.map(fn actor -> actor.inbox end)
|
||||
|> Enum.filter(fn inbox -> should_federate?(inbox, public) end)
|
||||
|> Instances.filter_reachable()
|
||||
@ -241,7 +240,6 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
||||
json = Jason.encode!(data)
|
||||
|
||||
recipients(actor, activity)
|
||||
|> Enum.filter(fn user -> User.ap_enabled?(user) end)
|
||||
|> Enum.map(fn %User{} = user ->
|
||||
determine_inbox(activity, user)
|
||||
end)
|
||||
|
@ -428,31 +428,8 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
||||
end
|
||||
|
||||
if orig_object_data["type"] in Pleroma.Constants.updatable_object_types() do
|
||||
%{
|
||||
updated_data: updated_object_data,
|
||||
updated: updated,
|
||||
used_history_in_new_object?: used_history_in_new_object?
|
||||
} = Object.Updater.make_new_object_data_from_update_object(orig_object_data, updated_object)
|
||||
|
||||
changeset =
|
||||
orig_object
|
||||
|> Repo.preload(:hashtags)
|
||||
|> Object.change(%{data: updated_object_data})
|
||||
|
||||
with {:ok, new_object} <- Repo.update(changeset),
|
||||
{:ok, _} <- Object.invalid_object_cache(new_object),
|
||||
{:ok, _} <- Object.set_cache(new_object),
|
||||
# The metadata/utils.ex uses the object id for the cache.
|
||||
{:ok, _} <- Pleroma.Activity.HTML.invalidate_cache_for(new_object.id) do
|
||||
if used_history_in_new_object? do
|
||||
with create_activity when not is_nil(create_activity) <-
|
||||
Pleroma.Activity.get_create_by_object_ap_id(orig_object_ap_id),
|
||||
{:ok, _} <- Pleroma.Activity.HTML.invalidate_cache_for(create_activity.id) do
|
||||
nil
|
||||
else
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
{:ok, _, updated} =
|
||||
Object.Updater.do_update_and_invalidate_cache(orig_object, updated_object)
|
||||
|
||||
if updated do
|
||||
object
|
||||
@ -460,7 +437,6 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
||||
|> ActivityPub.notify_and_stream()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
{:ok, object, meta}
|
||||
end
|
||||
|
@ -20,7 +20,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.Federator
|
||||
alias Pleroma.Workers.TransmogrifierWorker
|
||||
|
||||
import Ecto.Query
|
||||
|
||||
@ -946,47 +945,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
|
||||
defp strip_internal_tags(object), do: object
|
||||
|
||||
def perform(:user_upgrade, user) do
|
||||
# we pass a fake user so that the followers collection is stripped away
|
||||
old_follower_address = User.ap_followers(%User{nickname: user.nickname})
|
||||
|
||||
from(
|
||||
a in Activity,
|
||||
where: ^old_follower_address in a.recipients,
|
||||
update: [
|
||||
set: [
|
||||
recipients:
|
||||
fragment(
|
||||
"array_replace(?,?,?)",
|
||||
a.recipients,
|
||||
^old_follower_address,
|
||||
^user.follower_address
|
||||
)
|
||||
]
|
||||
]
|
||||
)
|
||||
|> Repo.update_all([])
|
||||
end
|
||||
|
||||
def upgrade_user_from_ap_id(ap_id) do
|
||||
with %User{local: false} = user <- User.get_cached_by_ap_id(ap_id),
|
||||
{:ok, data} <- ActivityPub.fetch_and_prepare_user_from_ap_id(ap_id),
|
||||
{:ok, user} <- update_user(user, data) do
|
||||
{:ok, _pid} = Task.start(fn -> ActivityPub.pinned_fetch_task(user) end)
|
||||
TransmogrifierWorker.enqueue("user_upgrade", %{"user_id" => user.id})
|
||||
{:ok, user}
|
||||
else
|
||||
%User{} = user -> {:ok, user}
|
||||
e -> e
|
||||
end
|
||||
end
|
||||
|
||||
defp update_user(user, data) do
|
||||
user
|
||||
|> User.remote_user_changeset(data)
|
||||
|> User.update_and_set_cache()
|
||||
end
|
||||
|
||||
def maybe_fix_user_url(%{"url" => url} = data) when is_map(url) do
|
||||
Map.put(data, "url", url["href"])
|
||||
end
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
82
lib/pleroma/web/api_spec/scopes/compiler.ex
Normal file
82
lib/pleroma/web/api_spec/scopes/compiler.ex
Normal file
@ -0,0 +1,82 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ApiSpec.Scopes.Compiler do
|
||||
defmacro __before_compile__(_env) do
|
||||
strings = __MODULE__.extract_all_scopes()
|
||||
|
||||
quote do
|
||||
def placeholder do
|
||||
unquote do
|
||||
Enum.map(
|
||||
strings,
|
||||
fn string ->
|
||||
quote do
|
||||
Pleroma.Web.Gettext.dgettext_noop(
|
||||
"oauth_scopes",
|
||||
unquote(string)
|
||||
)
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def extract_all_scopes do
|
||||
extract_all_scopes_from(Pleroma.Web.ApiSpec.spec())
|
||||
end
|
||||
|
||||
def extract_all_scopes_from(specs) do
|
||||
specs.paths
|
||||
|> Enum.reduce([], fn
|
||||
{_path, %{} = path_item}, acc ->
|
||||
extract_routes(path_item)
|
||||
|> Enum.flat_map(fn operation -> process_operation(operation) end)
|
||||
|> Kernel.++(acc)
|
||||
|
||||
{_, _}, acc ->
|
||||
acc
|
||||
end)
|
||||
|> Enum.uniq()
|
||||
end
|
||||
|
||||
defp extract_routes(path_item) do
|
||||
path_item
|
||||
|> Map.from_struct()
|
||||
|> Enum.map(fn {_method, path_item} -> path_item end)
|
||||
|> Enum.filter(fn
|
||||
%OpenApiSpex.Operation{} = _operation -> true
|
||||
_ -> false
|
||||
end)
|
||||
end
|
||||
|
||||
defp process_operation(operation) do
|
||||
operation.security
|
||||
|> Kernel.||([])
|
||||
|> Enum.flat_map(fn
|
||||
%{"oAuth" => scopes} -> process_scopes(scopes)
|
||||
_ -> []
|
||||
end)
|
||||
end
|
||||
|
||||
defp process_scopes(scopes) do
|
||||
scopes
|
||||
|> Enum.flat_map(fn scope ->
|
||||
process_scope(scope)
|
||||
end)
|
||||
end
|
||||
|
||||
def process_scope(scope) do
|
||||
hierarchy = String.split(scope, ":")
|
||||
|
||||
{_, list} =
|
||||
Enum.reduce(hierarchy, {"", []}, fn comp, {cur, list} ->
|
||||
{cur <> comp <> ":", [cur <> comp | list]}
|
||||
end)
|
||||
|
||||
list
|
||||
end
|
||||
end
|
10
lib/pleroma/web/api_spec/scopes/translator.ex
Normal file
10
lib/pleroma/web/api_spec/scopes/translator.ex
Normal file
@ -0,0 +1,10 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ApiSpec.Scopes.Translator do
|
||||
require Pleroma.Web.ApiSpec.Scopes.Compiler
|
||||
require Pleroma.Web.Gettext
|
||||
|
||||
@before_compile Pleroma.Web.ApiSpec.Scopes.Compiler
|
||||
end
|
@ -6,7 +6,6 @@ defmodule Pleroma.Web.Federator do
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object.Containment
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.Federator.Publisher
|
||||
@ -80,7 +79,7 @@ defmodule Pleroma.Web.Federator do
|
||||
|
||||
# NOTE: we use the actor ID to do the containment, this is fine because an
|
||||
# actor shouldn't be acting on objects outside their own AP server.
|
||||
with {_, {:ok, _user}} <- {:actor, ap_enabled_actor(actor)},
|
||||
with {_, {:ok, _user}} <- {:actor, User.get_or_fetch_by_ap_id(actor)},
|
||||
nil <- Activity.normalize(params["id"]),
|
||||
{_, :ok} <-
|
||||
{:correct_origin?, Containment.contain_origin_from_id(actor, params)},
|
||||
@ -110,14 +109,4 @@ defmodule Pleroma.Web.Federator do
|
||||
{:error, e}
|
||||
end
|
||||
end
|
||||
|
||||
def ap_enabled_actor(id) do
|
||||
user = User.get_cached_by_ap_id(id)
|
||||
|
||||
if User.ap_enabled?(user) do
|
||||
{:ok, user}
|
||||
else
|
||||
ActivityPub.make_user_from_ap_id(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -12,6 +12,8 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController do
|
||||
alias Pleroma.Web.MediaProxy
|
||||
alias Plug.Conn
|
||||
|
||||
plug(:sandbox)
|
||||
|
||||
def remote(conn, %{"sig" => sig64, "url" => url64}) do
|
||||
with {_, true} <- {:enabled, MediaProxy.enabled?()},
|
||||
{:ok, url} <- MediaProxy.decode_url(sig64, url64),
|
||||
@ -202,4 +204,9 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController do
|
||||
defp media_proxy_opts do
|
||||
Config.get([:media_proxy, :proxy_opts], [])
|
||||
end
|
||||
|
||||
defp sandbox(conn, _params) do
|
||||
conn
|
||||
|> merge_resp_headers([{"content-security-policy", "sandbox;"}])
|
||||
end
|
||||
end
|
||||
|
@ -76,9 +76,10 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
|
||||
{:meta, [name: "twitter:card", content: "summary_large_image"], []},
|
||||
{:meta,
|
||||
[
|
||||
name: "twitter:player",
|
||||
name: "twitter:image",
|
||||
content: MediaProxy.url(url["href"])
|
||||
], []}
|
||||
], []},
|
||||
{:meta, [name: "twitter:image:alt", content: truncate(attachment["name"])], []}
|
||||
| acc
|
||||
]
|
||||
|> maybe_add_dimensions(url)
|
||||
@ -130,4 +131,12 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
|
||||
metadata
|
||||
end
|
||||
end
|
||||
|
||||
defp truncate(nil), do: ""
|
||||
|
||||
defp truncate(text) do
|
||||
# truncate to 420 characters
|
||||
# see https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/markup
|
||||
Pleroma.Formatter.truncate(text, 420)
|
||||
end
|
||||
end
|
||||
|
@ -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
|
||||
@ -46,12 +46,32 @@ defmodule Pleroma.Web.Plugs.UploadedMedia do
|
||||
|
||||
config = Pleroma.Config.get(Pleroma.Upload)
|
||||
|
||||
with uploader <- Keyword.fetch!(config, :uploader),
|
||||
%{scheme: media_scheme, host: media_host, port: media_port} =
|
||||
Pleroma.Upload.base_url() |> URI.parse()
|
||||
|
||||
with {:valid_host, true} <- {:valid_host, match?(^media_host, conn.host)},
|
||||
uploader <- Keyword.fetch!(config, :uploader),
|
||||
proxy_remote = Keyword.get(config, :proxy_remote, false),
|
||||
{:ok, get_method} <- uploader.get_file(file),
|
||||
false <- media_is_banned(conn, get_method) do
|
||||
get_media(conn, get_method, proxy_remote, opts)
|
||||
else
|
||||
{:valid_host, false} ->
|
||||
redirect_url =
|
||||
%URI{
|
||||
scheme: media_scheme,
|
||||
host: media_host,
|
||||
port: media_port,
|
||||
path: conn.request_path,
|
||||
query: conn.query_string
|
||||
}
|
||||
|> URI.to_string()
|
||||
|> String.trim_trailing("?")
|
||||
|
||||
conn
|
||||
|> Phoenix.Controller.redirect(external: redirect_url)
|
||||
|> halt()
|
||||
|
||||
_ ->
|
||||
conn
|
||||
|> send_resp(:internal_server_error, dgettext("errors", "Failed"))
|
||||
|
@ -11,7 +11,7 @@ defmodule Pleroma.Web.Preload do
|
||||
terms =
|
||||
params
|
||||
|> parser.generate_terms()
|
||||
|> Enum.map(fn {k, v} -> {k, Base.encode64(Jason.encode!(v))} end)
|
||||
|> Enum.map(fn {k, v} -> {k, Base.encode64(Jason.encode!(v, escape: :html_safe))} end)
|
||||
|> Enum.into(%{})
|
||||
|
||||
Map.merge(acc, terms)
|
||||
@ -19,7 +19,7 @@ defmodule Pleroma.Web.Preload do
|
||||
|
||||
rendered_html =
|
||||
preload_data
|
||||
|> Jason.encode!()
|
||||
|> Jason.encode!(escape: :html_safe)
|
||||
|> build_script_tag()
|
||||
|> HTML.safe_to_string()
|
||||
|
||||
|
@ -6,8 +6,8 @@ defmodule Pleroma.Web.RichMedia.Parsers.OEmbed do
|
||||
def parse(html, _data) do
|
||||
with elements = [_ | _] <- get_discovery_data(html),
|
||||
oembed_url when is_binary(oembed_url) <- get_oembed_url(elements),
|
||||
{:ok, oembed_data} <- get_oembed_data(oembed_url) do
|
||||
oembed_data
|
||||
{:ok, oembed_data = %{"html" => html}} <- get_oembed_data(oembed_url) do
|
||||
%{oembed_data | "html" => Pleroma.HTML.filter_tags(html)}
|
||||
else
|
||||
_e -> %{}
|
||||
end
|
||||
|
@ -25,7 +25,15 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do
|
||||
true <- Visibility.is_public?(activity.object),
|
||||
{_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)},
|
||||
%User{} = user <- User.get_by_ap_id(activity.object.data["actor"]) do
|
||||
meta = Metadata.build_tags(%{activity_id: notice_id, object: activity.object, user: user})
|
||||
url = Helpers.url(conn) <> conn.request_path
|
||||
|
||||
meta =
|
||||
Metadata.build_tags(%{
|
||||
activity_id: notice_id,
|
||||
object: activity.object,
|
||||
user: user,
|
||||
url: url
|
||||
})
|
||||
|
||||
timeline =
|
||||
activity.object.data["context"]
|
||||
|
@ -25,6 +25,7 @@ defmodule Pleroma.Web.Streamer do
|
||||
def registry, do: @registry
|
||||
|
||||
@public_streams ["public", "public:local", "public:media", "public:local:media"]
|
||||
@local_streams ["public:local", "public:local:media"]
|
||||
@user_streams ["user", "user:notification", "direct", "user:pleroma_chat"]
|
||||
|
||||
@doc "Expands and authorizes a stream, and registers the process for streaming."
|
||||
@ -41,14 +42,37 @@ defmodule Pleroma.Web.Streamer do
|
||||
end
|
||||
end
|
||||
|
||||
defp can_access_stream(user, oauth_token, kind) do
|
||||
with {_, true} <- {:restrict?, Config.restrict_unauthenticated_access?(:timelines, kind)},
|
||||
{_, %User{id: user_id}, %Token{user_id: user_id}} <- {:user, user, oauth_token},
|
||||
{_, true} <-
|
||||
{:scopes,
|
||||
OAuthScopesPlug.filter_descendants(["read:statuses"], oauth_token.scopes) != []} do
|
||||
true
|
||||
else
|
||||
{:restrict?, _} ->
|
||||
true
|
||||
|
||||
_ ->
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
@doc "Expand and authorizes a stream"
|
||||
@spec get_topic(stream :: String.t(), User.t() | nil, Token.t() | nil, Map.t()) ::
|
||||
{:ok, topic :: String.t()} | {:error, :bad_topic}
|
||||
def get_topic(stream, user, oauth_token, params \\ %{})
|
||||
|
||||
# Allow all public steams.
|
||||
def get_topic(stream, _user, _oauth_token, _params) when stream in @public_streams do
|
||||
# Allow all public steams if the instance allows unauthenticated access.
|
||||
# Otherwise, only allow users with valid oauth tokens.
|
||||
def get_topic(stream, user, oauth_token, _params) when stream in @public_streams do
|
||||
kind = if stream in @local_streams, do: :local, else: :federated
|
||||
|
||||
if can_access_stream(user, oauth_token, kind) do
|
||||
{:ok, stream}
|
||||
else
|
||||
{:error, :unauthorized}
|
||||
end
|
||||
end
|
||||
|
||||
# Allow all hashtags streams.
|
||||
@ -57,12 +81,20 @@ defmodule Pleroma.Web.Streamer do
|
||||
end
|
||||
|
||||
# Allow remote instance streams.
|
||||
def get_topic("public:remote", _user, _oauth_token, %{"instance" => instance} = _params) do
|
||||
def get_topic("public:remote", user, oauth_token, %{"instance" => instance} = _params) do
|
||||
if can_access_stream(user, oauth_token, :federated) do
|
||||
{:ok, "public:remote:" <> instance}
|
||||
else
|
||||
{:error, :unauthorized}
|
||||
end
|
||||
end
|
||||
|
||||
def get_topic("public:remote:media", _user, _oauth_token, %{"instance" => instance} = _params) do
|
||||
def get_topic("public:remote:media", user, oauth_token, %{"instance" => instance} = _params) do
|
||||
if can_access_stream(user, oauth_token, :federated) do
|
||||
{:ok, "public:remote:media:" <> instance}
|
||||
else
|
||||
{:error, :unauthorized}
|
||||
end
|
||||
end
|
||||
|
||||
# Expand user streams.
|
||||
|
@ -8,7 +8,7 @@
|
||||
<%= checkbox @form, :"scope_#{scope}", value: scope in @scopes && scope, checked_value: scope, unchecked_value: "", name: "authorization[scope][]" %>
|
||||
<%= label @form, :"scope_#{scope}", String.capitalize(scope) %>
|
||||
<%= if scope in @scopes && scope do %>
|
||||
<%= String.capitalize(scope) %>
|
||||
<code><%= scope %></code> <%= :"Elixir.Gettext".dgettext(Gettext, "oauth_scopes", scope) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
|
@ -1,18 +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.Workers.TransmogrifierWorker do
|
||||
alias Pleroma.User
|
||||
|
||||
use Pleroma.Workers.WorkerHelper, queue: "transmogrifier"
|
||||
|
||||
@impl Oban.Worker
|
||||
def perform(%Job{args: %{"op" => "user_upgrade", "user_id" => user_id}}) do
|
||||
user = User.get_cached_by_id(user_id)
|
||||
Pleroma.Web.ActivityPub.Transmogrifier.perform(:user_upgrade, user)
|
||||
end
|
||||
|
||||
@impl Oban.Worker
|
||||
def timeout(_job), do: :timer.seconds(5)
|
||||
end
|
13
mix.exs
13
mix.exs
@ -4,10 +4,10 @@ defmodule Pleroma.Mixfile do
|
||||
def project do
|
||||
[
|
||||
app: :pleroma,
|
||||
version: version("2.5.51"),
|
||||
version: version("2.5.52"),
|
||||
elixir: "~> 1.11",
|
||||
elixirc_paths: elixirc_paths(Mix.env()),
|
||||
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
|
||||
compilers: [:phoenix] ++ Mix.compilers(),
|
||||
elixirc_options: [warnings_as_errors: warnings_as_errors()],
|
||||
xref: [exclude: [:eldap]],
|
||||
start_permanent: Mix.env() == :prod,
|
||||
@ -78,8 +78,7 @@ defmodule Pleroma.Mixfile do
|
||||
:comeonin,
|
||||
:fast_sanitize,
|
||||
:os_mon,
|
||||
:ssl,
|
||||
:esshd
|
||||
:ssl
|
||||
],
|
||||
included_applications: [:ex_syslogger]
|
||||
]
|
||||
@ -128,10 +127,7 @@ defmodule Pleroma.Mixfile do
|
||||
{:plug_cowboy, "~> 2.3"},
|
||||
# oban 2.14 requires Elixir 1.12+
|
||||
{:oban, "~> 2.13.4"},
|
||||
{:gettext,
|
||||
git: "https://github.com/tusooa/gettext.git",
|
||||
ref: "72fb2496b6c5280ed911bdc3756890e7f38a4808",
|
||||
override: true},
|
||||
{:gettext, "~> 0.20"},
|
||||
{:bcrypt_elixir, "~> 2.2"},
|
||||
{:trailing_format_plug, "~> 0.0.7"},
|
||||
{:fast_sanitize, "~> 0.2.0"},
|
||||
@ -181,7 +177,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"},
|
||||
|
4
mix.lock
4
mix.lock
@ -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"},
|
||||
@ -43,6 +42,7 @@
|
||||
"ex_doc": {:hex, :ex_doc, "0.29.4", "6257ecbb20c7396b1fe5accd55b7b0d23f44b6aa18017b415cb4c2b91d997729", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "2c6699a737ae46cb61e4ed012af931b57b699643b24dabe2400a8168414bc4f5"},
|
||||
"ex_machina": {:hex, :ex_machina, "2.7.0", "b792cc3127fd0680fecdb6299235b4727a4944a09ff0fa904cc639272cd92dc7", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "419aa7a39bde11894c87a615c4ecaa52d8f107bbdd81d810465186f783245bf8"},
|
||||
"ex_syslogger": {:hex, :ex_syslogger, "1.5.2", "72b6aa2d47a236e999171f2e1ec18698740f40af0bd02c8c650bf5f1fd1bac79", [:mix], [{:poison, ">= 1.5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:syslog, "~> 1.1.0", [hex: :syslog, repo: "hexpm", optional: false]}], "hexpm", "ab9fab4136dbc62651ec6f16fa4842f10cf02ab4433fa3d0976c01be99398399"},
|
||||
"expo": {:hex, :expo, "0.4.1", "1c61d18a5df197dfda38861673d392e642649a9cef7694d2f97a587b2cfb319b", [:mix], [], "hexpm", "2ff7ba7a798c8c543c12550fa0e2cbc81b95d4974c65855d8d15ba7b37a1ce47"},
|
||||
"fast_html": {:hex, :fast_html, "2.0.5", "c61760340606c1077ff1f196f17834056cb1dd3d5cb92a9f2cabf28bc6221c3c", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}], "hexpm", "605f4f4829443c14127694ebabb681778712ceecb4470ec32aa31012330e6506"},
|
||||
"fast_sanitize": {:hex, :fast_sanitize, "0.2.3", "67b93dfb34e302bef49fec3aaab74951e0f0602fd9fa99085987af05bd91c7a5", [:mix], [{:fast_html, "~> 2.0", [hex: :fast_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "e8ad286d10d0386e15d67d0ee125245ebcfbc7d7290b08712ba9013c8c5e56e2"},
|
||||
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
|
||||
@ -50,7 +50,7 @@
|
||||
"flake_id": {:hex, :flake_id, "0.1.0", "7716b086d2e405d09b647121a166498a0d93d1a623bead243e1f74216079ccb3", [:mix], [{:base62, "~> 1.2", [hex: :base62, repo: "hexpm", optional: false]}, {:ecto, ">= 2.0.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "31fc8090fde1acd267c07c36ea7365b8604055f897d3a53dd967658c691bd827"},
|
||||
"floki": {:hex, :floki, "0.34.2", "5fad07ef153b3b8ec110b6b155ec3780c4b2c4906297d0b4be1a7162d04a7e02", [:mix], [], "hexpm", "26b9d50f0f01796bc6be611ca815c5e0de034d2128e39cc9702eee6b66a4d1c8"},
|
||||
"gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm", "29bd14a88030980849c7ed2447b8db6d6c9278a28b11a44cafe41b791205440f"},
|
||||
"gettext": {:git, "https://github.com/tusooa/gettext.git", "72fb2496b6c5280ed911bdc3756890e7f38a4808", [ref: "72fb2496b6c5280ed911bdc3756890e7f38a4808"]},
|
||||
"gettext": {:hex, :gettext, "0.22.2", "6bfca374de34ecc913a28ba391ca184d88d77810a3e427afa8454a71a51341ac", [:mix], [{:expo, "~> 0.4.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "8a2d389673aea82d7eae387e6a2ccc12660610080ae7beb19452cfdc1ec30f60"},
|
||||
"gun": {:hex, :gun, "2.0.0", "2326bc0fd6d9cf628419708270d6fe8b02b8d002cf992e4165a77d997b1defd0", [:make, :rebar3], [{:cowlib, "2.12.0", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "6613cb7c62930dc8d58263c44dda72f8556346ba88358fc929dcbc5f76d04569"},
|
||||
"hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"},
|
||||
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
|
||||
|
264
priv/gettext/en/LC_MESSAGES/oauth_scopes.po
Normal file
264
priv/gettext/en/LC_MESSAGES/oauth_scopes.po
Normal file
@ -0,0 +1,264 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR Free Software Foundation, Inc.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"PO-Revision-Date: 2023-05-02 17:02-0400\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin"
|
||||
msgstr "All admin access"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:read"
|
||||
msgstr "Read all using admin API"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:write"
|
||||
msgstr "Write all using admin API"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "follow"
|
||||
msgstr "Read and write user relationships"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "push"
|
||||
msgstr "Push notifications"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read"
|
||||
msgstr "Read everything"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:accounts"
|
||||
msgstr "Read information of all accounts"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:backups"
|
||||
msgstr "Read your backups"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:blocks"
|
||||
msgstr "Read block relationships"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:bookmarks"
|
||||
msgstr "Read your bookmarks"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:chats"
|
||||
msgstr "Read your chats"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:favourites"
|
||||
msgstr "Read your favourites"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:filters"
|
||||
msgstr "Read your filtering settings"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:follows"
|
||||
msgstr "Read follow relationships"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:lists"
|
||||
msgstr "Read your lists"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:notifications"
|
||||
msgstr "Read your notifications"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:reports"
|
||||
msgstr "Read your reports"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:search"
|
||||
msgstr "Perform searches"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:statuses"
|
||||
msgstr "Read all statuses you can see"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write"
|
||||
msgstr "Write everything"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:accounts"
|
||||
msgstr "Change your account information"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:blocks"
|
||||
msgstr "Block or unblock someone"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:bookmarks"
|
||||
msgstr "Add to or remove from your bookmarks"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:chats"
|
||||
msgstr "Create or delete chats or chat messages, or mark them as read"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:conversations"
|
||||
msgstr "Change recipients of, mark as read, or delete conversations"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:favourites"
|
||||
msgstr "Favourite or unfavourite statuses"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:filters"
|
||||
msgstr "Change your filtering settings"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:follow"
|
||||
msgstr "Follow or unfollow someone"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:follows"
|
||||
msgstr "Follow or unfollow someone"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:lists"
|
||||
msgstr "Create, change or delete your lists"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:media"
|
||||
msgstr "Upload media files or modify those you uploaded"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:mutes"
|
||||
msgstr "Mute or unmute someone"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:notifications"
|
||||
msgstr "Mark notifications as read"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:reports"
|
||||
msgstr "Submit reports"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:statuses"
|
||||
msgstr "Post, edit, reblog or react to statuses"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:read:accounts"
|
||||
msgstr "Read all accounts using admin API"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:read:chats"
|
||||
msgstr "Read all chats using admin API"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:read:invites"
|
||||
msgstr "Read all invites using admin API"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:read:media_proxy_caches"
|
||||
msgstr "Read media proxy caches using admin API"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:read:reports"
|
||||
msgstr "Read all reports using admin API"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:read:statuses"
|
||||
msgstr "Read all statuses using admin API"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:write:accounts"
|
||||
msgstr "Change all accounts using admin API"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:write:chats"
|
||||
msgstr "Change all chats using admin API"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:write:follows"
|
||||
msgstr "Change follow relationships using admin API"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:write:invites"
|
||||
msgstr "Invite or revoke an invite using admin API"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:write:media_proxy_caches"
|
||||
msgstr "Change media proxy caches using admin API"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:write:reports"
|
||||
msgstr "Handle reports using admin API"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:write:statuses"
|
||||
msgstr "Delete, change scope of, or mark as sensitive statuses using admin API"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:media"
|
||||
msgstr "Read media attachments"
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:mutes"
|
||||
msgstr "Read mute relationships"
|
@ -9,7 +9,6 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Language: en_test\n"
|
||||
"Plural-Forms: nplurals=2\n"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:122
|
||||
|
@ -9,7 +9,6 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Language: en_test\n"
|
||||
"Plural-Forms: nplurals=2\n"
|
||||
|
||||
msgid "can't be blank"
|
||||
msgstr ""
|
||||
|
@ -9,7 +9,6 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Language: en_test\n"
|
||||
"Plural-Forms: nplurals=2\n"
|
||||
|
||||
msgid "eperm"
|
||||
msgstr ""
|
||||
|
@ -21,10 +21,6 @@ msgstr ""
|
||||
#~ ##
|
||||
#~ ## Use "mix gettext.extract --merge" or "mix gettext.merge"
|
||||
#~ ## to merge POT files into PO files.
|
||||
#~ msgid ""
|
||||
#~ msgstr ""
|
||||
#~ "Language: en_test\n"
|
||||
#~ "Plural-Forms: nplurals=2\n"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex:9
|
||||
|
261
priv/gettext/oauth_scopes.pot
Normal file
261
priv/gettext/oauth_scopes.pot
Normal file
@ -0,0 +1,261 @@
|
||||
## This file is a PO Template file.
|
||||
##
|
||||
## "msgid"s here are often extracted from source code.
|
||||
## Add new translations manually only if they're dynamic
|
||||
## translations that can't be statically extracted.
|
||||
##
|
||||
## Run "mix gettext.extract" to bring this file up to
|
||||
## date. Leave "msgstr"s empty as changing them here has no
|
||||
## effect: edit them in PO (.po) files instead.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:read"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:write"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "follow"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "push"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:accounts"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:backups"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:blocks"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:bookmarks"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:chats"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:favourites"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:filters"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:follows"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:lists"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:notifications"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:reports"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:search"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:statuses"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:accounts"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:blocks"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:bookmarks"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:chats"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:conversations"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:favourites"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:filters"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:follow"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:follows"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:lists"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:media"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:mutes"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:notifications"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:reports"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "write:statuses"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:read:accounts"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:read:chats"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:read:invites"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:read:media_proxy_caches"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:read:reports"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:read:statuses"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:write:accounts"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:write:chats"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:write:follows"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:write:invites"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:write:media_proxy_caches"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:write:reports"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "admin:write:statuses"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:media"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/scopes/translator.ex:5
|
||||
msgid "read:mutes"
|
||||
msgstr ""
|
@ -9,7 +9,6 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Language: ru\n"
|
||||
"Plural-Forms: nplurals=3\n"
|
||||
|
||||
msgid "can't be blank"
|
||||
msgstr "не может быть пустым"
|
||||
|
@ -24,10 +24,6 @@ msgstr ""
|
||||
##
|
||||
## Use "mix gettext.extract --merge" or "mix gettext.merge"
|
||||
## to merge POT files into PO files.
|
||||
#~ msgid ""
|
||||
#~ msgstr ""
|
||||
#~ "Language: zh_Hans\n"
|
||||
#~ "Plural-Forms: nplurals=1\n"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex:9
|
||||
#, elixir-format
|
||||
|
@ -0,0 +1,13 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Repo.Migrations.RemoveUserApEnabled do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
alter table(:users) do
|
||||
remove(:ap_enabled, :boolean, default: false, null: false)
|
||||
end
|
||||
end
|
||||
end
|
@ -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(:a, ["name", "title", "lang"])
|
||||
|
||||
Meta.allow_tag_with_these_attributes(:abbr, ["title"])
|
||||
Meta.allow_tag_with_these_attributes(:abbr, ["title", "lang"])
|
||||
|
||||
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(: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()
|
||||
|
31
test/fixtures/fep-e232.json
vendored
Normal file
31
test/fixtures/fep-e232.json
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
"type": "Create",
|
||||
"actor": "https://example.org/users/alice",
|
||||
"object": {
|
||||
"id": "https://example.org/objects/10",
|
||||
"type": "Note",
|
||||
"attributedTo": "https://example.org/users/alice",
|
||||
"content": "<p>test <a href=\"https://example.org/objects/9\">https://example.org/objects/9</a></p>",
|
||||
"published": "2022-10-01T21:30:05.211215Z",
|
||||
"tag": [
|
||||
{
|
||||
"name": "@bob@example.net",
|
||||
"type": "Mention",
|
||||
"href": "https://example.net/users/bob"
|
||||
},
|
||||
{
|
||||
"name": "https://example.org/objects/9",
|
||||
"type": "Link",
|
||||
"href": "https://example.org/objects/9",
|
||||
"mediaType": "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
|
||||
}
|
||||
],
|
||||
"to": [
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"cc": [
|
||||
"https://example.org/users/alice/followers"
|
||||
]
|
||||
}
|
||||
}
|
@ -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
|
@ -0,0 +1,25 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.BareUriTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.EctoType.ActivityPub.ObjectValidators.BareUri
|
||||
|
||||
test "diaspora://" do
|
||||
text = "diaspora://alice@fediverse.example/post/deadbeefdeadbeefdeadbeefdeadbeef"
|
||||
assert {:ok, text} = BareUri.cast(text)
|
||||
end
|
||||
|
||||
test "nostr:" do
|
||||
text = "nostr:note1gwdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
||||
assert {:ok, text} = BareUri.cast(text)
|
||||
end
|
||||
|
||||
test "errors for non-URIs" do
|
||||
assert :error == SafeText.cast(1)
|
||||
assert :error == SafeText.cast("foo")
|
||||
assert :error == SafeText.cast("foo bar")
|
||||
end
|
||||
end
|
@ -9,8 +9,12 @@ defmodule Pleroma.Object.FetcherTest do
|
||||
alias Pleroma.Instances
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Object.Fetcher
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidator
|
||||
|
||||
require Pleroma.Constants
|
||||
|
||||
import Mock
|
||||
import Pleroma.Factory
|
||||
import Tesla.Mock
|
||||
|
||||
setup do
|
||||
@ -284,6 +288,8 @@ defmodule Pleroma.Object.FetcherTest do
|
||||
|
||||
describe "refetching" do
|
||||
setup do
|
||||
insert(:user, ap_id: "https://mastodon.social/users/emelie")
|
||||
|
||||
object1 = %{
|
||||
"id" => "https://mastodon.social/1",
|
||||
"actor" => "https://mastodon.social/users/emelie",
|
||||
@ -293,10 +299,14 @@ defmodule Pleroma.Object.FetcherTest do
|
||||
"bcc" => [],
|
||||
"bto" => [],
|
||||
"cc" => [],
|
||||
"to" => [],
|
||||
"summary" => ""
|
||||
"to" => [Pleroma.Constants.as_public()],
|
||||
"summary" => "",
|
||||
"published" => "2023-05-08 23:43:20Z",
|
||||
"updated" => "2023-05-09 23:43:20Z"
|
||||
}
|
||||
|
||||
{:ok, local_object1, _} = ObjectValidator.validate(object1, [])
|
||||
|
||||
object2 = %{
|
||||
"id" => "https://mastodon.social/2",
|
||||
"actor" => "https://mastodon.social/users/emelie",
|
||||
@ -306,8 +316,10 @@ defmodule Pleroma.Object.FetcherTest do
|
||||
"bcc" => [],
|
||||
"bto" => [],
|
||||
"cc" => [],
|
||||
"to" => [],
|
||||
"to" => [Pleroma.Constants.as_public()],
|
||||
"summary" => "",
|
||||
"published" => "2023-05-08 23:43:20Z",
|
||||
"updated" => "2023-05-09 23:43:25Z",
|
||||
"formerRepresentations" => %{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [
|
||||
@ -319,14 +331,18 @@ defmodule Pleroma.Object.FetcherTest do
|
||||
"bcc" => [],
|
||||
"bto" => [],
|
||||
"cc" => [],
|
||||
"to" => [],
|
||||
"summary" => ""
|
||||
"to" => [Pleroma.Constants.as_public()],
|
||||
"summary" => "",
|
||||
"published" => "2023-05-08 23:43:20Z",
|
||||
"updated" => "2023-05-09 23:43:21Z"
|
||||
}
|
||||
],
|
||||
"totalItems" => 1
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, local_object2, _} = ObjectValidator.validate(object2, [])
|
||||
|
||||
mock(fn
|
||||
%{
|
||||
method: :get,
|
||||
@ -335,7 +351,7 @@ defmodule Pleroma.Object.FetcherTest do
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
headers: [{"content-type", "application/activity+json"}],
|
||||
body: Jason.encode!(object1)
|
||||
body: Jason.encode!(object1 |> Map.put("updated", "2023-05-09 23:44:20Z"))
|
||||
}
|
||||
|
||||
%{
|
||||
@ -345,7 +361,7 @@ defmodule Pleroma.Object.FetcherTest do
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
headers: [{"content-type", "application/activity+json"}],
|
||||
body: Jason.encode!(object2)
|
||||
body: Jason.encode!(object2 |> Map.put("updated", "2023-05-09 23:44:20Z"))
|
||||
}
|
||||
|
||||
%{
|
||||
@ -370,7 +386,7 @@ defmodule Pleroma.Object.FetcherTest do
|
||||
apply(HttpRequestMock, :request, [env])
|
||||
end)
|
||||
|
||||
%{object1: object1, object2: object2}
|
||||
%{object1: local_object1, object2: local_object2}
|
||||
end
|
||||
|
||||
test "it keeps formerRepresentations if remote does not have this attr", %{object1: object1} do
|
||||
@ -388,8 +404,9 @@ defmodule Pleroma.Object.FetcherTest do
|
||||
"bcc" => [],
|
||||
"bto" => [],
|
||||
"cc" => [],
|
||||
"to" => [],
|
||||
"summary" => ""
|
||||
"to" => [Pleroma.Constants.as_public()],
|
||||
"summary" => "",
|
||||
"published" => "2023-05-08 23:43:20Z"
|
||||
}
|
||||
],
|
||||
"totalItems" => 1
|
||||
@ -467,6 +484,53 @@ defmodule Pleroma.Object.FetcherTest do
|
||||
}
|
||||
} = refetched.data
|
||||
end
|
||||
|
||||
test "it keeps the history intact if only updated time has changed",
|
||||
%{object1: object1} do
|
||||
full_object1 =
|
||||
object1
|
||||
|> Map.merge(%{
|
||||
"updated" => "2023-05-08 23:43:47Z",
|
||||
"formerRepresentations" => %{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [
|
||||
%{"type" => "Note", "content" => "mew mew 1"}
|
||||
],
|
||||
"totalItems" => 1
|
||||
}
|
||||
})
|
||||
|
||||
{:ok, o} = Object.create(full_object1)
|
||||
|
||||
assert {:ok, refetched} = Fetcher.refetch_object(o)
|
||||
|
||||
assert %{
|
||||
"content" => "test 1",
|
||||
"formerRepresentations" => %{
|
||||
"orderedItems" => [
|
||||
%{"content" => "mew mew 1"}
|
||||
],
|
||||
"totalItems" => 1
|
||||
}
|
||||
} = refetched.data
|
||||
end
|
||||
|
||||
test "it goes through ObjectValidator and MRF", %{object2: object2} do
|
||||
with_mock Pleroma.Web.ActivityPub.MRF, [:passthrough],
|
||||
filter: fn
|
||||
%{"type" => "Note"} = object ->
|
||||
{:ok, Map.put(object, "content", "MRFd content")}
|
||||
|
||||
arg ->
|
||||
passthrough([arg])
|
||||
end do
|
||||
{:ok, o} = Object.create(object2)
|
||||
|
||||
assert {:ok, refetched} = Fetcher.refetch_object(o)
|
||||
|
||||
assert %{"content" => "MRFd content"} = refetched.data
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetch with history" do
|
||||
|
32
test/pleroma/upload/filter/only_media_test.exs
Normal file
32
test/pleroma/upload/filter/only_media_test.exs
Normal file
@ -0,0 +1,32 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Upload.Filter.OnlyMediaTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.Upload
|
||||
alias Pleroma.Upload.Filter.OnlyMedia
|
||||
|
||||
test "Allows media Content-Type" do
|
||||
["audio/mpeg", "image/jpeg", "video/mp4"]
|
||||
|> Enum.each(fn type ->
|
||||
upload = %Upload{
|
||||
content_type: type
|
||||
}
|
||||
|
||||
assert {:ok, :noop} = OnlyMedia.filter(upload)
|
||||
end)
|
||||
end
|
||||
|
||||
test "Disallows non-media Content-Type" do
|
||||
["application/javascript", "application/pdf", "text/html"]
|
||||
|> Enum.each(fn type ->
|
||||
upload = %Upload{
|
||||
content_type: type
|
||||
}
|
||||
|
||||
assert {:error, _} = OnlyMedia.filter(upload)
|
||||
end)
|
||||
end
|
||||
end
|
@ -1844,7 +1844,6 @@ defmodule Pleroma.UserTest do
|
||||
confirmation_token: "qqqq",
|
||||
domain_blocks: ["lain.com"],
|
||||
is_active: false,
|
||||
ap_enabled: true,
|
||||
is_moderator: true,
|
||||
is_admin: true,
|
||||
mascot: %{"a" => "b"},
|
||||
@ -1885,7 +1884,6 @@ defmodule Pleroma.UserTest do
|
||||
confirmation_token: nil,
|
||||
domain_blocks: [],
|
||||
is_active: false,
|
||||
ap_enabled: false,
|
||||
is_moderator: false,
|
||||
is_admin: false,
|
||||
mascot: nil,
|
||||
@ -2473,8 +2471,7 @@ defmodule Pleroma.UserTest do
|
||||
insert(:user,
|
||||
local: false,
|
||||
follower_address: "http://localhost:4001/users/masto_closed/followers",
|
||||
following_address: "http://localhost:4001/users/masto_closed/following",
|
||||
ap_enabled: true
|
||||
following_address: "http://localhost:4001/users/masto_closed/following"
|
||||
)
|
||||
|
||||
assert other_user.following_count == 0
|
||||
@ -2495,8 +2492,7 @@ defmodule Pleroma.UserTest do
|
||||
insert(:user,
|
||||
local: false,
|
||||
follower_address: "http://localhost:4001/users/masto_closed/followers",
|
||||
following_address: "http://localhost:4001/users/masto_closed/following",
|
||||
ap_enabled: true
|
||||
following_address: "http://localhost:4001/users/masto_closed/following"
|
||||
)
|
||||
|
||||
assert other_user.following_count == 0
|
||||
@ -2517,8 +2513,7 @@ defmodule Pleroma.UserTest do
|
||||
insert(:user,
|
||||
local: false,
|
||||
follower_address: "http://localhost:4001/users/masto_closed/followers",
|
||||
following_address: "http://localhost:4001/users/masto_closed/following",
|
||||
ap_enabled: true
|
||||
following_address: "http://localhost:4001/users/masto_closed/following"
|
||||
)
|
||||
|
||||
assert other_user.following_count == 0
|
||||
|
@ -575,7 +575,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
||||
user =
|
||||
insert(:user,
|
||||
ap_id: "https://mastodon.example.org/users/raymoo",
|
||||
ap_enabled: true,
|
||||
local: false,
|
||||
last_refreshed_at: nil
|
||||
)
|
||||
|
@ -174,7 +174,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
||||
{:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
|
||||
assert user.ap_id == user_id
|
||||
assert user.nickname == "admin@mastodon.example.org"
|
||||
assert user.ap_enabled
|
||||
assert user.follower_address == "http://mastodon.example.org/users/admin/followers"
|
||||
end
|
||||
|
||||
|
@ -276,8 +276,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
||||
follower =
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
inbox: "https://domain.com/users/nick1/inbox"
|
||||
})
|
||||
|
||||
actor = insert(:user, follower_address: follower.ap_id)
|
||||
@ -313,8 +312,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
||||
follower =
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
inbox: "https://domain.com/users/nick1/inbox"
|
||||
})
|
||||
|
||||
actor = insert(:user, follower_address: follower.ap_id)
|
||||
@ -348,8 +346,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
||||
follower =
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
inbox: "https://domain.com/users/nick1/inbox"
|
||||
})
|
||||
|
||||
actor = insert(:user, follower_address: follower.ap_id)
|
||||
@ -382,15 +379,13 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
||||
fetcher =
|
||||
insert(:user,
|
||||
local: false,
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
inbox: "https://domain.com/users/nick1/inbox"
|
||||
)
|
||||
|
||||
another_fetcher =
|
||||
insert(:user,
|
||||
local: false,
|
||||
inbox: "https://domain2.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
inbox: "https://domain2.com/users/nick1/inbox"
|
||||
)
|
||||
|
||||
actor = insert(:user)
|
||||
|
@ -8,7 +8,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
@ -123,6 +122,20 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
||||
|
||||
assert activity.data["context"] == object.data["context"]
|
||||
end
|
||||
|
||||
test "it drops link tags" do
|
||||
insert(:user, ap_id: "https://example.org/users/alice")
|
||||
|
||||
message = File.read!("test/fixtures/fep-e232.json") |> Jason.decode!()
|
||||
|
||||
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||
|
||||
object = Object.normalize(activity)
|
||||
assert length(object.data["tag"]) == 1
|
||||
|
||||
tag = object.data["tag"] |> List.first()
|
||||
assert tag["type"] == "Mention"
|
||||
end
|
||||
end
|
||||
|
||||
describe "prepare outgoing" do
|
||||
@ -339,69 +352,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
||||
end
|
||||
end
|
||||
|
||||
describe "user upgrade" do
|
||||
test "it upgrades a user to activitypub" do
|
||||
user =
|
||||
insert(:user, %{
|
||||
nickname: "rye@niu.moe",
|
||||
local: false,
|
||||
ap_id: "https://niu.moe/users/rye",
|
||||
follower_address: User.ap_followers(%User{nickname: "rye@niu.moe"})
|
||||
})
|
||||
|
||||
user_two = insert(:user)
|
||||
Pleroma.FollowingRelationship.follow(user_two, user, :follow_accept)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test"})
|
||||
{:ok, unrelated_activity} = CommonAPI.post(user_two, %{status: "test"})
|
||||
assert "http://localhost:4001/users/rye@niu.moe/followers" in activity.recipients
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert user.note_count == 1
|
||||
|
||||
{:ok, user} = Transmogrifier.upgrade_user_from_ap_id("https://niu.moe/users/rye")
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
assert user.ap_enabled
|
||||
assert user.note_count == 1
|
||||
assert user.follower_address == "https://niu.moe/users/rye/followers"
|
||||
assert user.following_address == "https://niu.moe/users/rye/following"
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert user.note_count == 1
|
||||
|
||||
activity = Activity.get_by_id(activity.id)
|
||||
assert user.follower_address in activity.recipients
|
||||
|
||||
assert %{
|
||||
"url" => [
|
||||
%{
|
||||
"href" =>
|
||||
"https://cdn.niu.moe/accounts/avatars/000/033/323/original/fd7f8ae0b3ffedc9.jpeg"
|
||||
}
|
||||
]
|
||||
} = user.avatar
|
||||
|
||||
assert %{
|
||||
"url" => [
|
||||
%{
|
||||
"href" =>
|
||||
"https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
|
||||
}
|
||||
]
|
||||
} = user.banner
|
||||
|
||||
refute "..." in activity.recipients
|
||||
|
||||
unrelated_activity = Activity.get_by_id(unrelated_activity.id)
|
||||
refute user.follower_address in unrelated_activity.recipients
|
||||
|
||||
user_two = User.get_cached_by_id(user_two.id)
|
||||
assert User.following?(user_two, user)
|
||||
refute "..." in User.following(user_two)
|
||||
end
|
||||
end
|
||||
|
||||
describe "actor rewriting" do
|
||||
test "it fixes the actor URL property to be a proper URI" do
|
||||
data = %{
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
}
|
||||
|
56
test/pleroma/web/api_spec/scopes/compiler_test.exs
Normal file
56
test/pleroma/web/api_spec/scopes/compiler_test.exs
Normal file
@ -0,0 +1,56 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ApiSpec.Scopes.CompilerTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
alias Pleroma.Web.ApiSpec.Scopes.Compiler
|
||||
|
||||
@dummy_response %{}
|
||||
|
||||
@data %{
|
||||
paths: %{
|
||||
"/mew" => %OpenApiSpex.PathItem{
|
||||
post: %OpenApiSpex.Operation{
|
||||
security: [%{"oAuth" => ["a:b:c"]}],
|
||||
responses: @dummy_response
|
||||
},
|
||||
get: %OpenApiSpex.Operation{security: nil, responses: @dummy_response}
|
||||
},
|
||||
"/mew2" => %OpenApiSpex.PathItem{
|
||||
post: %OpenApiSpex.Operation{
|
||||
security: [%{"oAuth" => ["d:e", "f:g"]}],
|
||||
responses: @dummy_response
|
||||
},
|
||||
get: %OpenApiSpex.Operation{security: nil, responses: @dummy_response}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe "process_scope/1" do
|
||||
test "gives all higher-level scopes" do
|
||||
scopes = Compiler.process_scope("admin:read:accounts")
|
||||
|
||||
assert [_, _, _] = scopes
|
||||
assert "admin" in scopes
|
||||
assert "admin:read" in scopes
|
||||
assert "admin:read:accounts" in scopes
|
||||
end
|
||||
end
|
||||
|
||||
describe "extract_all_scopes_from/1" do
|
||||
test "extracts scopes" do
|
||||
scopes = Compiler.extract_all_scopes_from(@data)
|
||||
|
||||
assert [_, _, _, _, _, _, _] = scopes
|
||||
assert "a" in scopes
|
||||
assert "a:b" in scopes
|
||||
assert "a:b:c" in scopes
|
||||
assert "d" in scopes
|
||||
assert "d:e" in scopes
|
||||
assert "f" in scopes
|
||||
assert "f:g" in scopes
|
||||
end
|
||||
end
|
||||
end
|
@ -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"
|
||||
@ -1328,7 +1339,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
||||
|
||||
test "cancels a pending follow for a remote user" do
|
||||
follower = insert(:user)
|
||||
followed = insert(:user, is_locked: true, local: false, ap_enabled: true)
|
||||
followed = insert(:user, is_locked: true, local: false)
|
||||
|
||||
assert {:ok, follower, followed, %{id: activity_id, data: %{"state" => "pending"}}} =
|
||||
CommonAPI.follow(follower, followed)
|
||||
|
@ -78,16 +78,14 @@ defmodule Pleroma.Web.FederatorTest do
|
||||
local: false,
|
||||
nickname: "nick1@domain.com",
|
||||
ap_id: "https://domain.com/users/nick1",
|
||||
inbox: inbox1,
|
||||
ap_enabled: true
|
||||
inbox: inbox1
|
||||
})
|
||||
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
nickname: "nick2@domain2.com",
|
||||
ap_id: "https://domain2.com/users/nick2",
|
||||
inbox: inbox2,
|
||||
ap_enabled: true
|
||||
inbox: inbox2
|
||||
})
|
||||
|
||||
dt = NaiveDateTime.utc_now()
|
||||
|
@ -6,7 +6,9 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Mock
|
||||
import Mox
|
||||
|
||||
alias Pleroma.ReverseProxy.ClientMock
|
||||
alias Pleroma.Web.MediaProxy
|
||||
alias Plug.Conn
|
||||
|
||||
@ -74,6 +76,20 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do
|
||||
assert %Conn{status: 404, resp_body: "Not Found"} = get(conn, url)
|
||||
end
|
||||
end
|
||||
|
||||
test "it applies sandbox CSP to MediaProxy requests", %{conn: conn} do
|
||||
media_url = "https://lain.com/image.png"
|
||||
media_proxy_url = MediaProxy.encode_url(media_url)
|
||||
|
||||
ClientMock
|
||||
|> expect(:request, fn :get, ^media_url, _, _, _ ->
|
||||
{:ok, 200, [{"content-type", "image/png"}]}
|
||||
end)
|
||||
|
||||
%Conn{resp_headers: headers} = get(conn, media_proxy_url)
|
||||
|
||||
assert {"content-security-policy", "sandbox;"} in headers
|
||||
end
|
||||
end
|
||||
|
||||
describe "Media Preview Proxy" do
|
||||
|
@ -182,7 +182,8 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCardTest do
|
||||
{:meta, [name: "twitter:title", content: Utils.user_name_string(user)], []},
|
||||
{:meta, [name: "twitter:description", content: "pleroma in a nutshell"], []},
|
||||
{:meta, [name: "twitter:card", content: "summary_large_image"], []},
|
||||
{:meta, [name: "twitter:player", content: "https://pleroma.gov/tenshi.png"], []},
|
||||
{:meta, [name: "twitter:image", content: "https://pleroma.gov/tenshi.png"], []},
|
||||
{:meta, [name: "twitter:image:alt", content: ""], []},
|
||||
{:meta, [name: "twitter:player:width", content: "1280"], []},
|
||||
{:meta, [name: "twitter:player:height", content: "1024"], []},
|
||||
{:meta, [name: "twitter:card", content: "player"], []},
|
||||
|
@ -33,11 +33,37 @@ 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
|
||||
|
||||
test "denies access to media if wrong Host", %{
|
||||
attachment_url: attachment_url
|
||||
} do
|
||||
conn = get(build_conn(), attachment_url)
|
||||
|
||||
assert conn.status == 200
|
||||
|
||||
new_media_base = "http://media.localhost:8080"
|
||||
|
||||
%{scheme: new_media_scheme, host: new_media_host, port: new_media_port} =
|
||||
URI.parse(new_media_base)
|
||||
|
||||
clear_config([Pleroma.Upload, :base_url], new_media_base)
|
||||
|
||||
conn = get(build_conn(), attachment_url)
|
||||
|
||||
expected_url =
|
||||
URI.parse(attachment_url)
|
||||
|> Map.put(:host, new_media_host)
|
||||
|> Map.put(:port, new_media_port)
|
||||
|> Map.put(:scheme, new_media_scheme)
|
||||
|> URI.to_string()
|
||||
|
||||
assert redirected_to(conn, 302) == expected_url
|
||||
end
|
||||
end
|
||||
|
@ -129,7 +129,7 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
|
||||
}}
|
||||
end
|
||||
|
||||
test "parses OEmbed" do
|
||||
test "parses OEmbed and filters HTML tags" do
|
||||
assert Parser.parse("http://example.com/oembed") ==
|
||||
{:ok,
|
||||
%{
|
||||
@ -139,7 +139,7 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
|
||||
"flickr_type" => "photo",
|
||||
"height" => "768",
|
||||
"html" =>
|
||||
"<a data-flickr-embed=\"true\" href=\"https://www.flickr.com/photos/bees/2362225867/\" title=\"Bacon Lollys by \u202E\u202D\u202Cbees\u202C, on Flickr\"><img src=\"https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_b.jpg\" width=\"1024\" height=\"768\" alt=\"Bacon Lollys\"></a><script async src=\"https://embedr.flickr.com/assets/client-code.js\" charset=\"utf-8\"></script>",
|
||||
"<a href=\"https://www.flickr.com/photos/bees/2362225867/\" title=\"Bacon Lollys by \u202E\u202D\u202Cbees\u202C, on Flickr\"><img src=\"https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_b.jpg\" width=\"1024\" height=\"768\" alt=\"Bacon Lollys\"/></a>",
|
||||
"license" => "All Rights Reserved",
|
||||
"license_id" => 0,
|
||||
"provider_name" => "Flickr",
|
||||
|
@ -29,6 +29,26 @@ defmodule Pleroma.Web.StreamerTest do
|
||||
assert {:ok, "public:local:media"} = Streamer.get_topic("public:local:media", nil, nil)
|
||||
end
|
||||
|
||||
test "rejects local public streams if restricted_unauthenticated is on" do
|
||||
clear_config([:restrict_unauthenticated, :timelines, :local], true)
|
||||
|
||||
assert {:error, :unauthorized} = Streamer.get_topic("public:local", nil, nil)
|
||||
assert {:error, :unauthorized} = Streamer.get_topic("public:local:media", nil, nil)
|
||||
end
|
||||
|
||||
test "rejects remote public streams if restricted_unauthenticated is on" do
|
||||
clear_config([:restrict_unauthenticated, :timelines, :federated], true)
|
||||
|
||||
assert {:error, :unauthorized} = Streamer.get_topic("public", nil, nil)
|
||||
assert {:error, :unauthorized} = Streamer.get_topic("public:media", nil, nil)
|
||||
|
||||
assert {:error, :unauthorized} =
|
||||
Streamer.get_topic("public:remote", nil, nil, %{"instance" => "lain.com"})
|
||||
|
||||
assert {:error, :unauthorized} =
|
||||
Streamer.get_topic("public:remote:media", nil, nil, %{"instance" => "lain.com"})
|
||||
end
|
||||
|
||||
test "allows instance streams" do
|
||||
assert {:ok, "public:remote:lain.com"} =
|
||||
Streamer.get_topic("public:remote", nil, nil, %{"instance" => "lain.com"})
|
||||
@ -69,6 +89,63 @@ defmodule Pleroma.Web.StreamerTest do
|
||||
end
|
||||
end
|
||||
|
||||
test "allows local public streams if restricted_unauthenticated is on", %{
|
||||
user: user,
|
||||
token: oauth_token
|
||||
} do
|
||||
clear_config([:restrict_unauthenticated, :timelines, :local], true)
|
||||
|
||||
%{token: read_notifications_token} = oauth_access(["read:notifications"], user: user)
|
||||
%{token: badly_scoped_token} = oauth_access(["irrelevant:scope"], user: user)
|
||||
|
||||
assert {:ok, "public:local"} = Streamer.get_topic("public:local", user, oauth_token)
|
||||
|
||||
assert {:ok, "public:local:media"} =
|
||||
Streamer.get_topic("public:local:media", user, oauth_token)
|
||||
|
||||
for token <- [read_notifications_token, badly_scoped_token] do
|
||||
assert {:error, :unauthorized} = Streamer.get_topic("public:local", user, token)
|
||||
|
||||
assert {:error, :unauthorized} = Streamer.get_topic("public:local:media", user, token)
|
||||
end
|
||||
end
|
||||
|
||||
test "allows remote public streams if restricted_unauthenticated is on", %{
|
||||
user: user,
|
||||
token: oauth_token
|
||||
} do
|
||||
clear_config([:restrict_unauthenticated, :timelines, :federated], true)
|
||||
|
||||
%{token: read_notifications_token} = oauth_access(["read:notifications"], user: user)
|
||||
%{token: badly_scoped_token} = oauth_access(["irrelevant:scope"], user: user)
|
||||
|
||||
assert {:ok, "public"} = Streamer.get_topic("public", user, oauth_token)
|
||||
assert {:ok, "public:media"} = Streamer.get_topic("public:media", user, oauth_token)
|
||||
|
||||
assert {:ok, "public:remote:lain.com"} =
|
||||
Streamer.get_topic("public:remote", user, oauth_token, %{"instance" => "lain.com"})
|
||||
|
||||
assert {:ok, "public:remote:media:lain.com"} =
|
||||
Streamer.get_topic("public:remote:media", user, oauth_token, %{
|
||||
"instance" => "lain.com"
|
||||
})
|
||||
|
||||
for token <- [read_notifications_token, badly_scoped_token] do
|
||||
assert {:error, :unauthorized} = Streamer.get_topic("public", user, token)
|
||||
assert {:error, :unauthorized} = Streamer.get_topic("public:media", user, token)
|
||||
|
||||
assert {:error, :unauthorized} =
|
||||
Streamer.get_topic("public:remote", user, token, %{
|
||||
"instance" => "lain.com"
|
||||
})
|
||||
|
||||
assert {:error, :unauthorized} =
|
||||
Streamer.get_topic("public:remote:media", user, token, %{
|
||||
"instance" => "lain.com"
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
test "allows user streams (with proper OAuth token scopes)", %{
|
||||
user: user,
|
||||
token: read_oauth_token
|
||||
|
@ -50,7 +50,6 @@ defmodule Pleroma.Factory do
|
||||
last_refreshed_at: NaiveDateTime.utc_now(),
|
||||
notification_settings: %Pleroma.User.NotificationSetting{},
|
||||
multi_factor_authentication_settings: %Pleroma.MFA.Settings{},
|
||||
ap_enabled: true,
|
||||
keys: pem
|
||||
}
|
||||
|
||||
|
@ -1,22 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "looking for change log of $CI_MERGE_REQUEST_IID"
|
||||
echo "looking for change log"
|
||||
|
||||
count=0
|
||||
for i in add remove fix security skip; do
|
||||
[ -f changelog.d/"$CI_MERGE_REQUEST_IID"."$i" ]
|
||||
retcode=$?
|
||||
if [ $retcode -eq 0 ]; then
|
||||
echo "found $CI_MERGE_REQUEST_IID.$i"
|
||||
count=$(( count + 1 ))
|
||||
else
|
||||
echo "no $CI_MERGE_REQUEST_IID.$i"
|
||||
fi
|
||||
done
|
||||
if [ $count -gt 0 ]; then
|
||||
echo "ok"
|
||||
git remote add upstream https://git.pleroma.social/pleroma/pleroma.git
|
||||
git fetch upstream ${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}:refs/remotes/upstream/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME
|
||||
|
||||
git diff --raw --no-renames upstream/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME HEAD -- changelog.d | \
|
||||
grep ' A\t' | grep '\.\(skip\|add\|remove\|fix\|security\)$'
|
||||
ret=$?
|
||||
|
||||
if [ $ret -eq 0 ]; then
|
||||
echo "found a changelog entry"
|
||||
exit 0
|
||||
else
|
||||
echo "must have a changelog entry or explicitly skip it"
|
||||
echo "changelog entry not found"
|
||||
exit 1
|
||||
fi
|
||||
|
Loading…
Reference in New Issue
Block a user