Merge branch 'bugs' into 'main'

Multiple bugs fixed

Closes #836, #843, #910, #890 et #894

See merge request framasoft/mobilizon!1109
This commit is contained in:
Thomas Citharel 2021-11-15 08:17:21 +00:00
commit 56bb28373b
107 changed files with 1699 additions and 4032 deletions

View File

@ -4,8 +4,45 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 2.0.0-beta.2 - 2021-11-15
This lists changes since 2.0.0-beta.1.
### Added
- Group followers and members get an notification email by default when a group publishes a new event (subject to activity notification settings)
- Group admins can now approve or deny new memberships
- Added organizer actor name (profile or group) in the icalendar export
- Add initial support for federation with Gancio
### Changed
- Event update notification is send to participants ~30 minutes after the event update, so that successive edits are throttled.
- Event, post and comments titles and content now have expose their detected language in HTML, for improved screen reader experience
### Fixed
- Release front-end files are no longer in duplicate
- Only show datetime timezone toggle on event if the timezone offset is different from our own
- Fix error when determining audience for Discussion when deleting a comment
- Fix a couple of accessibility issues
- Limit to acceptable tags when pasting raw HTML into comment fields on front-end
- Fixed group map display
- Fixed updating group physical address
- Allow group members to access group drafts
- Improve group refreshment workflow
- Fixed date signature generation for federation
- Fixed an issue when duplicating a group event from another profile
- Fixed event metadata not saved on eventcreation
- Use a different pagination parameter for searched events and featured events on search page
### Translations
- Gaelic
- Spanish
## 2.0.0-beta.1 - 2021-11-09 ## 2.0.0-beta.1 - 2021-11-09
Please read the [UPGRADE.md](https://framagit.org/framasoft/mobilizon/-/blob/main/UPGRADE.md#upgrading-from-13-to-20) file as well.
### Added ### Added
- Added possibility to follow groups and be notified from new upcoming events - Added possibility to follow groups and be notified from new upcoming events
@ -40,6 +77,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improve metadata on public page - Improve metadata on public page
- Make sure some event action pages (participate remotely or without an account) don't get indexed by search engines - Make sure some event action pages (participate remotely or without an account) don't get indexed by search engines
- Only send `Tombstone` element in `Delete` activities, not the whole previous deleted element. - Only send `Tombstone` element in `Delete` activities, not the whole previous deleted element.
- Make sure `Delete` activity are send correctly to everyone
- Only add address and tags to event icalendar export if they exist - Only add address and tags to event icalendar export if they exist
- `master` branch has been renamed to `main` - `master` branch has been renamed to `main`

View File

@ -1,19 +1,69 @@
# Upgrading from 1.3 to 2.0 # Upgrading from 1.3 to 2.0
Requirements dependencies depend on the way Mobilizon is installed. Requirements dependencies depend on the way Mobilizon is installed.
## New dependencies requirements ## New Elixir version requirement
### Docker and Release install
### Release and Docker
You are already using latest Elixir version in the release tarball and Docker images. You are already using latest Elixir version in the release tarball and Docker images.
### Source install ### Source install
* Elixir 1.12 and Erlang OTP 22 is now required. If your distribution doesn't provide these versions, you can uninstall them and install [Elixir](https://github.com/asdf-vm/asdf-elixir) through the [ASDF tool](https://asdf-vm.com/). **Elixir 1.12 and Erlang OTP 22 are now required**. If your distribution doesn't provide these versions (which is likely), you must uninstall them and install [Elixir](https://github.com/asdf-vm/asdf-elixir) through the [ASDF tool](https://asdf-vm.com/).
## Optional dependencies ## Geographic timezone data
These are optional, installing them will allow Mobilizon to export to PDF and ODS as well. Mobilizon 2.0 uses data based on [timezone-boundary-builder](https://github.com/evansiroky/timezone-boundary-builder) (which is based itself on OpenStreetMap data) to determine the timezone of an event automatically, based on it's geocoordinates. However, this needs ~700Mio of disk, so we don't redistribute data directly, depending on the case. It's possible to skip this part, but users will need to manually pick the timezone for every event they created when it has a different timezone from their own.
### Docker install
The geographic timezone data is already bundled into the image, you have nothing to do.
### Release install
In order to keep the release tarballs light, the geographic timezone data is not bundled directly. You need to download the data :
* either raw from Github, but **requires an extra ~1Gio of memory** to process the data
```sh
sudo -u mobilizon mkdir /var/lib/mobilizon/timezones
sudo -u mobilizon ./bin/mobilizon_ctl tz_world.update
```
* either already processed from our own distribution server
```sh
sudo -u mobilizon mkdir /var/lib/mobilizon/timezones
sudo -u mobilizon curl -L 'https://packages.joinmobilizon.org/tz_world/timezones-geodata.dets' -o /var/lib/mobilizon/timezones/timezones-geodata.dets
```
In both cases, ~700Mio of disk will be used. You may use the following configuration to specify where the data is expected:
```elixir
config :tz_world, data_dir: "/some/place"
```
### Source install
You need to download the data :
* either raw from Github, but **requires an extra ~1Gio of memory** to process the data
```sh
sudo -u mobilizon mkdir /var/lib/mobilizon/timezones
sudo -u mobilizon mix mobilizon.tz_world.update
```
* either already processed from our own distribution server
```sh
sudo -u mobilizon mkdir /var/lib/mobilizon/timezones
sudo -u mobilizon curl -L 'https://packages.joinmobilizon.org/tz_world/timezones-geodata.dets' -o /var/lib/mobilizon/timezones/timezones-geodata.dets
```
In both cases, ~700Mio of disk will be used. You may use the following configuration to specify where the data is expected:
```elixir
config :tz_world, data_dir: "/some/place"
```
## New optional dependencies
These are optional, installing them will allow Mobilizon to export to PDF and ODS as well. Mobilizon 2.0 allows to export the participant list, but more is planned.
### Docker ### Docker
Everything is included in our Docker image. Everything is included in our Docker image.
### Release and source install ### Release and source install
@ -23,7 +73,7 @@ New optional Python dependencies:
* `weasyprint` for PDF export (with [a few extra dependencies](https://doc.courtbouillon.org/weasyprint/stable/first_steps.html)) * `weasyprint` for PDF export (with [a few extra dependencies](https://doc.courtbouillon.org/weasyprint/stable/first_steps.html))
* `pyexcel-ods3` for ODS export (no extra dependencies) * `pyexcel-ods3` for ODS export (no extra dependencies)
Both can be installed through pip. Both can be installed through pip. You need to enable exports for PDF and ODS in the configuration afterwards. Read [the dedicated docs page about this]() (*upcoming*).
# Upgrading from 1.0 to 1.1 # Upgrading from 1.0 to 1.1

View File

@ -90,6 +90,8 @@ config :mobilizon, Mobilizon.Web.Upload.Uploader.Local, uploads: "/var/lib/mobil
config :tz_world, data_dir: "/var/lib/mobilizon/timezones" config :tz_world, data_dir: "/var/lib/mobilizon/timezones"
config :mobilizon, Timex.Gettext, default_locale: "en"
config :mobilizon, :media_proxy, config :mobilizon, :media_proxy,
enabled: true, enabled: true,
proxy_opts: [ proxy_opts: [

View File

@ -62,15 +62,18 @@ config :mobilizon, Mobilizon.Web.Upload.Uploader.Local, uploads: "test/uploads"
config :tz_world, data_dir: "_build/test/lib/tz_world/priv" config :tz_world, data_dir: "_build/test/lib/tz_world/priv"
config :exvcr,
vcr_cassette_library_dir: "test/fixtures/vcr_cassettes"
config :tesla, Mobilizon.Service.HTTP.ActivityPub, config :tesla, Mobilizon.Service.HTTP.ActivityPub,
adapter: Mobilizon.Service.HTTP.ActivityPub.Mock adapter: Mobilizon.Service.HTTP.ActivityPub.Mock
config :tesla, Mobilizon.Service.HTTP.WebfingerClient,
adapter: Mobilizon.Service.HTTP.WebfingerClient.Mock
config :tesla, Mobilizon.Service.HTTP.GeospatialClient, config :tesla, Mobilizon.Service.HTTP.GeospatialClient,
adapter: Mobilizon.Service.HTTP.GeospatialClient.Mock adapter: Mobilizon.Service.HTTP.GeospatialClient.Mock
config :tesla, Mobilizon.Service.HTTP.HostMetaClient,
adapter: Mobilizon.Service.HTTP.HostMetaClient.Mock
config :mobilizon, Mobilizon.Service.Geospatial, service: Mobilizon.Service.Geospatial.Mock config :mobilizon, Mobilizon.Service.Geospatial, service: Mobilizon.Service.Geospatial.Mock
config :mobilizon, Oban, queues: false, plugins: false config :mobilizon, Oban, queues: false, plugins: false

View File

@ -50,6 +50,7 @@
"p-debounce": "^4.0.0", "p-debounce": "^4.0.0",
"phoenix": "^1.6", "phoenix": "^1.6",
"register-service-worker": "^1.7.2", "register-service-worker": "^1.7.2",
"sanitize-html": "^2.5.3",
"tippy.js": "^6.2.3", "tippy.js": "^6.2.3",
"unfetch": "^4.2.0", "unfetch": "^4.2.0",
"v-tooltip": "^2.1.3", "v-tooltip": "^2.1.3",
@ -74,6 +75,7 @@
"@types/prosemirror-model": "^1.7.2", "@types/prosemirror-model": "^1.7.2",
"@types/prosemirror-state": "^1.2.4", "@types/prosemirror-state": "^1.2.4",
"@types/prosemirror-view": "^1.11.4", "@types/prosemirror-view": "^1.11.4",
"@types/sanitize-html": "^2.5.0",
"@typescript-eslint/eslint-plugin": "^5.3.0", "@typescript-eslint/eslint-plugin": "^5.3.0",
"@typescript-eslint/parser": "^5.3.0", "@typescript-eslint/parser": "^5.3.0",
"@vue/cli-plugin-babel": "~5.0.0-rc.0", "@vue/cli-plugin-babel": "~5.0.0-rc.0",

View File

@ -63,7 +63,12 @@
</button> </button>
</span> </span>
<br /> <br />
<div v-if="!comment.deletedAt" v-html="comment.text" dir="auto" /> <div
v-if="!comment.deletedAt"
v-html="comment.text"
dir="auto"
:lang="comment.language"
/>
<div v-else>{{ $t("[This comment has been deleted]") }}</div> <div v-else>{{ $t("[This comment has been deleted]") }}</div>
<div class="load-replies" v-if="comment.totalReplies"> <div class="load-replies" v-if="comment.totalReplies">
<p v-if="!showReplies" @click="fetchReplies"> <p v-if="!showReplies" @click="fetchReplies">

View File

@ -212,6 +212,7 @@ import Underline from "@tiptap/extension-underline";
import Link from "@tiptap/extension-link"; import Link from "@tiptap/extension-link";
import CharacterCount from "@tiptap/extension-character-count"; import CharacterCount from "@tiptap/extension-character-count";
import { AutoDir } from "./Editor/Autodir"; import { AutoDir } from "./Editor/Autodir";
import sanitizeHtml from "sanitize-html";
@Component({ @Component({
components: { EditorContent, BubbleMenu }, components: { EditorContent, BubbleMenu },
@ -265,6 +266,7 @@ export default class EditorComponent extends Vue {
"aria-label": this.ariaLabel, "aria-label": this.ariaLabel,
role: "textbox", role: "textbox",
}, },
transformPastedHTML: this.transformPastedHTML,
}, },
extensions: [ extensions: [
StarterKit, StarterKit,
@ -292,6 +294,19 @@ export default class EditorComponent extends Vue {
}); });
} }
transformPastedHTML(html: string): string {
// When using comment mode, limit to acceptable tags
if (this.isCommentMode) {
return sanitizeHtml(html, {
allowedTags: ["b", "i", "em", "strong", "a"],
allowedAttributes: {
a: ["href", "rel", "target"],
},
});
}
return html;
}
@Watch("value") @Watch("value")
onValueChanged(val: string): void { onValueChanged(val: string): void {
if (!this.editor) return; if (!this.editor) return;

View File

@ -39,7 +39,12 @@
/> />
</div> </div>
<div class="media-content"> <div class="media-content">
<h3 class="event-title" :title="event.title" dir="auto"> <h3
class="event-title"
:title="event.title"
dir="auto"
:lang="event.language"
>
{{ event.title }} {{ event.title }}
</h3> </h3>
<div class="content-end"> <div class="content-end">

View File

@ -17,7 +17,7 @@
</div> </div>
</div> </div>
<div class="title-info-wrapper has-text-grey-dark"> <div class="title-info-wrapper has-text-grey-dark">
<h3 class="event-minimalist-title"> <h3 class="event-minimalist-title" :lang="event.language" dir="auto">
<b-tag <b-tag
class="mr-2" class="mr-2"
type="is-warning" type="is-warning"

View File

@ -51,7 +51,9 @@
params: { uuid: participation.event.uuid }, params: { uuid: participation.event.uuid },
}" }"
> >
<h3 class="title">{{ participation.event.title }}</h3> <h3 class="title" :lang="participation.event.language">
{{ participation.event.title }}
</h3>
</router-link> </router-link>
</div> </div>
<inline-address <inline-address

View File

@ -10,7 +10,9 @@
style="height: 120px" style="height: 120px"
/> />
<div class="title-info-wrapper has-text-grey-dark"> <div class="title-info-wrapper has-text-grey-dark">
<h3 class="post-minimalist-title">{{ post.title }}</h3> <h3 class="post-minimalist-title" :lang="post.language">
{{ post.title }}
</h3>
<p class="post-publication-date"> <p class="post-publication-date">
<b-icon icon="clock" /> <b-icon icon="clock" />
<span dir="auto" class="has-text-grey-dark" v-if="isBeforeLastWeek">{{ <span dir="auto" class="has-text-grey-dark" v-if="isBeforeLastWeek">{{

View File

@ -214,6 +214,9 @@ export const LOGGED_USER_DRAFTS = gql`
} }
beginsOn beginsOn
visibility visibility
attributedTo {
...ActorFragment
}
organizerActor { organizerActor {
...ActorFragment ...ActorFragment
} }

View File

@ -18,6 +18,7 @@ export const COMMENT_FIELDS_FRAGMENT = gql`
updatedAt updatedAt
deletedAt deletedAt
isAnnouncement isAnnouncement
language
} }
${ACTOR_FRAGMENT} ${ACTOR_FRAGMENT}
`; `;

View File

@ -22,6 +22,7 @@ const FULL_EVENT_FRAGMENT = gql`
visibility visibility
joinOptions joinOptions
draft draft
language
picture { picture {
id id
url url
@ -60,6 +61,7 @@ const FULL_EVENT_FRAGMENT = gql`
uuid uuid
title title
beginsOn beginsOn
language
picture { picture {
id id
url url
@ -153,6 +155,7 @@ export const FETCH_EVENTS = gql`
status status
visibility visibility
insertedAt insertedAt
language
picture { picture {
id id
url url
@ -203,6 +206,7 @@ export const CREATE_EVENT = gql`
$physicalAddress: AddressInput $physicalAddress: AddressInput
$options: EventOptionsInput $options: EventOptionsInput
$contacts: [Contact] $contacts: [Contact]
$metadata: EventMetadataInput
) { ) {
createEvent( createEvent(
organizerActorId: $organizerActorId organizerActorId: $organizerActorId
@ -223,6 +227,7 @@ export const CREATE_EVENT = gql`
physicalAddress: $physicalAddress physicalAddress: $physicalAddress
options: $options options: $options
contacts: $contacts contacts: $contacts
metadata: $metadata
) { ) {
...FullEvent ...FullEvent
} }

View File

@ -105,6 +105,7 @@ export const GROUP_FIELDS_FRAGMENTS = gql`
title title
beginsOn beginsOn
draft draft
language
options { options {
maximumAttendeeCapacity maximumAttendeeCapacity
} }

View File

@ -37,6 +37,7 @@ export const HOME_USER_QUERIES = gql`
} }
beginsOn beginsOn
visibility visibility
language
organizerActor { organizerActor {
...ActorFragment ...ActorFragment
} }
@ -79,6 +80,7 @@ export const HOME_USER_QUERIES = gql`
picture { picture {
url url
} }
language
attributedTo { attributedTo {
...ActorFragment ...ActorFragment
} }
@ -129,6 +131,7 @@ export const CLOSE_CONTENT = gql`
id id
url url
} }
language
tags { tags {
...TagFragment ...TagFragment
} }

View File

@ -21,6 +21,7 @@ export const POST_FRAGMENT = gql`
publishAt publishAt
draft draft
visibility visibility
language
tags { tags {
...TagFragment ...TagFragment
} }
@ -56,6 +57,7 @@ export const POST_BASIC_FIELDS = gql`
publishAt publishAt
draft draft
visibility visibility
language
picture { picture {
id id
url url

View File

@ -90,6 +90,7 @@ export interface IEvent {
options: IEventOptions; options: IEventOptions;
metadata: IEventMetadata[]; metadata: IEventMetadata[];
contacts: IActor[]; contacts: IActor[];
language: string;
toEditJSON(): IEventEditJSON; toEditJSON(): IEventEditJSON;
} }
@ -134,6 +135,8 @@ export class EventModel implements IEvent {
publishAt = new Date(); publishAt = new Date();
language = "und";
participantStats = { participantStats = {
notApproved: 0, notApproved: 0,
notConfirmed: 0, notConfirmed: 0,
@ -210,6 +213,7 @@ export class EventModel implements IEvent {
this.tags = hash.tags; this.tags = hash.tags;
this.metadata = hash.metadata; this.metadata = hash.metadata;
this.language = hash.language;
if (hash.options) this.options = hash.options; if (hash.options) this.options = hash.options;
} }

View File

@ -669,7 +669,11 @@ const DEFAULT_LIMIT_NUMBER_OF_PLACES = 10;
}; };
}, },
update(data) { update(data) {
return new EventModel(data.event); let event = data.event;
if (this.isDuplicate) {
event = { ...event, organizerActor: this.currentActor };
}
return new EventModel(event);
}, },
skip() { skip() {
return !this.eventId; return !this.eventId;

View File

@ -10,7 +10,12 @@
<section class="intro" dir="auto"> <section class="intro" dir="auto">
<div class="columns"> <div class="columns">
<div class="column"> <div class="column">
<h1 class="title" style="margin: 0" dir="auto"> <h1
class="title"
style="margin: 0"
dir="auto"
:lang="event.language"
>
{{ event.title }} {{ event.title }}
</h1> </h1>
<div class="organizer"> <div class="organizer">
@ -289,6 +294,7 @@
</p> </p>
<div v-else> <div v-else>
<div <div
:lang="event.language"
dir="auto" dir="auto"
class="description-content" class="description-content"
ref="eventDescriptionElement" ref="eventDescriptionElement"

View File

@ -1366,4 +1366,8 @@ div.container {
grid-template: 1fr; grid-template: 1fr;
} }
} }
.map {
height: 60vh;
width: 100%;
}
</style> </style>

View File

@ -15,7 +15,7 @@
v-if="post.draft" v-if="post.draft"
>{{ $t("Draft") }}</b-tag >{{ $t("Draft") }}</b-tag
> >
<h1 class="title">{{ post.title }}</h1> <h1 class="title" :lang="post.language">{{ post.title }}</h1>
</div> </div>
<p class="metadata"> <p class="metadata">
<router-link <router-link
@ -165,7 +165,12 @@
}} }}
</b-message> </b-message>
<section v-html="post.body" dir="auto" class="content" /> <section
v-html="post.body"
dir="auto"
class="content"
:lang="post.language"
/>
<section class="tags" dir="auto"> <section class="tags" dir="auto">
<router-link <router-link
v-for="tag in post.tags" v-for="tag in post.tags"

View File

@ -101,11 +101,11 @@
<b-loading :active.sync="$apollo.loading"></b-loading> <b-loading :active.sync="$apollo.loading"></b-loading>
<h2 class="title">{{ $t("Featured events") }}</h2> <h2 class="title">{{ $t("Featured events") }}</h2>
<div v-if="events.elements.length > 0"> <div v-if="events.elements.length > 0">
<multi-card :events="events.elements" /> <multi-card class="my-4" :events="events.elements" />
<div class="pagination" v-if="events.total > EVENT_PAGE_LIMIT"> <div class="pagination" v-if="events.total > EVENT_PAGE_LIMIT">
<b-pagination <b-pagination
:total="events.total" :total="events.total"
v-model="eventPage" v-model="featuredEventPage"
:per-page="EVENT_PAGE_LIMIT" :per-page="EVENT_PAGE_LIMIT"
:aria-next-label="$t('Next page')" :aria-next-label="$t('Next page')"
:aria-previous-label="$t('Previous page')" :aria-previous-label="$t('Previous page')"
@ -251,7 +251,7 @@ const GEOHASH_DEPTH = 9; // put enough accuracy, radius will be used anyway
query: FETCH_EVENTS, query: FETCH_EVENTS,
variables() { variables() {
return { return {
page: this.eventPage, page: this.featuredEventPage,
limit: EVENT_PAGE_LIMIT, limit: EVENT_PAGE_LIMIT,
}; };
}, },
@ -391,6 +391,17 @@ export default class Search extends Vue {
this.search = searchQuery; this.search = searchQuery;
} }
get featuredEventPage(): number {
return parseInt(this.$route.query.featuredEventPage as string, 10) || 1;
}
set featuredEventPage(page: number) {
this.$router.push({
name: this.$route.name || RouteName.SEARCH,
query: { ...this.$route.query, featuredEventPage: page.toString() },
});
}
get eventPage(): number { get eventPage(): number {
return parseInt(this.$route.query.eventPage as string, 10) || 1; return parseInt(this.$route.query.eventPage as string, 10) || 1;
} }

View File

@ -23,6 +23,7 @@ const postData = {
body: "My content", body: "My content",
insertedAt: "2020-12-02T09:01:20.873Z", insertedAt: "2020-12-02T09:01:20.873Z",
tags: [], tags: [],
language: "en",
}; };
const generateWrapper = ( const generateWrapper = (

View File

@ -4,7 +4,9 @@ exports[`PostListItem renders post list item with basic informations 1`] = `
<a href="/p/my-blog-post-some-uuid" class="post-minimalist-card-wrapper" dir="auto"> <a href="/p/my-blog-post-some-uuid" class="post-minimalist-card-wrapper" dir="auto">
<!----> <!---->
<div class="title-info-wrapper has-text-grey-dark"> <div class="title-info-wrapper has-text-grey-dark">
<h3 class="post-minimalist-title">My Blog Post</h3> <h3 lang="en" class="post-minimalist-title">
My Blog Post
</h3>
<p class="post-publication-date"><span class="icon"><i class="mdi mdi-clock mdi-24px"></i></span> <span dir="auto" class="has-text-grey-dark">Dec 2, 2020</span></p> <p class="post-publication-date"><span class="icon"><i class="mdi mdi-clock mdi-24px"></i></span> <span dir="auto" class="has-text-grey-dark">Dec 2, 2020</span></p>
<!----> <!---->
<!----> <!---->
@ -16,7 +18,9 @@ exports[`PostListItem renders post list item with publisher name 1`] = `
<a href="/p/my-blog-post-some-uuid" class="post-minimalist-card-wrapper" dir="auto"> <a href="/p/my-blog-post-some-uuid" class="post-minimalist-card-wrapper" dir="auto">
<!----> <!---->
<div class="title-info-wrapper has-text-grey-dark"> <div class="title-info-wrapper has-text-grey-dark">
<h3 class="post-minimalist-title">My Blog Post</h3> <h3 lang="en" class="post-minimalist-title">
My Blog Post
</h3>
<p class="post-publication-date"><span class="icon"><i class="mdi mdi-clock mdi-24px"></i></span> <span dir="auto" class="has-text-grey-dark">Dec 2, 2020</span></p> <p class="post-publication-date"><span class="icon"><i class="mdi mdi-clock mdi-24px"></i></span> <span dir="auto" class="has-text-grey-dark">Dec 2, 2020</span></p>
<!----> <!---->
<p class="post-publisher has-text-grey-dark"><span class="icon"><i class="mdi mdi-account-edit mdi-24px"></i></span> <span>Published by <b class="has-text-weight-medium">An author</b></span></p> <p class="post-publisher has-text-grey-dark"><span class="icon"><i class="mdi mdi-account-edit mdi-24px"></i></span> <span>Published by <b class="has-text-weight-medium">An author</b></span></p>
@ -28,7 +32,9 @@ exports[`PostListItem renders post list item with tags 1`] = `
<a href="/p/my-blog-post-some-uuid" class="post-minimalist-card-wrapper" dir="auto"> <a href="/p/my-blog-post-some-uuid" class="post-minimalist-card-wrapper" dir="auto">
<!----> <!---->
<div class="title-info-wrapper has-text-grey-dark"> <div class="title-info-wrapper has-text-grey-dark">
<h3 class="post-minimalist-title">My Blog Post</h3> <h3 lang="en" class="post-minimalist-title">
My Blog Post
</h3>
<p class="post-publication-date"><span class="icon"><i class="mdi mdi-clock mdi-24px"></i></span> <span dir="auto" class="has-text-grey-dark">Dec 2, 2020</span></p> <p class="post-publication-date"><span class="icon"><i class="mdi mdi-clock mdi-24px"></i></span> <span dir="auto" class="has-text-grey-dark">Dec 2, 2020</span></p>
<div class="tags" style="display: inline;"><span class="icon"><i class="mdi mdi-tag mdi-24px"></i></span> <span class="tag"><!----><span class="">A tag</span> <div class="tags" style="display: inline;"><span class="icon"><i class="mdi mdi-tag mdi-24px"></i></span> <span class="tag"><!----><span class="">A tag</span>
<!----></span> <!----></span>

View File

@ -111,6 +111,7 @@ export const eventCommentThreadsMock = {
deletedAt: null, deletedAt: null,
insertedAt: "2020-12-03T09:02:00Z", insertedAt: "2020-12-03T09:02:00Z",
isAnnouncement: false, isAnnouncement: false,
language: "en",
}, },
{ {
__typename: "Comment", __typename: "Comment",
@ -141,6 +142,7 @@ export const eventCommentThreadsMock = {
deletedAt: null, deletedAt: null,
insertedAt: "2020-12-03T11:02:00Z", insertedAt: "2020-12-03T11:02:00Z",
isAnnouncement: false, isAnnouncement: false,
language: "en",
}, },
], ],
}, },
@ -185,6 +187,7 @@ export const newCommentForEventResponse: DataMock = {
deletedAt: null, deletedAt: null,
insertedAt: "2020-12-03T13:02:00Z", insertedAt: "2020-12-03T13:02:00Z",
isAnnouncement: false, isAnnouncement: false,
language: "en",
}, },
}, },
}; };

View File

@ -2034,6 +2034,13 @@
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065"
integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==
"@types/sanitize-html@^2.5.0":
version "2.5.0"
resolved "https://registry.yarnpkg.com/@types/sanitize-html/-/sanitize-html-2.5.0.tgz#bfef58fbcf2674b20ffcc23c3506faa68c3a13e3"
integrity sha512-PeFIEZsO9m1+ACJlXUaimgrR+5DEDiIXhz7Hso307jmq5Yz0lb5kDp8LiTr5dMMMliC/jNNx/qds7Zoxa4zexw==
dependencies:
htmlparser2 "^6.0.0"
"@types/serve-index@*": "@types/serve-index@*":
version "1.9.1" version "1.9.1"
resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278"
@ -5708,7 +5715,7 @@ html-webpack-plugin@^5.1.0:
pretty-error "^4.0.0" pretty-error "^4.0.0"
tapable "^2.0.0" tapable "^2.0.0"
htmlparser2@^6.1.0: htmlparser2@^6.0.0, htmlparser2@^6.1.0:
version "6.1.0" version "6.1.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"
integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==
@ -6142,6 +6149,11 @@ is-plain-object@^2.0.4:
dependencies: dependencies:
isobject "^3.0.1" isobject "^3.0.1"
is-plain-object@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
is-potential-custom-element-name@^1.0.1: is-potential-custom-element-name@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
@ -7814,6 +7826,11 @@ parse-json@^5.0.0:
json-parse-even-better-errors "^2.3.0" json-parse-even-better-errors "^2.3.0"
lines-and-columns "^1.1.6" lines-and-columns "^1.1.6"
parse-srcset@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1"
integrity sha1-8r0iH2zJcKk42IVWq8WJyqqiveE=
parse5-htmlparser2-tree-adapter@^6.0.0: parse5-htmlparser2-tree-adapter@^6.0.0:
version "6.0.1" version "6.0.1"
resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6"
@ -8220,7 +8237,7 @@ postcss@^7.0.36:
picocolors "^0.2.1" picocolors "^0.2.1"
source-map "^0.6.1" source-map "^0.6.1"
postcss@^8.2.15, postcss@^8.2.6, postcss@^8.3.5: postcss@^8.2.15, postcss@^8.2.6, postcss@^8.3.11, postcss@^8.3.5:
version "8.3.11" version "8.3.11"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.11.tgz#c3beca7ea811cd5e1c4a3ec6d2e7599ef1f8f858" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.11.tgz#c3beca7ea811cd5e1c4a3ec6d2e7599ef1f8f858"
integrity sha512-hCmlUAIlUiav8Xdqw3Io4LcpA1DOt7h3LSTAC4G6JGHFFaWzI6qvFt9oilvl8BmkbBRX1IhM90ZAmpk68zccQA== integrity sha512-hCmlUAIlUiav8Xdqw3Io4LcpA1DOt7h3LSTAC4G6JGHFFaWzI6qvFt9oilvl8BmkbBRX1IhM90ZAmpk68zccQA==
@ -8837,6 +8854,18 @@ safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2,
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sanitize-html@^2.5.3:
version "2.5.3"
resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.5.3.tgz#91aa3dc760b072cdf92f9c6973747569b1ba1cd8"
integrity sha512-DGATXd1fs/Rm287/i5FBKVYSBBUL0iAaztOA1/RFhEs4yqo39/X52i/q/CwsfCUG5cilmXSBmnQmyWfnKhBlOg==
dependencies:
deepmerge "^4.2.2"
escape-string-regexp "^4.0.0"
htmlparser2 "^6.0.0"
is-plain-object "^5.0.0"
parse-srcset "^1.0.2"
postcss "^8.3.11"
sass-loader@^12.0.0: sass-loader@^12.0.0:
version "12.3.0" version "12.3.0"
resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.3.0.tgz#93278981c189c36a58cbfc37d4b9cef0cdc02871" resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.3.0.tgz#93278981c189c36a58cbfc37d4b9cef0cdc02871"

View File

@ -32,14 +32,14 @@ defmodule Mobilizon.Federation.ActivityPub.Actor do
case Actors.get_actor_by_url(url, preload) do case Actors.get_actor_by_url(url, preload) do
{:ok, %Actor{} = cached_actor} -> {:ok, %Actor{} = cached_actor} ->
if Actors.needs_update?(cached_actor) do if Actors.needs_update?(cached_actor) do
__MODULE__.make_actor_from_url(url, preload) __MODULE__.make_actor_from_url(url, preload: preload)
else else
{:ok, cached_actor} {:ok, cached_actor}
end end
{:error, :actor_not_found} -> {:error, :actor_not_found} ->
# For tests, see https://github.com/jjh42/mock#not-supported---mocking-internal-function-calls and Mobilizon.Federation.ActivityPubTest # For tests, see https://github.com/jjh42/mock#not-supported---mocking-internal-function-calls and Mobilizon.Federation.ActivityPubTest
__MODULE__.make_actor_from_url(url, preload) __MODULE__.make_actor_from_url(url, preload: preload)
end end
end end
@ -48,15 +48,15 @@ defmodule Mobilizon.Federation.ActivityPub.Actor do
@doc """ @doc """
Create an actor locally by its URL (AP ID) Create an actor locally by its URL (AP ID)
""" """
@spec make_actor_from_url(url :: String.t(), preload :: boolean()) :: @spec make_actor_from_url(url :: String.t(), options :: Keyword.t()) ::
{:ok, Actor.t()} | {:error, make_actor_errors | Ecto.Changeset.t()} {:ok, Actor.t()} | {:error, make_actor_errors | Ecto.Changeset.t()}
def make_actor_from_url(url, preload \\ false) do def make_actor_from_url(url, options \\ []) do
if are_same_origin?(url, Endpoint.url()) do if are_same_origin?(url, Endpoint.url()) do
{:error, :actor_is_local} {:error, :actor_is_local}
else else
case Fetcher.fetch_and_prepare_actor_from_url(url) do case Fetcher.fetch_and_prepare_actor_from_url(url, options) do
{:ok, data} when is_map(data) -> {:ok, data} when is_map(data) ->
Actors.upsert_actor(data, preload) Actors.upsert_actor(data, Keyword.get(options, :preload, false))
# Request returned 410 # Request returned 410
{:error, :actor_deleted} -> {:error, :actor_deleted} ->
@ -78,13 +78,13 @@ defmodule Mobilizon.Federation.ActivityPub.Actor do
case Actors.get_actor_by_name_with_preload(nickname, type) do case Actors.get_actor_by_name_with_preload(nickname, type) do
%Actor{url: actor_url} = actor -> %Actor{url: actor_url} = actor ->
if Actors.needs_update?(actor) do if Actors.needs_update?(actor) do
make_actor_from_url(actor_url, true) make_actor_from_url(actor_url, preload: true)
else else
{:ok, actor} {:ok, actor}
end end
nil -> nil ->
make_actor_from_nickname(nickname, true) make_actor_from_nickname(nickname, preload: true)
end end
end end
@ -100,7 +100,7 @@ defmodule Mobilizon.Federation.ActivityPub.Actor do
def make_actor_from_nickname(nickname, preload \\ false) do def make_actor_from_nickname(nickname, preload \\ false) do
case WebFinger.finger(nickname) do case WebFinger.finger(nickname) do
{:ok, url} when is_binary(url) -> {:ok, url} when is_binary(url) ->
make_actor_from_url(url, preload) make_actor_from_url(url, preload: preload)
{:error, e} -> {:error, e} ->
{:error, e} {:error, e}

View File

@ -49,8 +49,11 @@ defmodule Mobilizon.Federation.ActivityPub.Fetcher do
{:error, :content_not_json} {:error, :content_not_json}
{:ok, %Tesla.Env{} = res} -> {:ok, %Tesla.Env{} = res} ->
Logger.debug("Resource returned bad HTTP code inspect #{res}") Logger.debug("Resource returned bad HTTP code #{inspect(res)}")
{:error, :http_error} {:error, :http_error}
{:error, err} ->
{:error, err}
end end
else else
{:error, :invalid_url} {:error, :invalid_url}
@ -122,21 +125,12 @@ defmodule Mobilizon.Federation.ActivityPub.Fetcher do
""" """
@spec fetch_and_prepare_actor_from_url(String.t()) :: @spec fetch_and_prepare_actor_from_url(String.t()) ::
{:ok, map()} | {:error, fetch_actor_errors} {:ok, map()} | {:error, fetch_actor_errors}
def fetch_and_prepare_actor_from_url(url) do def fetch_and_prepare_actor_from_url(url, options \\ []) do
Logger.debug("Fetching and preparing actor from url") Logger.debug("Fetching and preparing actor from url")
Logger.debug(inspect(url)) Logger.debug(inspect(url))
case Tesla.get(url, case fetch(url, options) do
headers: [{"Accept", "application/activity+json"}], {:ok, data} ->
follow_redirect: true
) do
{:ok, %{status: 200, body: body}} ->
Logger.debug("response okay, now decoding json")
case Jason.decode(body) do
{:ok, data} when is_map(data) ->
Logger.debug("Got activity+json response at actor's endpoint, now converting data")
case ActorConverter.as_to_model_data(data) do case ActorConverter.as_to_model_data(data) do
{:error, :actor_not_allowed_type} -> {:error, :actor_not_allowed_type} ->
{:error, :actor_not_allowed_type} {:error, :actor_not_allowed_type}
@ -145,16 +139,11 @@ defmodule Mobilizon.Federation.ActivityPub.Fetcher do
{:ok, map} {:ok, map}
end end
{:error, %Jason.DecodeError{} = e} -> {:error, :http_gone} ->
Logger.warn("Could not decode actor at fetch #{url}, #{inspect(e)}")
{:error, :json_decode_error}
end
{:ok, %{status: 410}} ->
Logger.info("Response HTTP 410") Logger.info("Response HTTP 410")
{:error, :actor_deleted} {:error, :actor_deleted}
{:ok, %Tesla.Env{}} -> {:error, :http_error} ->
Logger.info("Non 200 HTTP Code") Logger.info("Non 200 HTTP Code")
{:error, :http_error} {:error, :http_error}

View File

@ -101,7 +101,8 @@ defmodule Mobilizon.Federation.ActivityPub.Permission do
false false
end end
else else
true # Object is not owned by a group
false
end end
end end

View File

@ -52,7 +52,7 @@ defmodule Mobilizon.Federation.ActivityPub.Refresher do
@spec fetch_group(String.t(), Actor.t()) :: :ok | {:error, fetch_actor_errors} @spec fetch_group(String.t(), Actor.t()) :: :ok | {:error, fetch_actor_errors}
def fetch_group(group_url, %Actor{} = on_behalf_of) do def fetch_group(group_url, %Actor{} = on_behalf_of) do
case ActivityPubActor.make_actor_from_url(group_url) do case ActivityPubActor.make_actor_from_url(group_url, on_behalf_of: on_behalf_of) do
{:error, err} {:error, err}
when err in [:actor_deleted, :http_error, :json_decode_error, :actor_is_local] -> when err in [:actor_deleted, :http_error, :json_decode_error, :actor_is_local] ->
Logger.debug("Error while making actor") Logger.debug("Error while making actor")

View File

@ -391,12 +391,15 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do
} = params } = params
) )
when object_type in ["Person", "Group", "Application", "Service", "Organization"] do when object_type in ["Person", "Group", "Application", "Service", "Organization"] do
with {:ok, %Actor{suspended: false} = old_actor} <- with author_url <- Utils.get_actor(params),
{:ok, %Actor{suspended: false} = author} <-
ActivityPubActor.get_or_fetch_actor_by_url(author_url),
{:ok, %Actor{suspended: false} = old_actor} <-
ActivityPubActor.get_or_fetch_actor_by_url(object["id"]), ActivityPubActor.get_or_fetch_actor_by_url(object["id"]),
object_data <- object_data <-
object |> Converter.Actor.as_to_model_data(), object |> Converter.Actor.as_to_model_data(),
{:ok, %Activity{} = activity, %Actor{} = new_actor} <- {:ok, %Activity{} = activity, %Actor{} = new_actor} <-
Actions.Update.update(old_actor, object_data, false) do Actions.Update.update(old_actor, object_data, false, %{updater_actor: author}) do
{:ok, activity, new_actor} {:ok, activity, new_actor}
else else
e -> e ->
@ -599,42 +602,28 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do
) do ) do
Logger.info("Handle incoming to delete an object") Logger.info("Handle incoming to delete an object")
with actor_url <- Utils.get_actor(data), actor_url = Utils.get_actor(data)
{:actor, {:ok, %Actor{} = actor}} <- object_id = Utils.get_url(object)
{:actor, ActivityPubActor.get_or_fetch_actor_by_url(actor_url)},
object_id <- Utils.get_url(object),
{:ok, object} <- is_group_object_gone(object_id),
{:origin_check, true} <-
{:origin_check,
Utils.origin_check_from_id?(actor_url, object_id) ||
Permission.can_delete_group_object?(actor, object)},
{:ok, activity, object} <- Actions.Delete.delete(object, actor, false) do
{:ok, activity, object}
else
{:origin_check, false} ->
Logger.warn("Object origin check failed")
:error
{:actor, {:error, _err}} -> case ActivityPubActor.get_or_fetch_actor_by_url(actor_url) do
{:error, _err} ->
{:error, :unknown_actor} {:error, :unknown_actor}
{:error, e} -> {:ok, %Actor{} = actor} ->
Logger.debug(inspect(e)) case is_group_object_gone(object_id) do
{:ok, object} ->
# Sentry.capture_message("Error while handling a Delete activity", if Utils.origin_check_from_id?(actor_url, object_id) ||
# extra: %{data: data} Permission.can_delete_group_object?(actor, object) do
# ) Actions.Delete.delete(object, actor, false)
else
Logger.warn("Object origin check failed")
:error :error
end
e -> {:error, err} ->
Logger.error(inspect(e)) Logger.debug(inspect(err))
{:error, err}
# Sentry.capture_message("Error while handling a Delete activity", end
# extra: %{data: data}
# )
:error
end end
end end

View File

@ -43,18 +43,22 @@ defmodule Mobilizon.Federation.ActivityPub.Types.Actors do
@spec update(Actor.t(), map, map) :: @spec update(Actor.t(), map, map) ::
{:ok, Actor.t(), ActivityStream.t()} | {:error, Ecto.Changeset.t()} {:ok, Actor.t(), ActivityStream.t()} | {:error, Ecto.Changeset.t()}
def update(%Actor{} = old_actor, args, additional) do def update(%Actor{} = old_actor, args, additional) do
updater_actor = Map.get(args, :updater_actor) || Map.get(additional, :updater_actor)
case Actors.update_actor(old_actor, args) do case Actors.update_actor(old_actor, args) do
{:ok, %Actor{} = new_actor} -> {:ok, %Actor{} = new_actor} ->
GroupActivity.insert_activity(new_actor, GroupActivity.insert_activity(new_actor,
subject: "group_updated", subject: "group_updated",
old_group: old_actor, old_group: old_actor,
updater_actor: Map.get(args, :updater_actor) updater_actor: updater_actor
) )
actor_as_data = Convertible.model_to_as(new_actor) actor_as_data = Convertible.model_to_as(new_actor)
Cachex.del(:activity_pub, "actor_#{new_actor.preferred_username}") Cachex.del(:activity_pub, "actor_#{new_actor.preferred_username}")
audience = Audience.get_audience(new_actor) audience = Audience.get_audience(new_actor)
additional = Map.merge(additional, %{"actor" => old_actor.url})
additional = Map.merge(additional, %{"actor" => (updater_actor || old_actor).url})
update_data = make_update_data(actor_as_data, Map.merge(audience, additional)) update_data = make_update_data(actor_as_data, Map.merge(audience, additional))
{:ok, new_actor, update_data} {:ok, new_actor, update_data}

View File

@ -129,7 +129,7 @@ defmodule Mobilizon.Federation.ActivityPub.Types.Events do
@spec permissions(Event.t()) :: Permission.t() @spec permissions(Event.t()) :: Permission.t()
def permissions(%Event{draft: draft, attributed_to_id: _attributed_to_id}) do def permissions(%Event{draft: draft, attributed_to_id: _attributed_to_id}) do
%Permission{ %Permission{
access: if(draft, do: nil, else: :member), access: if(draft, do: :moderator, else: :member),
create: :moderator, create: :moderator,
update: :moderator, update: :moderator,
delete: :moderator delete: :moderator

View File

@ -280,6 +280,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Utils do
_ -> _ ->
Logger.debug("not in our database, let's try to create it") Logger.debug("not in our database, let's try to create it")
# This is odd, why do addresses have url instead of just @id?
map = Map.put(map, "url", map["id"]) map = Map.put(map, "url", map["id"])
do_get_address(map) do_get_address(map)
end end

View File

@ -114,8 +114,12 @@ defmodule Mobilizon.Federation.HTTPSignatures.Signature do
Logger.debug("headers") Logger.debug("headers")
Logger.debug(inspect(headers)) Logger.debug(inspect(headers))
with {:ok, key} <- prepare_public_key(keys) do case prepare_public_key(keys) do
{:ok, key} ->
HTTPSignatures.sign(key, actor.url <> "#main-key", headers) HTTPSignatures.sign(key, actor.url <> "#main-key", headers)
{:error, :pem_decode_error} ->
raise ArgumentError, message: "Failed to prepare public keys for #{actor.url}"
end end
end end
@ -129,7 +133,7 @@ defmodule Mobilizon.Federation.HTTPSignatures.Signature do
@spec generate_date_header(NaiveDateTime.t()) :: String.t() @spec generate_date_header(NaiveDateTime.t()) :: String.t()
def generate_date_header(%NaiveDateTime{} = date) do def generate_date_header(%NaiveDateTime{} = date) do
Timex.format!(date, "{WDshort}, {0D} {Mshort} {YYYY} {h24}:{m}:{s} GMT") Timex.lformat!(date, "{WDshort}, {0D} {Mshort} {YYYY} {h24}:{m}:{s} GMT", "en")
end end
@spec generate_request_target(String.t(), String.t()) :: String.t() @spec generate_request_target(String.t(), String.t()) :: String.t()

View File

@ -188,10 +188,12 @@ defmodule Mobilizon.Federation.WebFinger do
@spec find_webfinger_endpoint(String.t()) :: @spec find_webfinger_endpoint(String.t()) ::
{:ok, String.t()} | {:error, :link_not_found} | {:error, any()} {:ok, String.t()} | {:error, :link_not_found} | {:error, any()}
defp find_webfinger_endpoint(domain) when is_binary(domain) do defp find_webfinger_endpoint(domain) when is_binary(domain) do
with {:ok, %{body: body}} <- fetch_document("http://#{domain}/.well-known/host-meta"), with {:ok, %Tesla.Env{status: 200, body: body}} <-
fetch_document("http://#{domain}/.well-known/host-meta"),
link_template when is_binary(link_template) <- find_link_from_template(body) do link_template when is_binary(link_template) <- find_link_from_template(body) do
{:ok, link_template} {:ok, link_template}
else else
{:ok, %Tesla.Env{status: 404}} -> {:error, :entity_not_found}
{:error, :link_not_found} -> {:error, :link_not_found} {:error, :link_not_found} -> {:error, :link_not_found}
{:error, error} -> {:error, error} {:error, error} -> {:error, error}
end end

View File

@ -93,7 +93,8 @@ defmodule Mobilizon.Actors.Actor do
:manually_approves_followers, :manually_approves_followers,
:user_id, :user_id,
:visibility, :visibility,
:openness :openness,
:physical_address_id
] ]
@update_attrs @update_required_attrs ++ @update_optional_attrs @update_attrs @update_required_attrs ++ @update_optional_attrs

View File

@ -48,6 +48,7 @@ defmodule Mobilizon.Web.Plugs.HTTPSignatures do
signature_valid = HTTPSignatures.validate_conn(conn) signature_valid = HTTPSignatures.validate_conn(conn)
Logger.debug("Is signature valid ? #{inspect(signature_valid)}") Logger.debug("Is signature valid ? #{inspect(signature_valid)}")
date_valid = date_valid?(conn) date_valid = date_valid?(conn)
Logger.debug("Is date valid ? #{inspect(date_valid)}")
assign(conn, :valid_signature, signature_valid && date_valid) assign(conn, :valid_signature, signature_valid && date_valid)
end end
end end

View File

@ -48,9 +48,10 @@ defmodule Mobilizon.Web.Plugs.MappedSignatureToIdentity do
# if this has payload make sure it is signed by the same actor that made it # if this has payload make sure it is signed by the same actor that made it
def call(%{assigns: %{valid_signature: true}, params: %{"actor" => actor}} = conn, _opts) do def call(%{assigns: %{valid_signature: true}, params: %{"actor" => actor}} = conn, _opts) do
with actor_id <- Utils.get_url(actor), with actor_id when actor_id != nil <- Utils.get_url(actor),
{:actor, %Actor{} = actor} <- {:actor, actor_from_key_id(conn)}, {:actor, %Actor{} = actor} <- {:actor, actor_from_key_id(conn)},
{:actor_match, true} <- {:actor_match, actor.url == actor_id} do {:actor_match, true} <- {:actor_match, actor.url == actor_id} do
Logger.debug("Mapped identity to #{actor.url} from actor param")
assign(conn, :actor, actor) assign(conn, :actor, actor)
else else
{:actor_match, false} -> {:actor_match, false} ->
@ -58,7 +59,7 @@ defmodule Mobilizon.Web.Plugs.MappedSignatureToIdentity do
Logger.debug("key_id=#{key_id_from_conn(conn)}, actor=#{actor}") Logger.debug("key_id=#{key_id_from_conn(conn)}, actor=#{actor}")
assign(conn, :valid_signature, false) assign(conn, :valid_signature, false)
# remove me once testsuite uses mapped capabilities instead of what we do now # TODO: remove me once testsuite uses mapped capabilities instead of what we do now
{:actor, nil} -> {:actor, nil} ->
Logger.debug("Failed to map identity from signature (lookup failure)") Logger.debug("Failed to map identity from signature (lookup failure)")
Logger.debug("key_id=#{key_id_from_conn(conn)}, actor=#{actor}") Logger.debug("key_id=#{key_id_from_conn(conn)}, actor=#{actor}")
@ -70,6 +71,7 @@ defmodule Mobilizon.Web.Plugs.MappedSignatureToIdentity do
def call(%{assigns: %{valid_signature: true}} = conn, _opts) do def call(%{assigns: %{valid_signature: true}} = conn, _opts) do
case actor_from_key_id(conn) do case actor_from_key_id(conn) do
%Actor{} = actor -> %Actor{} = actor ->
Logger.debug("Mapped identity to #{actor.url} from signed fetch")
assign(conn, :actor, actor) assign(conn, :actor, actor)
_ -> _ ->

View File

@ -12,6 +12,7 @@ defmodule Mobilizon.Web.ActivityPub.ActorView do
alias Mobilizon.Resources.Resource alias Mobilizon.Resources.Resource
alias Mobilizon.Storage.Page alias Mobilizon.Storage.Page
alias Mobilizon.Todos.TodoList alias Mobilizon.Todos.TodoList
require Logger
@private_visibility_empty_collection %{elements: [], total: 0} @private_visibility_empty_collection %{elements: [], total: 0}
@json_ld_header Utils.make_json_ld_header() @json_ld_header Utils.make_json_ld_header()
@ -39,9 +40,16 @@ defmodule Mobilizon.Web.ActivityPub.ActorView do
page = Map.get(args, :page, 1) page = Map.get(args, :page, 1)
collection_name = String.trim_trailing(view_name, ".json") collection_name = String.trim_trailing(view_name, ".json")
collection_name = String.to_existing_atom(collection_name) collection_name = String.to_existing_atom(collection_name)
actor_applicant = Map.get(args, :actor_applicant)
Logger.debug("Rendering actor collection #{inspect(collection_name)}")
Logger.debug(
"Using authenticated fetch with actor #{if actor_applicant, do: actor_applicant.url, else: nil}"
)
%{total: total, elements: elements} = %{total: total, elements: elements} =
if can_get_collection?(collection_name, actor, Map.get(args, :actor_applicant)), if can_get_collection?(collection_name, actor, actor_applicant),
do: fetch_collection(collection_name, actor, page), do: fetch_collection(collection_name, actor, page),
else: default_collection(collection_name, actor, page) else: default_collection(collection_name, actor, page)
@ -127,8 +135,13 @@ defmodule Mobilizon.Web.ActivityPub.ActorView do
when visibility in [:public, :unlisted] and collection in [:outbox, :followers, :following], when visibility in [:public, :unlisted] and collection in [:outbox, :followers, :following],
do: true do: true
defp can_get_collection?(_collection_name, %Actor{} = actor, %Actor{} = actor_applicant), defp can_get_collection?(_collection_name, %Actor{} = actor, %Actor{} = actor_applicant) do
do: actor_applicant_group_member?(actor, actor_applicant) Logger.debug(
"Testing if #{actor_applicant.url} can be allowed access to #{actor.url} private collections"
)
actor_applicant_group_member?(actor, actor_applicant)
end
defp can_get_collection?(_, _, _), do: false defp can_get_collection?(_, _, _), do: false

View File

@ -20,11 +20,7 @@ defmodule Mobilizon.Mixfile do
coveralls: :test, coveralls: :test,
"coveralls.detail": :test, "coveralls.detail": :test,
"coveralls.post": :test, "coveralls.post": :test,
"coveralls.html": :test, "coveralls.html": :test
vcr: :test,
"vcr.delete": :test,
"vcr.check": :test,
"vcr.show": :test
], ],
name: "Mobilizon", name: "Mobilizon",
source_url: "https://framagit.org/framasoft/mobilizon", source_url: "https://framagit.org/framasoft/mobilizon",
@ -216,7 +212,6 @@ defmodule Mobilizon.Mixfile do
{:mix_test_watch, "~> 1.0", only: :dev, runtime: false}, {:mix_test_watch, "~> 1.0", only: :dev, runtime: false},
{:ex_unit_notifier, "~> 1.0", only: :test}, {:ex_unit_notifier, "~> 1.0", only: :test},
{:dialyxir, "~> 1.1", only: [:dev], runtime: false}, {:dialyxir, "~> 1.1", only: [:dev], runtime: false},
{:exvcr, "~> 0.12", only: :test},
{:credo, "~> 1.5", only: [:dev, :test], runtime: false}, {:credo, "~> 1.5", only: [:dev, :test], runtime: false},
{:mock, "~> 0.3.4", only: :test}, {:mock, "~> 0.3.4", only: :test},
{:elixir_feed_parser, "~> 2.1.0", only: :test}, {:elixir_feed_parser, "~> 2.1.0", only: :test},

View File

@ -53,7 +53,6 @@
"exgravatar": {:hex, :exgravatar, "2.0.2", "638412896170409da114f98947d3f8d4f38e851b0e329c1cc4cd324d5e2ea081", [:mix], [], "hexpm", "f3deb5baa6fcf354a965d794ee73a956d95f1f79f41bddf69800c713cfb014a1"}, "exgravatar": {:hex, :exgravatar, "2.0.2", "638412896170409da114f98947d3f8d4f38e851b0e329c1cc4cd324d5e2ea081", [:mix], [], "hexpm", "f3deb5baa6fcf354a965d794ee73a956d95f1f79f41bddf69800c713cfb014a1"},
"exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm", "32e95820a97cffea67830e91514a2ad53b888850442d6d395f53a1ac60c82e07"}, "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm", "32e95820a97cffea67830e91514a2ad53b888850442d6d395f53a1ac60c82e07"},
"export": {:hex, :export, "0.1.1", "6dfd268b0692428f89b9285859a2dc02b6dcd2e8fdfbca34ac6e6a331351df91", [:mix], [{:erlport, "~> 0.9", [hex: :erlport, repo: "hexpm", optional: false]}], "hexpm", "3da7444ff4053f1824352f4bdb13fbd2c28c93c2011786fb686b649fdca1021f"}, "export": {:hex, :export, "0.1.1", "6dfd268b0692428f89b9285859a2dc02b6dcd2e8fdfbca34ac6e6a331351df91", [:mix], [{:erlport, "~> 0.9", [hex: :erlport, repo: "hexpm", optional: false]}], "hexpm", "3da7444ff4053f1824352f4bdb13fbd2c28c93c2011786fb686b649fdca1021f"},
"exvcr": {:hex, :exvcr, "0.13.2", "e17fd3ee3a341f41a3aa65a3ce73a339759a9d0658f83782492c6e9b6cf9daa4", [:mix], [{:exactor, "~> 2.2", [hex: :exactor, repo: "hexpm", optional: false]}, {:exjsx, "~> 4.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:finch, "~> 0.8.0", [hex: :finch, repo: "hexpm", optional: true]}, {:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: true]}, {:httpotion, "~> 3.1", [hex: :httpotion, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:meck, "~> 0.8", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "17f41a533d14f582fe6b5f83214f058cf5ba77c6a7bc15bc53a9ea1827d92d96"},
"fast_html": {:hex, :fast_html, "2.0.4", "4910ee49f2f6b19692e3bf30bf97f1b6b7dac489cd6b0f34cd0fe3042c56ba30", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}], "hexpm", "3bb49d541dfc02ad5e425904f53376d758c09f89e521afc7d2b174b3227761ea"}, "fast_html": {:hex, :fast_html, "2.0.4", "4910ee49f2f6b19692e3bf30bf97f1b6b7dac489cd6b0f34cd0fe3042c56ba30", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}], "hexpm", "3bb49d541dfc02ad5e425904f53376d758c09f89e521afc7d2b174b3227761ea"},
"fast_sanitize": {:hex, :fast_sanitize, "0.2.2", "3cbbaebaea6043865dfb5b4ecb0f1af066ad410a51470e353714b10c42007b81", [:mix], [{:fast_html, "~> 2.0", [hex: :fast_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "69f204db9250afa94a0d559d9110139850f57de2b081719fbafa1e9a89e94466"}, "fast_sanitize": {:hex, :fast_sanitize, "0.2.2", "3cbbaebaea6043865dfb5b4ecb0f1af066ad410a51470e353714b10c42007b81", [:mix], [{:fast_html, "~> 2.0", [hex: :fast_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "69f204db9250afa94a0d559d9110139850f57de2b081719fbafa1e9a89e94466"},
"file_info": {:hex, :file_info, "0.0.4", "2e0e77f211e833f38ead22cb29ce53761d457d80b3ffe0ffe0eb93880b0963b2", [:mix], [{:mimetype_parser, "~> 0.1.2", [hex: :mimetype_parser, repo: "hexpm", optional: false]}], "hexpm", "50e7ad01c2c8b9339010675fe4dc4a113b8d6ca7eddce24d1d74fd0e762781a5"}, "file_info": {:hex, :file_info, "0.0.4", "2e0e77f211e833f38ead22cb29ce53761d457d80b3ffe0ffe0eb93880b0963b2", [:mix], [{:mimetype_parser, "~> 0.1.2", [hex: :mimetype_parser, repo: "hexpm", optional: false]}], "hexpm", "50e7ad01c2c8b9339010675fe4dc4a113b8d6ca7eddce24d1d74fd0e762781a5"},

View File

@ -43,7 +43,7 @@ msgstr "%{member} a été invité⋅e par %{profile}."
#: lib/service/activity/renderer/member.ex:50 lib/web/templates/email/activity/_member_activity_item.html.heex:40 #: lib/service/activity/renderer/member.ex:50 lib/web/templates/email/activity/_member_activity_item.html.heex:40
#: lib/web/templates/email/activity/_member_activity_item.text.eex:27 #: lib/web/templates/email/activity/_member_activity_item.text.eex:27
msgid "%{profile} added the member %{member}." msgid "%{profile} added the member %{member}."
msgstr "%{profile} a ajouté le ou la membre %{membre}." msgstr "%{profile} a ajouté le ou la membre %{member}."
#: lib/service/activity/renderer/discussion.ex:65 lib/web/templates/email/activity/_discussion_activity_item.html.heex:46 #: lib/service/activity/renderer/discussion.ex:65 lib/web/templates/email/activity/_discussion_activity_item.html.heex:46
#: lib/web/templates/email/activity/_discussion_activity_item.text.eex:19 #: lib/web/templates/email/activity/_discussion_activity_item.text.eex:19
@ -87,7 +87,7 @@ msgstr "%{profile} a supprimé la resource %{resource}."
#: lib/service/activity/renderer/member.ex:66 lib/web/templates/email/activity/_member_activity_item.html.heex:56 #: lib/service/activity/renderer/member.ex:66 lib/web/templates/email/activity/_member_activity_item.html.heex:56
#: lib/web/templates/email/activity/_member_activity_item.text.eex:39 #: lib/web/templates/email/activity/_member_activity_item.text.eex:39
msgid "%{profile} excluded member %{member}." msgid "%{profile} excluded member %{member}."
msgstr "%{profile} a exclu le ou la membre %{membre}." msgstr "%{profile} a exclu le ou la membre %{member}."
#: lib/service/activity/renderer/resource.ex:76 lib/web/templates/email/activity/_resource_activity_item.html.heex:71 #: lib/service/activity/renderer/resource.ex:76 lib/web/templates/email/activity/_resource_activity_item.html.heex:71
#: lib/web/templates/email/activity/_resource_activity_item.text.eex:28 #: lib/web/templates/email/activity/_resource_activity_item.text.eex:28

View File

@ -4,7 +4,6 @@
# Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/test/web/activity_pub/activity_pub_test.exs # Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/test/web/activity_pub/activity_pub_test.exs
defmodule Mobilizon.Federation.ActivityPubTest do defmodule Mobilizon.Federation.ActivityPubTest do
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
use Mobilizon.DataCase use Mobilizon.DataCase
import Mock import Mock
@ -47,10 +46,17 @@ defmodule Mobilizon.Federation.ActivityPubTest do
File.read!("test/fixtures/mastodon-status-2.json") File.read!("test/fixtures/mastodon-status-2.json")
|> Jason.decode!() |> Jason.decode!()
actor_data =
File.read!("test/fixtures/mastodon-actor.json")
|> Jason.decode!()
Mock Mock
|> expect(:call, fn |> expect(:call, 2, fn
%{method: :get, url: ^url}, _opts -> %{method: :get, url: ^url}, _opts ->
{:ok, %Tesla.Env{status: 200, body: data}} {:ok, %Tesla.Env{status: 200, body: data}}
%{method: :get, url: "https://framapiaf.org/users/Framasoft"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
end) end)
{:ok, object} = ActivityPub.fetch_object_from_url(url) {:ok, object} = ActivityPub.fetch_object_from_url(url)
@ -72,13 +78,20 @@ defmodule Mobilizon.Federation.ActivityPubTest do
File.read!("test/fixtures/mastodon-status-4.json") File.read!("test/fixtures/mastodon-status-4.json")
|> Jason.decode!() |> Jason.decode!()
actor_data =
File.read!("test/fixtures/mastodon-actor.json")
|> Jason.decode!()
Mock Mock
|> expect(:call, 2, fn |> expect(:call, 3, fn
%{method: :get, url: ^url}, _opts -> %{method: :get, url: ^url}, _opts ->
{:ok, %Tesla.Env{status: 200, body: data}} {:ok, %Tesla.Env{status: 200, body: data}}
%{method: :get, url: ^reply_to_url}, _opts -> %{method: :get, url: ^reply_to_url}, _opts ->
{:ok, %Tesla.Env{status: 200, body: reply_to_data}} {:ok, %Tesla.Env{status: 200, body: reply_to_data}}
%{method: :get, url: "https://pirateradio.social/users/captain"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
end) end)
{:ok, object} = ActivityPub.fetch_object_from_url(url) {:ok, object} = ActivityPub.fetch_object_from_url(url)
@ -98,13 +111,26 @@ defmodule Mobilizon.Federation.ActivityPubTest do
File.read!("test/fixtures/peertube-video.json") File.read!("test/fixtures/peertube-video.json")
|> Jason.decode!() |> Jason.decode!()
actor_data =
File.read!("test/fixtures/mastodon-actor.json")
|> Jason.decode!()
Mock Mock
|> expect(:call, 2, fn |> expect(:call, 5, fn
%{method: :get, url: ^url}, _opts -> %{method: :get, url: ^url}, _opts ->
{:ok, %Tesla.Env{status: 200, body: data}} {:ok, %Tesla.Env{status: 200, body: data}}
%{method: :get, url: ^origin_url}, _opts -> %{method: :get, url: ^origin_url}, _opts ->
{:ok, %Tesla.Env{status: 200, body: origin_data}} {:ok, %Tesla.Env{status: 200, body: origin_data}}
%{method: :get, url: "https://diaspodon.fr/users/dada"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
%{method: :get, url: "https://framatube.org/accounts/framasoft"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
%{method: :get, url: "https://framapiaf.org/users/Pouhiou"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
end) end)
{:ok, object} = ActivityPub.fetch_object_from_url(url) {:ok, object} = ActivityPub.fetch_object_from_url(url)

View File

@ -1,39 +1,116 @@
defmodule Mobilizon.Federation.ActivityPub.ActorTest do defmodule Mobilizon.Federation.ActivityPub.ActorTest do
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
use Mobilizon.DataCase use Mobilizon.DataCase
import Mox
import Mock import Mock
alias Mobilizon.Actors alias Mobilizon.Actors
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Federation.ActivityPub.Actor, as: ActivityPubActor alias Mobilizon.Federation.ActivityPub.Actor, as: ActivityPubActor
alias Mobilizon.Federation.ActivityPub.{Fetcher, Relay} alias Mobilizon.Federation.ActivityPub.Relay
alias Mobilizon.Service.HTTP.ActivityPub.Mock
alias Mobilizon.Service.HTTP.HostMetaClient.Mock, as: HostMetaClientMock
alias Mobilizon.Service.HTTP.WebfingerClient.Mock, as: WebfingerClientMock
describe "fetching actor from its url" do describe "fetching actor from its url" do
@actor_url "https://framapiaf.org/users/tcit"
test "returns an actor from nickname" do test "returns an actor from nickname" do
use_cassette "activity_pub/fetch_tcit@framapiaf.org" do actor_data =
File.read!("test/fixtures/mastodon-actor.json")
|> Jason.decode!()
|> Map.put("id", @actor_url)
|> Map.put("preferredUsername", "tcit")
|> Map.put("discoverable", true)
Mock
|> expect(:call, fn
%{method: :get, url: @actor_url}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
end)
HostMetaClientMock
|> expect(:call, fn
%{method: :get, url: "http://framapiaf.org/.well-known/host-meta"}, _opts ->
{:ok, %Tesla.Env{status: 404, body: ""}}
end)
webfinger_data =
File.read!("test/fixtures/webfinger/mastodon-webfinger.json")
|> String.replace("social.tcit.fr", "framapiaf.org")
|> Jason.decode!()
WebfingerClientMock
|> expect(:call, fn
%{
method: :get,
url: "http://framapiaf.org/.well-known/webfinger?resource=acct:tcit@framapiaf.org"
},
_opts ->
{:ok, %Tesla.Env{status: 200, body: webfinger_data}}
end)
assert {:ok, assert {:ok,
%Actor{preferred_username: "tcit", domain: "framapiaf.org", visibility: :public} = %Actor{preferred_username: "tcit", domain: "framapiaf.org", visibility: :public} =
_actor} = ActivityPubActor.make_actor_from_nickname("tcit@framapiaf.org") _actor} = ActivityPubActor.make_actor_from_nickname("tcit@framapiaf.org")
end end
use_cassette "activity_pub/fetch_tcit@framapiaf.org_not_discoverable" do test "returns an actor from nickname when not discoverable" do
actor_data =
File.read!("test/fixtures/mastodon-actor.json")
|> Jason.decode!()
|> Map.put("id", @actor_url)
|> Map.put("preferredUsername", "tcit")
Mock
|> expect(:call, fn
%{method: :get, url: @actor_url}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
end)
HostMetaClientMock
|> expect(:call, fn
%{method: :get, url: "http://framapiaf.org/.well-known/host-meta"}, _opts ->
{:ok, %Tesla.Env{status: 404, body: ""}}
end)
webfinger_data =
File.read!("test/fixtures/webfinger/mastodon-webfinger.json")
|> String.replace("social.tcit.fr", "framapiaf.org")
|> Jason.decode!()
WebfingerClientMock
|> expect(:call, fn
%{
method: :get,
url: "http://framapiaf.org/.well-known/webfinger?resource=acct:tcit@framapiaf.org"
},
_opts ->
{:ok, %Tesla.Env{status: 200, body: webfinger_data}}
end)
assert {:ok, assert {:ok,
%Actor{preferred_username: "tcit", domain: "framapiaf.org", visibility: :unlisted} = %Actor{preferred_username: "tcit", domain: "framapiaf.org", visibility: :unlisted} =
_actor} = ActivityPubActor.make_actor_from_nickname("tcit@framapiaf.org") _actor} = ActivityPubActor.make_actor_from_nickname("tcit@framapiaf.org")
end end
end
@actor_url "https://framapiaf.org/users/tcit"
test "returns an actor from url" do test "returns an actor from url" do
actor_data =
File.read!("test/fixtures/mastodon-actor.json")
|> Jason.decode!()
|> Map.put("id", @actor_url)
|> Map.put("preferredUsername", "tcit")
Mock
|> expect(:call, fn
%{method: :get, url: @actor_url}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
end)
# Initial fetch # Initial fetch
use_cassette "activity_pub/fetch_framapiaf.org_users_tcit" do
# Unlisted because discoverable is not present in the JSON payload # Unlisted because discoverable is not present in the JSON payload
assert {:ok, assert {:ok,
%Actor{preferred_username: "tcit", domain: "framapiaf.org", visibility: :unlisted}} = %Actor{preferred_username: "tcit", domain: "framapiaf.org", visibility: :unlisted}} =
ActivityPubActor.get_or_fetch_actor_by_url(@actor_url) ActivityPubActor.get_or_fetch_actor_by_url(@actor_url)
end
# Fetch uses cache if Actors.needs_update? returns false # Fetch uses cache if Actors.needs_update? returns false
with_mocks([ with_mocks([
@ -49,7 +126,7 @@ defmodule Mobilizon.Federation.ActivityPub.ActorTest do
needs_update?: fn _ -> false end needs_update?: fn _ -> false end
]}, ]},
{ActivityPubActor, [:passthrough], {ActivityPubActor, [:passthrough],
make_actor_from_url: fn @actor_url, false -> make_actor_from_url: fn @actor_url, preload: false ->
{:ok, {:ok,
%Actor{ %Actor{
preferred_username: "tcit", preferred_username: "tcit",
@ -61,7 +138,7 @@ defmodule Mobilizon.Federation.ActivityPub.ActorTest do
ActivityPubActor.get_or_fetch_actor_by_url(@actor_url) ActivityPubActor.get_or_fetch_actor_by_url(@actor_url)
assert_called(Actors.needs_update?(:_)) assert_called(Actors.needs_update?(:_))
refute called(ActivityPubActor.make_actor_from_url(@actor_url, false)) refute called(ActivityPubActor.make_actor_from_url(@actor_url, preload: false))
end end
# Fetch doesn't use cache if Actors.needs_update? returns true # Fetch doesn't use cache if Actors.needs_update? returns true
@ -78,7 +155,7 @@ defmodule Mobilizon.Federation.ActivityPub.ActorTest do
needs_update?: fn _ -> true end needs_update?: fn _ -> true end
]}, ]},
{ActivityPubActor, [:passthrough], {ActivityPubActor, [:passthrough],
make_actor_from_url: fn @actor_url, false -> make_actor_from_url: fn @actor_url, preload: false ->
{:ok, {:ok,
%Actor{ %Actor{
preferred_username: "tcit", preferred_username: "tcit",
@ -92,24 +169,21 @@ defmodule Mobilizon.Federation.ActivityPub.ActorTest do
assert_called(ActivityPubActor.get_or_fetch_actor_by_url(@actor_url)) assert_called(ActivityPubActor.get_or_fetch_actor_by_url(@actor_url))
assert_called(Actors.get_actor_by_url(@actor_url, false)) assert_called(Actors.get_actor_by_url(@actor_url, false))
assert_called(Actors.needs_update?(:_)) assert_called(Actors.needs_update?(:_))
assert_called(ActivityPubActor.make_actor_from_url(@actor_url, false)) assert_called(ActivityPubActor.make_actor_from_url(@actor_url, preload: false))
end end
end end
test "handles remote actor being deleted" do test "handles remote actor being deleted" do
with_mocks([ Mock
{Fetcher, [:passthrough], |> expect(:call, fn
fetch_and_prepare_actor_from_url: fn @actor_url -> %{method: :get, url: @actor_url}, _opts ->
{:error, :actor_deleted} {:ok, %Tesla.Env{status: 410, body: ""}}
end} end)
]) do
assert match?( assert match?(
{:error, :actor_deleted}, {:error, :actor_deleted},
ActivityPubActor.make_actor_from_url(@actor_url, false) ActivityPubActor.make_actor_from_url(@actor_url, preload: false)
) )
assert_called(Fetcher.fetch_and_prepare_actor_from_url(@actor_url))
end
end end
@public_url "https://www.w3.org/ns/activitystreams#Public" @public_url "https://www.w3.org/ns/activitystreams#Public"

View File

@ -36,12 +36,79 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.CommentsTest do
end end
test "it fetches replied-to activities if we don't have them" do test "it fetches replied-to activities if we don't have them" do
data = actor_data = File.read!("test/fixtures/mastodon-actor.json") |> Jason.decode!()
File.read!("test/fixtures/mastodon-post-activity.json") status_data = File.read!("test/fixtures/mastodon-status-2.json") |> Jason.decode!()
reply_to_data =
File.read!("test/fixtures/pleroma-comment-object.json")
|> Jason.decode!() |> Jason.decode!()
reply_to_url = "https://fedi.absturztau.be/objects/1726cdc7-4f2a-4ddb-9c68-03d27c98c3d9" reply_to_url = "https://fedi.absturztau.be/objects/1726cdc7-4f2a-4ddb-9c68-03d27c98c3d9"
Mock
|> expect(:call, 5, fn
%{method: :get, url: "https://framapiaf.org/users/admin"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body:
actor_data
|> Map.put("id", "https://framapiaf.org/users/admin")
|> Map.put("preferredUsername", "admin")
}}
%{method: :get, url: "https://framapiaf.org/users/tcit"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body:
actor_data
|> Map.put("id", "https://framapiaf.org/users/tcit")
|> Map.put("preferredUsername", "tcit")
}}
%{method: :get, url: "https://framapiaf.org/users/Framasoft"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body:
actor_data
|> Map.put("id", "https://framapiaf.org/users/Framasoft")
|> Map.put("preferredUsername", "Framasoft")
}}
%{
method: :get,
url: "https://fedi.absturztau.be/objects/1726cdc7-4f2a-4ddb-9c68-03d27c98c3d9"
},
_opts ->
{:ok,
%Tesla.Env{
status: 200,
body:
status_data
|> Map.put(
"id",
"https://fedi.absturztau.be/objects/1726cdc7-4f2a-4ddb-9c68-03d27c98c3d9"
)
|> Map.put("actor", "https://fedi.absturztau.be/users/dqn")
}}
%{method: :get, url: "https://fedi.absturztau.be/users/dqn"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body: Map.put(actor_data, "id", "https://fedi.absturztau.be/users/dqn")
}}
%{method: :get, url: ^reply_to_url}, _opts ->
{:ok, %Tesla.Env{status: 200, body: reply_to_data}}
end)
data =
File.read!("test/fixtures/mastodon-post-activity.json")
|> Jason.decode!()
object = object =
data["object"] data["object"]
|> Map.put("inReplyTo", reply_to_url) |> Map.put("inReplyTo", reply_to_url)
@ -50,16 +117,6 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.CommentsTest do
data data
|> Map.put("object", object) |> Map.put("object", object)
reply_to_data =
File.read!("test/fixtures/pleroma-comment-object.json")
|> Jason.decode!()
Mock
|> expect(:call, fn
%{method: :get, url: ^reply_to_url}, _opts ->
{:ok, %Tesla.Env{status: 200, body: reply_to_data}}
end)
{:ok, returned_activity, _} = Transmogrifier.handle_incoming(data) {:ok, returned_activity, _} = Transmogrifier.handle_incoming(data)
%Comment{} = %Comment{} =
@ -75,6 +132,25 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.CommentsTest do
end end
test "it doesn't saves replies to an event if the event doesn't accept comments" do test "it doesn't saves replies to an event if the event doesn't accept comments" do
actor_data = File.read!("test/fixtures/mastodon-actor.json") |> Jason.decode!()
Mock
|> expect(:call, 2, fn
%{method: :get, url: "https://framapiaf.org/users/admin"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body: Map.put(actor_data, "id", "https://framapiaf.org/users/admin")
}}
%{method: :get, url: "https://framapiaf.org/users/tcit"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body: Map.put(actor_data, "id", "https://framapiaf.org/users/tcit")
}}
end)
data = data =
File.read!("test/fixtures/mastodon-post-activity.json") File.read!("test/fixtures/mastodon-post-activity.json")
|> Jason.decode!() |> Jason.decode!()
@ -94,6 +170,31 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.CommentsTest do
@url_404 "https://404.site/whatever" @url_404 "https://404.site/whatever"
test "it does not crash if the object in inReplyTo can't be fetched" do test "it does not crash if the object in inReplyTo can't be fetched" do
actor_data = File.read!("test/fixtures/mastodon-actor.json") |> Jason.decode!()
Mock
|> expect(:call, 2, fn
%{method: :get, url: "https://framapiaf.org/users/admin"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body:
actor_data
|> Map.put("id", "https://framapiaf.org/users/admin")
|> Map.put("preferredUsername", "admin")
}}
%{method: :get, url: "https://framapiaf.org/users/tcit"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body:
actor_data
|> Map.put("id", "https://framapiaf.org/users/tcit")
|> Map.put("preferredUsername", "tcit")
}}
end)
data = data =
File.read!("test/fixtures/mastodon-post-activity.json") File.read!("test/fixtures/mastodon-post-activity.json")
|> Jason.decode!() |> Jason.decode!()
@ -118,6 +219,31 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.CommentsTest do
end end
test "it ignores incoming private notes" do test "it ignores incoming private notes" do
actor_data = File.read!("test/fixtures/mastodon-actor.json") |> Jason.decode!()
Mock
|> expect(:call, 2, fn
%{method: :get, url: "https://framapiaf.org/users/admin"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body:
actor_data
|> Map.put("id", "https://framapiaf.org/users/admin")
|> Map.put("preferredUsername", "admin")
}}
%{method: :get, url: "https://framapiaf.org/users/tcit"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body:
actor_data
|> Map.put("id", "https://framapiaf.org/users/tcit")
|> Map.put("preferredUsername", "tcit")
}}
end)
data = File.read!("test/fixtures/mastodon-post-activity-private.json") |> Jason.decode!() data = File.read!("test/fixtures/mastodon-post-activity-private.json") |> Jason.decode!()
event = insert(:event) event = insert(:event)
object = data["object"] object = data["object"]
@ -128,16 +254,33 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.CommentsTest do
end end
test "it works for incoming notices" do test "it works for incoming notices" do
actor_data = File.read!("test/fixtures/mastodon-actor.json") |> Jason.decode!()
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!() data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!()
Mock
|> expect(:call, 2, fn
%{method: :get, url: "https://framapiaf.org/users/admin"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body: Map.put(actor_data, "id", "https://framapiaf.org/users/admin")
}}
%{method: :get, url: "https://framapiaf.org/users/tcit"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body: Map.put(actor_data, "id", "https://framapiaf.org/users/tcit")
}}
end)
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data) {:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
assert data["id"] == assert data["id"] ==
"https://framapiaf.org/users/admin/statuses/99512778738411822/activity" "https://framapiaf.org/users/admin/statuses/99512778738411822/activity"
assert data["to"] == [ assert data["to"] == [
"https://www.w3.org/ns/activitystreams#Public", "https://www.w3.org/ns/activitystreams#Public"
"https://framapiaf.org/users/tcit"
] ]
# assert data["cc"] == [ # assert data["cc"] == [
@ -164,6 +307,31 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.CommentsTest do
end end
test "it works for incoming notices with hashtags" do test "it works for incoming notices with hashtags" do
actor_data = File.read!("test/fixtures/mastodon-actor.json") |> Jason.decode!()
Mock
|> expect(:call, 2, fn
%{method: :get, url: "https://framapiaf.org/users/admin"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body:
actor_data
|> Map.put("id", "https://framapiaf.org/users/admin")
|> Map.put("preferredUsername", "admin")
}}
%{method: :get, url: "https://framapiaf.org/users/tcit"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body:
actor_data
|> Map.put("id", "https://framapiaf.org/users/tcit")
|> Map.put("preferredUsername", "tcit")
}}
end)
data = File.read!("test/fixtures/mastodon-post-activity-hashtag.json") |> Jason.decode!() data = File.read!("test/fixtures/mastodon-post-activity-hashtag.json") |> Jason.decode!()
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data) {:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)

View File

@ -1,6 +1,5 @@
defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.DeleteTest do defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.DeleteTest do
use Mobilizon.DataCase use Mobilizon.DataCase
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
use Oban.Testing, repo: Mobilizon.Storage.Repo use Oban.Testing, repo: Mobilizon.Storage.Repo
import Mobilizon.Factory import Mobilizon.Factory
import Mox import Mox
@ -56,6 +55,19 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.DeleteTest do
end end
test "it fails for incoming deletes with spoofed origin" do test "it fails for incoming deletes with spoofed origin" do
actor_data =
File.read!("test/fixtures/mastodon-actor.json")
|> Jason.decode!()
Mock
|> expect(:call, 2, fn
%{method: :get, url: "https://framapiaf.org/users/peertube"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
%{method: :get, url: "http://mastodon.example.org/users/gargron"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
end)
comment = insert(:comment) comment = insert(:comment)
announce_data = announce_data =
@ -77,7 +89,7 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.DeleteTest do
data data
|> Map.put("object", object) |> Map.put("object", object)
{:error, :unknown_actor} = Transmogrifier.handle_incoming(data) :error = Transmogrifier.handle_incoming(data)
assert Discussions.get_comment_from_url(comment.url) assert Discussions.get_comment_from_url(comment.url)
end end
@ -132,12 +144,12 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.DeleteTest do
|> Map.put("id", deleted_actor_url) |> Map.put("id", deleted_actor_url)
Mock Mock
|> expect(:call, fn |> expect(:call, 2, fn
%{url: ^deleted_actor_url}, _opts -> %{url: ^deleted_actor_url}, _opts ->
{:ok, %Tesla.Env{status: 200, body: deleted_actor_data}} {:ok, %Tesla.Env{status: 200, body: deleted_actor_data}}
end) end)
assert :error == Transmogrifier.handle_incoming(data) assert {:error, "Group object URL remote"} == Transmogrifier.handle_incoming(data)
assert Actors.get_actor_by_url(url) assert Actors.get_actor_by_url(url)
end end

View File

@ -1,16 +1,31 @@
defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.FollowTest do defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.FollowTest do
use Mobilizon.DataCase use Mobilizon.DataCase
import Mox
import ExUnit.CaptureLog import ExUnit.CaptureLog
import Mobilizon.Factory import Mobilizon.Factory
alias Mobilizon.Actors alias Mobilizon.Actors
alias Mobilizon.Actors.Follower alias Mobilizon.Actors.Follower
alias Mobilizon.Federation.ActivityPub.{Actions, Activity, Transmogrifier} alias Mobilizon.Federation.ActivityPub.{Actions, Activity, Transmogrifier}
alias Mobilizon.Service.HTTP.ActivityPub.Mock
describe "handle incoming follow requests" do describe "handle incoming follow requests" do
test "it works only for groups" do test "it works only for groups" do
actor = insert(:actor) actor = insert(:actor)
actor_data =
File.read!("test/fixtures/mastodon-actor.json")
|> Jason.decode!()
Mock
|> expect(:call, fn
%{method: :get, url: "https://social.tcit.fr/users/tcit"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body: Map.put(actor_data, "id", "https://social.tcit.fr/users/tcit")
}}
end)
data = data =
File.read!("test/fixtures/mastodon-follow-activity.json") File.read!("test/fixtures/mastodon-follow-activity.json")
|> Jason.decode!() |> Jason.decode!()
@ -27,6 +42,20 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.FollowTest do
test "it works for incoming follow requests" do test "it works for incoming follow requests" do
actor = insert(:group) actor = insert(:group)
actor_data =
File.read!("test/fixtures/mastodon-actor.json")
|> Jason.decode!()
Mock
|> expect(:call, fn
%{method: :get, url: "https://social.tcit.fr/users/tcit"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body: Map.put(actor_data, "id", "https://social.tcit.fr/users/tcit")
}}
end)
data = data =
File.read!("test/fixtures/mastodon-follow-activity.json") File.read!("test/fixtures/mastodon-follow-activity.json")
|> Jason.decode!() |> Jason.decode!()

View File

@ -22,9 +22,12 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.UndoTest do
|> Jason.decode!() |> Jason.decode!()
Mock Mock
|> expect(:call, fn |> expect(:call, 2, fn
%{method: :get, url: "https://framapiaf.org/users/Framasoft"}, _opts -> %{method: :get, url: "https://framapiaf.org/users/Framasoft"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}} {:ok, %Tesla.Env{status: 200, body: actor_data}}
%{method: :get, url: "https://framapiaf.org/users/peertube"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
end) end)
{:ok, _, %Comment{}} = Transmogrifier.handle_incoming(announce_data) {:ok, _, %Comment{}} = Transmogrifier.handle_incoming(announce_data)

View File

@ -1,8 +1,8 @@
defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.UpdateTest do defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.UpdateTest do
use Mobilizon.DataCase use Mobilizon.DataCase
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
use Oban.Testing, repo: Mobilizon.Storage.Repo use Oban.Testing, repo: Mobilizon.Storage.Repo
import Mobilizon.Factory import Mobilizon.Factory
import Mox
alias Mobilizon.{Actors, Events, Posts} alias Mobilizon.{Actors, Events, Posts}
alias Mobilizon.Actors.{Actor, Member} alias Mobilizon.Actors.{Actor, Member}
@ -10,12 +10,25 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.UpdateTest do
alias Mobilizon.Posts.Post alias Mobilizon.Posts.Post
alias Mobilizon.Federation.ActivityPub.{Activity, Transmogrifier} alias Mobilizon.Federation.ActivityPub.{Activity, Transmogrifier}
alias Mobilizon.Federation.ActivityStream.Convertible alias Mobilizon.Federation.ActivityStream.Convertible
alias Mobilizon.Service.HTTP.ActivityPub.Mock
describe "handle incoming update activities" do describe "handle incoming update activities" do
test "it works for incoming update activities on actors" do test "it works for incoming update activities on actors" do
use_cassette "activity_pub/update_actor_activity" do
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!() data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!()
actor_data =
File.read!("test/fixtures/mastodon-actor.json")
|> Jason.decode!()
Mock
|> expect(:call, 2, fn
%{method: :get, url: "https://framapiaf.org/users/admin"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
%{method: :get, url: "https://framapiaf.org/users/tcit"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
end)
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data) {:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
update_data = File.read!("test/fixtures/mastodon-update.json") |> Jason.decode!() update_data = File.read!("test/fixtures/mastodon-update.json") |> Jason.decode!()
@ -29,20 +42,30 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.UpdateTest do
|> Map.put("actor", data["actor"]) |> Map.put("actor", data["actor"])
|> Map.put("object", object) |> Map.put("object", object)
{:ok, %Activity{data: _data, local: false}, _} = {:ok, %Activity{data: _data, local: false}, _} = Transmogrifier.handle_incoming(update_data)
Transmogrifier.handle_incoming(update_data)
{:ok, %Actor{} = actor} = Actors.get_actor_by_url(update_data["actor"]) {:ok, %Actor{} = actor} = Actors.get_actor_by_url(update_data["actor"])
assert actor.name == "nextsoft" assert actor.name == "nextsoft"
assert actor.summary == "<p>Some bio</p>" assert actor.summary == "<p>Some bio</p>"
end end
end
test "it works for incoming update activities on events" do test "it works for incoming update activities on events" do
use_cassette "activity_pub/event_update_activities" do
data = File.read!("test/fixtures/mobilizon-post-activity.json") |> Jason.decode!() data = File.read!("test/fixtures/mobilizon-post-activity.json") |> Jason.decode!()
actor_data =
File.read!("test/fixtures/mastodon-actor.json")
|> Jason.decode!()
Mock
|> expect(:call, 2, fn
%{method: :get, url: "https://mobilizon.fr/@metacartes"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
%{method: :get, url: "https://framapiaf.org/users/tcit"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
end)
{:ok, %Activity{data: data, local: false}, %Event{id: event_id}} = {:ok, %Activity{data: data, local: false}, %Event{id: event_id}} =
Transmogrifier.handle_incoming(data) Transmogrifier.handle_incoming(data)
@ -67,8 +90,7 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.UpdateTest do
|> Map.put("actor", data["actor"]) |> Map.put("actor", data["actor"])
|> Map.put("object", object) |> Map.put("object", object)
{:ok, %Activity{data: data, local: false}, _} = {:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(update_data)
Transmogrifier.handle_incoming(update_data)
%Event{} = event = Events.get_event_by_url(data["object"]["id"]) %Event{} = event = Events.get_event_by_url(data["object"]["id"])
@ -83,7 +105,6 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.UpdateTest do
assert event.description == data["object"]["content"] assert event.description == data["object"]["content"]
end end
end
# test "it works for incoming update activities which lock the account" do # test "it works for incoming update activities which lock the account" do
# data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!() # data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!()

View File

@ -4,8 +4,6 @@
# Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/test/web/activity_pub/transmogrifier_test.exs # Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/test/web/activity_pub/transmogrifier_test.exs
defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
use Mobilizon.DataCase use Mobilizon.DataCase
use Oban.Testing, repo: Mobilizon.Storage.Repo use Oban.Testing, repo: Mobilizon.Storage.Repo
@ -33,7 +31,22 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
describe "handle incoming events" do describe "handle incoming events" do
test "it works for incoming events" do test "it works for incoming events" do
use_cassette "activity_pub/fetch_mobilizon_post_activity" do actor_data = File.read!("test/fixtures/mastodon-actor.json") |> Jason.decode!()
Mock
|> expect(:call, 2, fn
%{method: :get, url: url}, _opts ->
case url do
"https://mobilizon.fr/@metacartes" ->
actor_data = Map.put(actor_data, "id", "https://mobilizon.fr/@metacartes")
{:ok, %Tesla.Env{status: 200, body: actor_data}}
"https://framapiaf.org/users/tcit" ->
actor_data = Map.put(actor_data, "id", "https://framapiaf.org/users/tcit")
{:ok, %Tesla.Env{status: 200, body: actor_data}}
end
end)
data = File.read!("test/fixtures/mobilizon-post-activity.json") |> Jason.decode!() data = File.read!("test/fixtures/mobilizon-post-activity.json") |> Jason.decode!()
{:ok, %Activity{data: data, local: false}, %Event{} = event} = {:ok, %Activity{data: data, local: false}, %Event{} = event} =
@ -77,10 +90,16 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
{:ok, %Actor{}} = Actors.get_actor_by_url(object["actor"]) {:ok, %Actor{}} = Actors.get_actor_by_url(object["actor"])
end end
end
test "it works for incoming events from Gancio" do test "it works for incoming events from Gancio" do
data = File.read!("test/fixtures/gancio-event-activity.json") |> Jason.decode!() data = File.read!("test/fixtures/gancio-event-activity.json") |> Jason.decode!()
actor_data = File.read!("test/fixtures/gancio-actor.json") |> Jason.decode!()
Mock
|> expect(:call, fn
%{method: :get, url: "https://demo.gancio.org/federation/u/gancio"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
end)
{:ok, %Activity{data: data, local: false}, %Event{} = event} = {:ok, %Activity{data: data, local: false}, %Event{} = event} =
Transmogrifier.handle_incoming(data) Transmogrifier.handle_incoming(data)
@ -524,6 +543,12 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
end end
test "it accepts incoming resources and handles group being not found" do test "it accepts incoming resources and handles group being not found" do
Mock
|> expect(:call, fn
%{method: :get, url: "https://someurl.com/notfound"}, _opts ->
{:ok, %Tesla.Env{status: 404, body: ""}}
end)
creator = creator =
insert(:actor, insert(:actor,
domain: "mobilizon.app", domain: "mobilizon.app",
@ -649,12 +674,18 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
test "it works for incoming announces" do test "it works for incoming announces" do
data = File.read!("test/fixtures/mastodon-announce.json") |> Jason.decode!() data = File.read!("test/fixtures/mastodon-announce.json") |> Jason.decode!()
status_data = File.read!("test/fixtures/mastodon-status.json") |> Jason.decode!() status_data = File.read!("test/fixtures/mastodon-status.json") |> Jason.decode!()
actor_data = File.read!("test/fixtures/mastodon-actor.json") |> Jason.decode!()
Mock Mock
|> expect(:call, fn |> expect(:call, 2, fn
%{method: :get, url: "https://framapiaf.org/users/peertube/statuses/104584600044284729"}, %{method: :get, url: url}, _opts ->
_opts -> case url do
"https://framapiaf.org/users/peertube/statuses/104584600044284729" ->
{:ok, %Tesla.Env{status: 200, body: status_data}} {:ok, %Tesla.Env{status: 200, body: status_data}}
"https://framapiaf.org/users/peertube" ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
end
end) end)
{:ok, _, %Comment{actor: %Actor{url: actor_url}, url: comment_url}} = {:ok, _, %Comment{actor: %Actor{url: actor_url}, url: comment_url}} =
@ -677,10 +708,12 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
File.read!("test/fixtures/mastodon-announce.json") File.read!("test/fixtures/mastodon-announce.json")
|> Jason.decode!() |> Jason.decode!()
|> Map.put("object", comment_url) |> Map.put("object", comment_url)
|> Map.put("actor", actor_url)
Mock Mock
|> expect(:call, fn |> expect(:call, fn
%{method: :get, url: ^actor_url}, _opts -> %{method: :get, url: ^actor_url}, _opts ->
actor_data = Map.put(actor_data, "id", actor_url)
{:ok, %Tesla.Env{status: 200, body: actor_data}} {:ok, %Tesla.Env{status: 200, body: actor_data}}
end) end)
@ -926,10 +959,21 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
File.read!("test/fixtures/https__info.pleroma.site_activity.json") File.read!("test/fixtures/https__info.pleroma.site_activity.json")
|> Jason.decode!() |> Jason.decode!()
actor_data =
File.read!("test/fixtures/mastodon-actor.json")
|> Jason.decode!()
|> Map.put("id", "https://framapiaf.org/users/admin")
Mock Mock
|> expect(:call, fn |> expect(:call, 2, fn
%{method: :get, url: "https://info.pleroma.site/activity.json"}, _opts -> %{method: :get, url: url}, _opts ->
case url do
"https://info.pleroma.site/activity.json" ->
{:ok, %Tesla.Env{status: 200, body: data}} {:ok, %Tesla.Env{status: 200, body: data}}
"https://framapiaf.org/users/admin" ->
{:ok, %Tesla.Env{status: 200, body: actor_data}}
end
end) end)
data = %{ data = %{

View File

@ -1,6 +1,4 @@
defmodule Mobilizon.Federation.ActivityPub.UtilsTest do defmodule Mobilizon.Federation.ActivityPub.UtilsTest do
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
use Mobilizon.DataCase use Mobilizon.DataCase
import Mobilizon.Factory import Mobilizon.Factory

View File

@ -4,13 +4,13 @@
# Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/test/web/web_finger/web_finger_test.exs # Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/test/web/web_finger/web_finger_test.exs
defmodule Mobilizon.Federation.WebFingerTest do defmodule Mobilizon.Federation.WebFingerTest do
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
use Mobilizon.DataCase use Mobilizon.DataCase
import Mox
import Mobilizon.Factory import Mobilizon.Factory
alias Mobilizon.Federation.WebFinger alias Mobilizon.Federation.WebFinger
alias Mobilizon.Service.HTTP.HostMetaClient.Mock, as: HostMetaClientMock
alias Mobilizon.Service.HTTP.WebfingerClient.Mock, as: WebfingerClientMock
alias Mobilizon.Web.Endpoint alias Mobilizon.Web.Endpoint
@mastodon_account "tcit@social.tcit.fr" @mastodon_account "tcit@social.tcit.fr"
@ -21,6 +21,8 @@ defmodule Mobilizon.Federation.WebFingerTest do
@peertube_account_username "framasoft" @peertube_account_username "framasoft"
@friendica_account "lain@squeet.me" @friendica_account "lain@squeet.me"
@friendica_account_username "lain" @friendica_account_username "lain"
@gancio_account "gancio@demo.gancio.org"
@gancio_account_username "gancio"
describe "host meta" do describe "host meta" do
test "returns a link to the xml lrdd" do test "returns a link to the xml lrdd" do
@ -53,35 +55,140 @@ defmodule Mobilizon.Federation.WebFingerTest do
describe "fingering" do describe "fingering" do
test "a mastodon actor" do test "a mastodon actor" do
use_cassette "webfinger/mastodon" do host_meta_xml = File.read!("test/fixtures/webfinger/mastodon-host-meta.xml")
webfinger_data =
File.read!("test/fixtures/webfinger/mastodon-webfinger.json") |> Jason.decode!()
WebfingerClientMock
|> expect(:call, fn
%{
method: :get,
url: "https://social.tcit.fr/.well-known/webfinger?resource=acct:tcit@social.tcit.fr"
},
_opts ->
{:ok, %Tesla.Env{status: 200, body: webfinger_data}}
end)
HostMetaClientMock
|> expect(:call, fn
%{method: :get, url: "http://social.tcit.fr/.well-known/host-meta"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: host_meta_xml}}
end)
res = "https://social.tcit.fr/users/#{@mastodon_account_username}" res = "https://social.tcit.fr/users/#{@mastodon_account_username}"
assert {:ok, res} == WebFinger.finger(@mastodon_account) assert {:ok, res} == WebFinger.finger(@mastodon_account)
end end
end
test "a pleroma actor" do test "a pleroma actor" do
use_cassette "webfinger/pleroma" do host_meta_xml = File.read!("test/fixtures/webfinger/pleroma-host-meta.xml")
webfinger_data =
File.read!("test/fixtures/webfinger/pleroma-webfinger.json") |> Jason.decode!()
WebfingerClientMock
|> expect(:call, fn
%{
method: :get,
url:
"https://pleroma.soykaf.com/.well-known/webfinger?resource=acct:lain@pleroma.soykaf.com"
},
_opts ->
{:ok, %Tesla.Env{status: 200, body: webfinger_data}}
end)
HostMetaClientMock
|> expect(:call, fn
%{method: :get, url: "http://pleroma.soykaf.com/.well-known/host-meta"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: host_meta_xml}}
end)
res = "https://pleroma.soykaf.com/users/#{@pleroma_account_username}" res = "https://pleroma.soykaf.com/users/#{@pleroma_account_username}"
assert {:ok, res} == WebFinger.finger(@pleroma_account) assert {:ok, res} == WebFinger.finger(@pleroma_account)
end end
end
test "a peertube actor" do test "a peertube actor" do
use_cassette "webfinger/peertube" do host_meta_xml = File.read!("test/fixtures/webfinger/peertube-host-meta.xml")
webfinger_data =
File.read!("test/fixtures/webfinger/peertube-webfinger.json") |> Jason.decode!()
WebfingerClientMock
|> expect(:call, fn
%{
method: :get,
url: "https://framatube.org/.well-known/webfinger?resource=acct:framasoft@framatube.org"
},
_opts ->
{:ok, %Tesla.Env{status: 200, body: webfinger_data}}
end)
HostMetaClientMock
|> expect(:call, fn
%{method: :get, url: "http://framatube.org/.well-known/host-meta"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: host_meta_xml}}
end)
res = "https://framatube.org/accounts/#{@peertube_account_username}" res = "https://framatube.org/accounts/#{@peertube_account_username}"
assert {:ok, res} == WebFinger.finger(@peertube_account) assert {:ok, res} == WebFinger.finger(@peertube_account)
end end
end
test "a friendica actor" do test "a friendica actor" do
use_cassette "webfinger/friendica" do host_meta_xml = File.read!("test/fixtures/webfinger/friendica-host-meta.xml")
webfinger_data =
File.read!("test/fixtures/webfinger/friendica-webfinger.json") |> Jason.decode!()
WebfingerClientMock
|> expect(:call, fn
%{
method: :get,
url: "https://squeet.me/.well-known/webfinger?resource=acct:lain@squeet.me"
},
_opts ->
{:ok, %Tesla.Env{status: 200, body: webfinger_data}}
end)
HostMetaClientMock
|> expect(:call, fn
%{method: :get, url: "http://squeet.me/.well-known/host-meta"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: host_meta_xml}}
end)
res = "https://squeet.me/profile/#{@friendica_account_username}" res = "https://squeet.me/profile/#{@friendica_account_username}"
assert {:ok, res} == WebFinger.finger(@friendica_account) assert {:ok, res} == WebFinger.finger(@friendica_account)
end end
test "a Gancio actor" do
host_meta_xml = File.read!("test/fixtures/webfinger/gancio-host-meta.xml")
webfinger_data =
File.read!("test/fixtures/webfinger/gancio-webfinger.json") |> Jason.decode!()
WebfingerClientMock
|> expect(:call, fn
%{
method: :get,
url:
"https://demo.gancio.org/.well-known/webfinger?resource=acct:gancio@demo.gancio.org"
},
_opts ->
{:ok, %Tesla.Env{status: 200, body: webfinger_data}}
end)
HostMetaClientMock
|> expect(:call, fn
%{method: :get, url: "http://demo.gancio.org/.well-known/host-meta"}, _opts ->
{:ok, %Tesla.Env{status: 200, body: host_meta_xml}}
end)
res = "https://demo.gancio.org/federation/u/#{@gancio_account_username}"
assert {:ok, res} == WebFinger.finger(@gancio_account)
end end
end end
end end

36
test/fixtures/gancio-actor.json vendored Normal file
View File

@ -0,0 +1,36 @@
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
"toot": "http://joinmastodon.org/ns#",
"schema": "http://schema.org#",
"ProperyValue": "schema:PropertyValue",
"value": "schema:value"
}
],
"id": "https://demo.gancio.org/federation/u/gancio",
"type": "Application",
"name": "gancio",
"preferredUsername": "gancio",
"inbox": "https://demo.gancio.org/federation/u/gancio/inbox",
"outbox": "https://demo.gancio.org/federation/u/gancio/outbox",
"discoverable": true,
"attachment": [
{
"type": "PropertyValue",
"name": "Website",
"value": "<a href='https://demo.gancio.org'>https://demo.gancio.org</a>"
}
],
"icon": {
"type": "Image",
"mediaType": "image/png",
"url": "https://demo.gancio.org/logo.png"
},
"publicKey": {
"id": "https://demo.gancio.org/federation/u/gancio#main-key",
"owner": "https://demo.gancio.org/federation/u/gancio",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxp9BQ8TvVqu+0xXk7VuZ\nnuO42cHxVI+z/3TQ80AfX5aoUnK/uP7lIPy+NiIgRRu0L4hsjEs+HP6Ny9NAKFtC\nddS3pUrgIDz/AUyKeYRsCycw4XyeX7gaqIan4vCx+ANPDVTc3twDenynHhaXbPsP\nzGeKiAsGIFKRUxc5I5xnQBk6Fy6LZvGwfif07AcECER+nzffSOMPYFVbhlRuBwOg\n/tJcut77KOEpJIQSwqzT0FOw4oFtkvJt/nhpQMkXwOjEuiMOVpPoXUIpWjnbvNmy\nIPXdnKN4QqHi0fAE+FvKGbNmr18vqApT/D4Yen6W1ZWCRdUR1jjl8LNFBkPH/Tad\nkOj+UyRRJjRRqY5mXCI72Bmhwmi/YdS4gt9K73okOZ3atM+9Kfj3azZm8pP7fRkK\n/lwRP8RZFSSpz4w9JtzYmR7P8qTaxwMuq8VrxtFmf1IBChFpyNHUDtmC9MzLBRE7\n+fnpr1bARR3OwO83/xtT+vKNE+2SBvsf7zeFRXa+p5dGaih90rQOwL8EsUItiG61\nm4y9n3Q7BM7XwrZ7sGe3Hey5SWveOEgemfP4ANJBiMQpU69LKM9dGW1FcEX4FlwW\nZx/135nzMXE2cF+y+q/yY2FlacXPqJXMY32mIc+rHMzvFY/ZDzjRY/7Gg2ekjXuN\n1o7Ag7a+5k+r+XkWBNKIHp8CAwEAAQ==\n-----END PUBLIC KEY-----\n"
}
}

119
test/fixtures/mastodon-tcit-tcit.json vendored Normal file
View File

@ -0,0 +1,119 @@
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
"toot": "http://joinmastodon.org/ns#",
"featured": {
"@id": "toot:featured",
"@type": "@id"
},
"featuredTags": {
"@id": "toot:featuredTags",
"@type": "@id"
},
"alsoKnownAs": {
"@id": "as:alsoKnownAs",
"@type": "@id"
},
"movedTo": {
"@id": "as:movedTo",
"@type": "@id"
},
"schema": "http://schema.org#",
"PropertyValue": "schema:PropertyValue",
"value": "schema:value",
"IdentityProof": "toot:IdentityProof",
"discoverable": "toot:discoverable",
"Device": "toot:Device",
"Ed25519Signature": "toot:Ed25519Signature",
"Ed25519Key": "toot:Ed25519Key",
"Curve25519Key": "toot:Curve25519Key",
"EncryptedMessage": "toot:EncryptedMessage",
"publicKeyBase64": "toot:publicKeyBase64",
"deviceId": "toot:deviceId",
"claim": {
"@type": "@id",
"@id": "toot:claim"
},
"fingerprintKey": {
"@type": "@id",
"@id": "toot:fingerprintKey"
},
"identityKey": {
"@type": "@id",
"@id": "toot:identityKey"
},
"devices": {
"@type": "@id",
"@id": "toot:devices"
},
"messageFranking": "toot:messageFranking",
"messageType": "toot:messageType",
"cipherText": "toot:cipherText",
"suspended": "toot:suspended",
"focalPoint": {
"@container": "@list",
"@id": "toot:focalPoint"
}
}
],
"id": "https://social.tcit.fr/users/tcit",
"type": "Person",
"following": "https://social.tcit.fr/users/tcit/following",
"followers": "https://social.tcit.fr/users/tcit/followers",
"inbox": "https://social.tcit.fr/users/tcit/inbox",
"outbox": "https://social.tcit.fr/users/tcit/outbox",
"featured": "https://social.tcit.fr/users/tcit/collections/featured",
"featuredTags": "https://social.tcit.fr/users/tcit/collections/tags",
"preferredUsername": "tcit",
"name": "🦄 Thomas Citharel",
"summary": "<p>Hoping to make people&apos;s life better with free software at <span class=\"h-card\"><a href=\"https://framapiaf.org/@Framasoft\" class=\"u-url mention\">@<span>Framasoft</span></a></span>.</p><p>ᕕ(ᐛ)ᕗ</p>",
"url": "https://social.tcit.fr/@tcit",
"manuallyApprovesFollowers": false,
"discoverable": true,
"published": "2017-04-03T00:00:00Z",
"devices": "https://social.tcit.fr/users/tcit/collections/devices",
"publicKey": {
"id": "https://social.tcit.fr/users/tcit#main-key",
"owner": "https://social.tcit.fr/users/tcit",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApXwYMUdFg3XUd+bGsh8C\nyiMRGpRGAWuCdM5pDWx5uM4pW2pM3xbHbcI21j9h8BmlAiPg6hbZD73KGly2N8Rt\n5iIS0I+l6i8kA1JCCdlAaDTRd41RKMggZDoQvjVZQtsyE1VzMeU2kbqqTFN6ew7H\nvbd6O0NhixoKoZ5f3jwuBDZoT0p1TAcaMdmG8oqHD97isizkDnRn8cOBA6wtI+xb\n5xP2zxZMsLpTDZLiKU8XcPKZCw4OfQfmDmKkHtrFb77jCAQj/s/FxjVnvxRwmfhN\nnWy0D+LUV/g63nHh/b5zXIeV92QZLvDYbgbezmzUzv9UeA1s70GGbaDqCIy85gw9\n+wIDAQAB\n-----END PUBLIC KEY-----\n"
},
"tag": [],
"attachment": [
{
"type": "PropertyValue",
"name": "Works at",
"value": "<span class=\"h-card\"><a href=\"https://framapiaf.org/@Framasoft\" class=\"u-url mention\">@<span>Framasoft@framapiaf.org</span></a></span>"
},
{
"type": "PropertyValue",
"name": "Pronouns",
"value": "He/Him"
},
{
"type": "PropertyValue",
"name": "Work Account",
"value": "<a href=\"https://framapiaf.org/@tcit\" rel=\"me nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"\">framapiaf.org/@tcit</span><span class=\"invisible\"></span></a>"
},
{
"type": "PropertyValue",
"name": "Site",
"value": "<a href=\"https://tcit.fr\" rel=\"me nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"\">tcit.fr</span><span class=\"invisible\"></span></a>"
}
],
"endpoints": {
"sharedInbox": "https://social.tcit.fr/inbox"
},
"icon": {
"type": "Image",
"mediaType": "image/jpeg",
"url": "https://social.tcit.fr/system/accounts/avatars/000/000/001/original/a28c50ce5f2b13fd.jpg"
},
"image": {
"type": "Image",
"mediaType": "image/jpeg",
"url": "https://social.tcit.fr/system/accounts/headers/000/000/001/original/ac9c4a71083bd9a1.jpg"
}
}

View File

@ -0,0 +1,112 @@
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
"toot": "http://joinmastodon.org/ns#",
"featured": {
"@id": "toot:featured",
"@type": "@id"
},
"alsoKnownAs": {
"@id": "as:alsoKnownAs",
"@type": "@id"
},
"movedTo": {
"@id": "as:movedTo",
"@type": "@id"
},
"schema": "http://schema.org#",
"PropertyValue": "schema:PropertyValue",
"value": "schema:value",
"IdentityProof": "toot:IdentityProof",
"discoverable": "toot:discoverable",
"Device": "toot:Device",
"Ed25519Signature": "toot:Ed25519Signature",
"Ed25519Key": "toot:Ed25519Key",
"Curve25519Key": "toot:Curve25519Key",
"EncryptedMessage": "toot:EncryptedMessage",
"publicKeyBase64": "toot:publicKeyBase64",
"deviceId": "toot:deviceId",
"claim": {
"@type": "@id",
"@id": "toot:claim"
},
"fingerprintKey": {
"@type": "@id",
"@id": "toot:fingerprintKey"
},
"identityKey": {
"@type": "@id",
"@id": "toot:identityKey"
},
"devices": {
"@type": "@id",
"@id": "toot:devices"
},
"messageFranking": "toot:messageFranking",
"messageType": "toot:messageType",
"cipherText": "toot:cipherText",
"focalPoint": {
"@container": "@list",
"@id": "toot:focalPoint"
}
}
],
"id": "https://framapiaf.org/users/admin",
"type": "Service",
"following": "https://framapiaf.org/users/admin/following",
"followers": "https://framapiaf.org/users/admin/followers",
"inbox": "https://framapiaf.org/users/admin/inbox",
"outbox": "https://framapiaf.org/users/admin/outbox",
"featured": "https://framapiaf.org/users/admin/collections/featured",
"preferredUsername": "admin",
"name": "Administrateur",
"summary": "<p>Je ne suis qu&apos;un compte inutile. Merci nous de contacter via <a href=\"https://contact.framasoft.org/\" rel=\"nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"\">contact.framasoft.org/</span><span class=\"invisible\"></span></a></p>",
"url": "https://framapiaf.org/@admin",
"manuallyApprovesFollowers": false,
"discoverable": null,
"devices": "https://framapiaf.org/users/admin/collections/devices",
"publicKey": {
"id": "https://framapiaf.org/users/admin#main-key",
"owner": "https://framapiaf.org/users/admin",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHaU/AZ5dWtSxZXkPa89\nDUQ4z+JQHGGUG/xkGuq0v8P6qJfQqtHPBO5vH0IQJqluXWQS96gqTwjZnYevcpNA\nveYv0K25DWszx5Ehz6JX2/sSvu2rNUcQ3YZvSjdo/Yy1u5Fuc5lLmvw8uFzXYekD\nWovTMOnp4mIKpVEm/G/v4w8jvFEKw88h743vwaEIim88GEQItMxzGAV6zSqV1DWO\nLxtoRsinslJYfAG46ex4YUATFveWvOUeWk5W1sEa5f3c0moaTmBM/PAAo8vLxhlw\nJhsHihsCH+BcXKVMjW8OCqYYqISMxEifUBX63HcJt78ELHpOuc1c2eG59PomtTjQ\nywIDAQAB\n-----END PUBLIC KEY-----\n"
},
"tag": [],
"attachment": [
{
"type": "PropertyValue",
"name": "News",
"value": "<span class=\"h-card\"><a href=\"https://framapiaf.org/@Framasoft\" class=\"u-url mention\">@<span>Framasoft</span></a></span>"
},
{
"type": "PropertyValue",
"name": "Support",
"value": "<a href=\"https://contact.framasoft.org/\" rel=\"me nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"\">contact.framasoft.org/</span><span class=\"invisible\"></span></a>"
},
{
"type": "PropertyValue",
"name": "Soutenir",
"value": "<a href=\"https://soutenir.framasoft.org/\" rel=\"me nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"\">soutenir.framasoft.org/</span><span class=\"invisible\"></span></a>"
},
{
"type": "PropertyValue",
"name": "Site",
"value": "<a href=\"https://framasoft.org/\" rel=\"me nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"\">framasoft.org/</span><span class=\"invisible\"></span></a>"
}
],
"endpoints": {
"sharedInbox": "https://framapiaf.org/inbox"
},
"icon": {
"type": "Image",
"mediaType": "image/jpeg",
"url": "https://framapiaf.s3.framasoft.org/framapiaf/accounts/avatars/000/000/002/original/85fbb27ad5e3cf71.jpg"
},
"image": {
"type": "Image",
"mediaType": "image/jpeg",
"url": "https://framapiaf.s3.framasoft.org/framapiaf/accounts/headers/000/000/002/original/6aba75f1ab1ab6de.jpg"
}
}

55
test/fixtures/signature/nyu_rye.json vendored Normal file
View File

@ -0,0 +1,55 @@
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
"toot": "http://joinmastodon.org/ns#",
"featured": { "@id": "toot:featured", "@type": "@id" },
"alsoKnownAs": { "@id": "as:alsoKnownAs", "@type": "@id" },
"movedTo": { "@id": "as:movedTo", "@type": "@id" },
"schema": "http://schema.org#",
"PropertyValue": "schema:PropertyValue",
"value": "schema:value",
"IdentityProof": "toot:IdentityProof",
"discoverable": "toot:discoverable",
"Device": "toot:Device",
"Ed25519Signature": "toot:Ed25519Signature",
"Ed25519Key": "toot:Ed25519Key",
"Curve25519Key": "toot:Curve25519Key",
"EncryptedMessage": "toot:EncryptedMessage",
"publicKeyBase64": "toot:publicKeyBase64",
"deviceId": "toot:deviceId",
"claim": { "@type": "@id", "@id": "toot:claim" },
"fingerprintKey": { "@type": "@id", "@id": "toot:fingerprintKey" },
"identityKey": { "@type": "@id", "@id": "toot:identityKey" },
"devices": { "@type": "@id", "@id": "toot:devices" },
"messageFranking": "toot:messageFranking",
"messageType": "toot:messageType",
"cipherText": "toot:cipherText",
"focalPoint": { "@container": "@list", "@id": "toot:focalPoint" }
}
],
"id": "https://niu.moe/users/rye",
"type": "Person",
"following": "https://niu.moe/users/rye/following",
"followers": "https://niu.moe/users/rye/followers",
"inbox": "https://niu.moe/users/rye/inbox",
"outbox": "https://niu.moe/users/rye/outbox",
"featured": "https://niu.moe/users/rye/collections/featured",
"preferredUsername": "rye",
"name": "♡ rye ♡",
"summary": "\\u003cp\\u003ecome back with a warrant\\u003c/p\\u003e",
"url": "https://niu.moe/@rye",
"manuallyApprovesFollowers": false,
"discoverable": false,
"devices": "https://niu.moe/users/rye/collections/devices",
"publicKey": {
"id": "https://niu.moe/users/rye#main-key",
"owner": "https://niu.moe/users/rye",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA83uRWjCFO35FwfA38mzv\\nEL0TUaXB7+2hYvPwNrn1WY6me5DRbqB5zzMrzWMGr0HSooqNqEYBafGsmVTWUqIk\\nKM9ehtIBraJI+mT5X7DPR3LrXOJF4a9EEslg8XvAk8MN9IrAhm6UljnvB67RtDcA\\nTNB01VWy9yWnxFRtz9o/EMoBPyw5giOaXE2ibVNP8lQIqGKuuBKPzPjSJygdvQ5q\\nxfow2z1TpKRqdsNDqn4n6U6zCXYTzkr0J71/tGw7fsgfv78l0Wjrc7EcuBk74OaG\\nC65UDiu3X4Q6kxCfCEhPSfuwLN+UZkzxcn6goWR0iYpWs57+4tFKu9nJYP4QJ0K9\\nTwIDAQAB\\n-----END PUBLIC KEY-----\\n"
},
"tag": [],
"attachment": [],
"endpoints": { "sharedInbox": "https://niu.moe/inbox" }
}

View File

@ -1,116 +0,0 @@
[
{
"request": {
"body": "",
"headers": {
"Accept": "application/activity+json"
},
"method": "get",
"options": {
"follow_redirect": "true"
},
"request_body": "",
"url": "https://framapiaf.org/users/admin"
},
"response": {
"binary": false,
"body": "{\"@context\":[\"https://www.w3.org/ns/activitystreams\",\"https://w3id.org/security/v1\",{\"manuallyApprovesFollowers\":\"as:manuallyApprovesFollowers\",\"toot\":\"http://joinmastodon.org/ns#\",\"featured\":{\"@id\":\"toot:featured\",\"@type\":\"@id\"},\"alsoKnownAs\":{\"@id\":\"as:alsoKnownAs\",\"@type\":\"@id\"},\"movedTo\":{\"@id\":\"as:movedTo\",\"@type\":\"@id\"},\"schema\":\"http://schema.org#\",\"PropertyValue\":\"schema:PropertyValue\",\"value\":\"schema:value\",\"IdentityProof\":\"toot:IdentityProof\",\"discoverable\":\"toot:discoverable\",\"focalPoint\":{\"@container\":\"@list\",\"@id\":\"toot:focalPoint\"}}],\"id\":\"https://framapiaf.org/users/admin\",\"type\":\"Service\",\"following\":\"https://framapiaf.org/users/admin/following\",\"followers\":\"https://framapiaf.org/users/admin/followers\",\"inbox\":\"https://framapiaf.org/users/admin/inbox\",\"outbox\":\"https://framapiaf.org/users/admin/outbox\",\"featured\":\"https://framapiaf.org/users/admin/collections/featured\",\"preferredUsername\":\"admin\",\"name\":\"Administrateur\",\"summary\":\"\\u003cp\\u003eJe ne suis qu\\u0026apos;un compte inutile. Merci nous de contacter via \\u003ca href=\\\"https://contact.framasoft.org/\\\" rel=\\\"nofollow noopener\\\" target=\\\"_blank\\\"\\u003e\\u003cspan class=\\\"invisible\\\"\\u003ehttps://\\u003c/span\\u003e\\u003cspan class=\\\"\\\"\\u003econtact.framasoft.org/\\u003c/span\\u003e\\u003cspan class=\\\"invisible\\\"\\u003e\\u003c/span\\u003e\\u003c/a\\u003e\\u003c/p\\u003e\",\"url\":\"https://framapiaf.org/@admin\",\"manuallyApprovesFollowers\":false,\"discoverable\":null,\"publicKey\":{\"id\":\"https://framapiaf.org/users/admin#main-key\",\"owner\":\"https://framapiaf.org/users/admin\",\"publicKeyPem\":\"-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHaU/AZ5dWtSxZXkPa89\\nDUQ4z+JQHGGUG/xkGuq0v8P6qJfQqtHPBO5vH0IQJqluXWQS96gqTwjZnYevcpNA\\nveYv0K25DWszx5Ehz6JX2/sSvu2rNUcQ3YZvSjdo/Yy1u5Fuc5lLmvw8uFzXYekD\\nWovTMOnp4mIKpVEm/G/v4w8jvFEKw88h743vwaEIim88GEQItMxzGAV6zSqV1DWO\\nLxtoRsinslJYfAG46ex4YUATFveWvOUeWk5W1sEa5f3c0moaTmBM/PAAo8vLxhlw\\nJhsHihsCH+BcXKVMjW8OCqYYqISMxEifUBX63HcJt78ELHpOuc1c2eG59PomtTjQ\\nywIDAQAB\\n-----END PUBLIC KEY-----\\n\"},\"tag\":[],\"attachment\":[{\"type\":\"PropertyValue\",\"name\":\"News\",\"value\":\"\\u003cspan class=\\\"h-card\\\"\\u003e\\u003ca href=\\\"https://framapiaf.org/@Framasoft\\\" class=\\\"u-url mention\\\"\\u003e@\\u003cspan\\u003eFramasoft\\u003c/span\\u003e\\u003c/a\\u003e\\u003c/span\\u003e\"},{\"type\":\"PropertyValue\",\"name\":\"Support\",\"value\":\"\\u003ca href=\\\"https://contact.framasoft.org/\\\" rel=\\\"me nofollow noopener\\\" target=\\\"_blank\\\"\\u003e\\u003cspan class=\\\"invisible\\\"\\u003ehttps://\\u003c/span\\u003e\\u003cspan class=\\\"\\\"\\u003econtact.framasoft.org/\\u003c/span\\u003e\\u003cspan class=\\\"invisible\\\"\\u003e\\u003c/span\\u003e\\u003c/a\\u003e\"},{\"type\":\"PropertyValue\",\"name\":\"Soutenir\",\"value\":\"\\u003ca href=\\\"https://soutenir.framasoft.org/\\\" rel=\\\"me nofollow noopener\\\" target=\\\"_blank\\\"\\u003e\\u003cspan class=\\\"invisible\\\"\\u003ehttps://\\u003c/span\\u003e\\u003cspan class=\\\"\\\"\\u003esoutenir.framasoft.org/\\u003c/span\\u003e\\u003cspan class=\\\"invisible\\\"\\u003e\\u003c/span\\u003e\\u003c/a\\u003e\"},{\"type\":\"PropertyValue\",\"name\":\"Site\",\"value\":\"\\u003ca href=\\\"https://framasoft.org/\\\" rel=\\\"me nofollow noopener\\\" target=\\\"_blank\\\"\\u003e\\u003cspan class=\\\"invisible\\\"\\u003ehttps://\\u003c/span\\u003e\\u003cspan class=\\\"\\\"\\u003eframasoft.org/\\u003c/span\\u003e\\u003cspan class=\\\"invisible\\\"\\u003e\\u003c/span\\u003e\\u003c/a\\u003e\"}],\"endpoints\":{\"sharedInbox\":\"https://framapiaf.org/inbox\"},\"icon\":{\"type\":\"Image\",\"mediaType\":\"image/jpeg\",\"url\":\"https://framapiaf.s3.framasoft.org/framapiaf/accounts/avatars/000/000/002/original/85fbb27ad5e3cf71.jpg\"},\"image\":{\"type\":\"Image\",\"mediaType\":\"image/jpeg\",\"url\":\"https://framapiaf.s3.framasoft.org/framapiaf/accounts/headers/000/000/002/original/6aba75f1ab1ab6de.jpg\"}}",
"headers": {
"Date": "Sun, 15 Dec 2019 20:24:11 GMT",
"Content-Type": "application/activity+json; charset=utf-8",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Server": "Mastodon",
"X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff",
"X-XSS-Protection": "1; mode=block",
"Vary": "Accept, Accept-Encoding, Origin",
"Cache-Control": "max-age=180, public",
"ETag": "W/\"773e09a2a60446fe74d997858877f7e0\"",
"Set-Cookie": "_mastodon_session=XoZzbDOQtPbBNtbz7WoWZ4ZHTySKGQUeb1Hl3%2BxqZV%2FvxVEOMGMjKArqNF%2F78EJaF5TS%2FKcHPhwonEfsI5cz--jZG8CkvbBBmaJMDx--WRqeW2u0rVAHoNKcMNfLYA%3D%3D; path=/; secure; HttpOnly",
"X-Request-Id": "2a29bc1c-9dc8-4e36-b6d5-106c2f649959",
"X-Runtime": "0.012324",
"X-Cached": "MISS",
"Strict-Transport-Security": "max-age=31536000"
},
"status_code": 200,
"type": "ok"
}
},
{
"request": {
"body": "",
"headers": {
"Accept": "application/activity+json",
"Date": "Sun, 15 Dec 2019 20:24:11 GMT",
"Signature": "keyId=\"http://mobilizon.test/relay#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) date host\",signature=\"C6AGJG5xDdDBYfoAgBaL0iG0/Ru9qpvUij5vvONxJJpcjwc4LIePLaCid4LWK4aiY/z67M+LgopmD7xRn2Qht+Cyu3Kh38t5dS8EI0RWR4JesRyBauCZpzbRJG2w5SES4BPt53+5AuvPZZ81BBgPYF4A7ITBn550NLocesuFFsJJZHwfNqRCUm4cmx57/tnLBr0S4w/VDn6iQ3TBSlXdUJ7N9Za9y7p+vfkFT2PqSXu55HdWLX5NvaiVl2m7JKBCxCrB3i4Lr/Og5bsKhi6LiUoc7Lp0LX1tNftp6NOGgBIo0982NQ0v2jGsMj+eGU2stDl6bz3Z9SRnyyxirz+fag==\""
},
"method": "get",
"options": {
"follow_redirect": "true",
"recv_timeout": 20000,
"connect_timeout": 10000
},
"request_body": "",
"url": "https://info.pleroma.site/activity.json"
},
"response": {
"binary": false,
"body": "{\n \"@context\": \"https://www.w3.org/ns/activitystreams\",\n \"actor\": \"https://queer.hacktivis.me/users/lanodan\",\n \"announcement_count\": 3,\n \"announcements\": [\n \"https://io.markegli.com/users/mark\",\n \"https://voluntaryism.club/users/sevvie\",\n \"https://pleroma.pla1.net/users/pla\"\n ],\n \"attachment\": [],\n \"attributedTo\": \"https://queer.hacktivis.me/users/lanodan\",\n \"content\": \"<p>this post was not actually written by Haelwenn</p>\",\n \"id\": \"https://info.pleroma.site/activity.json\",\n \"published\": \"2018-09-01T22:15:00Z\",\n \"tag\": [],\n \"to\": [\n \"https://www.w3.org/ns/activitystreams#Public\"\n ],\n \"type\": \"Note\"\n}\n",
"headers": {
"Server": "nginx",
"Date": "Sun, 15 Dec 2019 20:24:11 GMT",
"Content-Type": "application/json",
"Content-Length": "750",
"Last-Modified": "Sat, 01 Sep 2018 22:56:24 GMT",
"Connection": "keep-alive",
"ETag": "\"5b8b1918-2ee\"",
"Accept-Ranges": "bytes"
},
"status_code": 200,
"type": "ok"
}
},
{
"request": {
"body": "",
"headers": {
"Accept": "application/activity+json"
},
"method": "get",
"options": {
"follow_redirect": "true"
},
"request_body": "",
"url": "https://queer.hacktivis.me/users/lanodan"
},
"response": {
"binary": false,
"body": "{\"@context\":[\"https://www.w3.org/ns/activitystreams\",\"https://queer.hacktivis.me/schemas/litepub-0.1.jsonld\",{\"@language\":\"und\"}],\"attachment\":[],\"discoverable\":false,\"endpoints\":{\"oauthAuthorizationEndpoint\":\"https://queer.hacktivis.me/oauth/authorize\",\"oauthRegistrationEndpoint\":\"https://queer.hacktivis.me/api/v1/apps\",\"oauthTokenEndpoint\":\"https://queer.hacktivis.me/oauth/token\",\"sharedInbox\":\"https://queer.hacktivis.me/inbox\",\"uploadMedia\":\"https://queer.hacktivis.me/api/ap/upload_media\"},\"followers\":\"https://queer.hacktivis.me/users/lanodan/followers\",\"following\":\"https://queer.hacktivis.me/users/lanodan/following\",\"icon\":{\"type\":\"Image\",\"url\":\"https://queer.hacktivis.me/media/c8e81887-7d81-4cdc-91b3-c624ea79e6c9/425f089961270eff91b66d45f8faeeb12a725a5f87a6a52bfc54c43bd89f5fe9.png\"},\"id\":\"https://queer.hacktivis.me/users/lanodan\",\"image\":{\"type\":\"Image\",\"url\":\"https://queer.hacktivis.me/media/37b6ce56-8c24-4e64-bd70-a76e84ab0c69/53a48a3a49ed5e5637a84e4f3663df17f8d764244bbc1027ba03cfc446e8b7bd.jpg\"},\"inbox\":\"https://queer.hacktivis.me/users/lanodan/inbox\",\"manuallyApprovesFollowers\":true,\"name\":\"Haelwenn /ɛlwən/ 🐺\",\"outbox\":\"https://queer.hacktivis.me/users/lanodan/outbox\",\"preferredUsername\":\"lanodan\",\"publicKey\":{\"id\":\"https://queer.hacktivis.me/users/lanodan#main-key\",\"owner\":\"https://queer.hacktivis.me/users/lanodan\",\"publicKeyPem\":\"-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsWOgdjSMc010qvxC3njI\\nXJlFWMJ5gJ8QXCW/PajYdsHPM6d+jxBNJ6zp9/tIRa2m7bWHTSkuHQ7QthOpt6vu\\n+dAWpKRLS607SPLItn/qUcyXvgN+H8shfyhMxvkVs9jXdtlBsLUVE7UNpN0dxzqe\\nI79QWbf7o4amgaIWGRYB+OYMnIxKt+GzIkivZdSVSYjfxNnBYkMCeUxm5EpPIxKS\\nP5bBHAVRRambD5NUmyKILuC60/rYuc/C+vmgpY2HCWFS2q6o34dPr9enwL6t4b3m\\nS1t/EJHk9rGaaDqSGkDEfyQI83/7SDebWKuETMKKFLZi1vMgQIFuOYCIhN6bIiZm\\npQIDAQAB\\n-----END PUBLIC KEY-----\\n\\n\"},\"summary\":\"---<br>Website: <a href=\\\"https://hacktivis.me/\\\">https://hacktivis.me/</a><br>Pronouns: she/fae, elle/iel<br>Lang: en, fr, (LSF), ...<br>```<br>🦊🦄⚧🂡ⓥ :anarchy: 👿🐧 :gentoo:<br>Pleroma dev (backend, mastofe)<br><br>banner from: <a href=\\\"https://soc.flyingcube.tech/objects/56f79be2-9013-4559-9826-f7dc392417db\\\">https://soc.flyingcube.tech/objects/56f79be2-9013-4559-9826-f7dc392417db</a><br>Federation-bots: <a class='hashtag' data-tag='nobot' href='https://queer.hacktivis.me/tag/nobot' rel='tag'>#nobot</a>\",\"tag\":[{\"icon\":{\"type\":\"Image\",\"url\":\"https://queer.hacktivis.me/emoji/custom/symbols/anarchy.png\"},\"name\":\":anarchy:\",\"type\":\"Emoji\"},{\"icon\":{\"type\":\"Image\",\"url\":\"https://queer.hacktivis.me/emoji/custom/gentoo.png\"},\"name\":\":gentoo:\",\"type\":\"Emoji\"}],\"type\":\"Person\",\"url\":\"https://queer.hacktivis.me/users/lanodan\"}",
"headers": {
"Server": "nginx/1.16.1",
"Date": "Sun, 15 Dec 2019 20:24:12 GMT",
"Content-Type": "application/activity+json; charset=utf-8",
"Content-Length": "2693",
"Connection": "keep-alive",
"Keep-Alive": "timeout=20",
"access-control-allow-credentials": "true",
"access-control-allow-origin": "*",
"access-control-expose-headers": "Link,X-RateLimit-Reset,X-RateLimit-Limit,X-RateLimit-Remaining,X-Request-Id,Idempotency-Key",
"cache-control": "max-age=0, private, must-revalidate",
"content-security-policy": "default-src 'none'; base-uri 'self'; frame-ancestors 'none'; img-src 'self' data: https:; media-src 'self' https:; style-src 'self' 'unsafe-inline'; font-src 'self'; manifest-src 'self'; connect-src 'self' https://queer.hacktivis.me wss://queer.hacktivis.me; script-src 'self'; upgrade-insecure-requests;",
"expect-ct": "enforce, max-age=2592000",
"referrer-policy": "no-referrer",
"strict-transport-security": "max-age=31536000; includeSubDomains",
"x-content-type-options": "nosniff",
"x-download-options": "noopen",
"x-frame-options": "DENY",
"x-permitted-cross-domain-policies": "none",
"x-request-id": "FeClJfdJwAn7WY0ABtmh",
"x-xss-protection": "1; mode=block"
},
"status_code": 200,
"type": "ok"
}
}
]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,40 +0,0 @@
[
{
"request": {
"body": "",
"headers": {
"Accept": "application/activity+json"
},
"method": "get",
"options": {
"follow_redirect": "true"
},
"request_body": "",
"url": "https://framapiaf.org/users/Framasoft"
},
"response": {
"binary": false,
"body": "{\"@context\":[\"https://www.w3.org/ns/activitystreams\",\"https://w3id.org/security/v1\",{\"manuallyApprovesFollowers\":\"as:manuallyApprovesFollowers\",\"toot\":\"http://joinmastodon.org/ns#\",\"featured\":{\"@id\":\"toot:featured\",\"@type\":\"@id\"},\"alsoKnownAs\":{\"@id\":\"as:alsoKnownAs\",\"@type\":\"@id\"},\"movedTo\":{\"@id\":\"as:movedTo\",\"@type\":\"@id\"},\"schema\":\"http://schema.org#\",\"PropertyValue\":\"schema:PropertyValue\",\"value\":\"schema:value\",\"IdentityProof\":\"toot:IdentityProof\",\"discoverable\":\"toot:discoverable\",\"Hashtag\":\"as:Hashtag\",\"focalPoint\":{\"@container\":\"@list\",\"@id\":\"toot:focalPoint\"}}],\"id\":\"https://framapiaf.org/users/Framasoft\",\"type\":\"Person\",\"following\":\"https://framapiaf.org/users/Framasoft/following\",\"followers\":\"https://framapiaf.org/users/Framasoft/followers\",\"inbox\":\"https://framapiaf.org/users/Framasoft/inbox\",\"outbox\":\"https://framapiaf.org/users/Framasoft/outbox\",\"featured\":\"https://framapiaf.org/users/Framasoft/collections/featured\",\"preferredUsername\":\"Framasoft\",\"name\":\"Framasoft\",\"summary\":\"\\u003cp\\u003eLa route est longue mais la voie est libre…\\u003c/p\\u003e\\u003cp\\u003eBesoin d\\u0026apos;aide ? \\u003ca href=\\\"https://contact.framasoft.org\\\" rel=\\\"nofollow noopener\\\" target=\\\"_blank\\\"\\u003e\\u003cspan class=\\\"invisible\\\"\\u003ehttps://\\u003c/span\\u003e\\u003cspan class=\\\"\\\"\\u003econtact.framasoft.org\\u003c/span\\u003e\\u003cspan class=\\\"invisible\\\"\\u003e\\u003c/span\\u003e\\u003c/a\\u003e /!\\\\ Pas de support sur Mastodon /!\\\\\\u003c/p\\u003e\\u003cp\\u003e\\u003ca href=\\\"https://framapiaf.org/tags/Framasoft\\\" class=\\\"mention hashtag\\\" rel=\\\"tag\\\"\\u003e#\\u003cspan\\u003eFramasoft\\u003c/span\\u003e\\u003c/a\\u003e \\u003ca href=\\\"https://framapiaf.org/tags/Libre\\\" class=\\\"mention hashtag\\\" rel=\\\"tag\\\"\\u003e#\\u003cspan\\u003eLibre\\u003c/span\\u003e\\u003c/a\\u003e\\u003c/p\\u003e\",\"url\":\"https://framapiaf.org/@Framasoft\",\"manuallyApprovesFollowers\":false,\"discoverable\":true,\"publicKey\":{\"id\":\"https://framapiaf.org/users/Framasoft#main-key\",\"owner\":\"https://framapiaf.org/users/Framasoft\",\"publicKeyPem\":\"-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0SgyiKbsNd0adHldDHiw\\nCotPzipq0QMrBgvmapnME8obZvrJWTF+imihNBH/DBemQqRb0ABilWvs0hluWCHl\\nouCi4SnlUljjpp2nmMTFUMPeF/GQByZS4ZPmnipgG+/uqkWL0U/206r//6agvw2s\\nmRcuVwo1xR4MZshxdtqXm/Wg9zavDSMLf/66VevieWvVy+5n0ZsqFAFuHrITgrgt\\n6wS8S3IT7de+7F28JeU/zmRFA3/3+IyWrpTx1CY4J+UM11mLbtpLWy3MCAMffchF\\nZh7TAiaJKAVMjT2Ubyr/1nNn9b4FORwOMIgWIGp5OAD1W/xVTW/rmqArAllgUMEW\\nvwIDAQAB\\n-----END PUBLIC KEY-----\\n\"},\"tag\":[{\"type\":\"Hashtag\",\"href\":\"https://framapiaf.org/explore/framasoft\",\"name\":\"#framasoft\"},{\"type\":\"Hashtag\",\"href\":\"https://framapiaf.org/explore/libre\",\"name\":\"#libre\"}],\"attachment\":[{\"type\":\"PropertyValue\",\"name\":\"Contact\",\"value\":\"\\u003ca href=\\\"https://contact.framasoft.org/\\\" rel=\\\"me nofollow noopener\\\" target=\\\"_blank\\\"\\u003e\\u003cspan class=\\\"invisible\\\"\\u003ehttps://\\u003c/span\\u003e\\u003cspan class=\\\"\\\"\\u003econtact.framasoft.org/\\u003c/span\\u003e\\u003cspan class=\\\"invisible\\\"\\u003e\\u003c/span\\u003e\\u003c/a\\u003e\"},{\"type\":\"PropertyValue\",\"name\":\"Découvrir\",\"value\":\"\\u003ca href=\\\"https://framasoft.org\\\" rel=\\\"me nofollow noopener\\\" target=\\\"_blank\\\"\\u003e\\u003cspan class=\\\"invisible\\\"\\u003ehttps://\\u003c/span\\u003e\\u003cspan class=\\\"\\\"\\u003eframasoft.org\\u003c/span\\u003e\\u003cspan class=\\\"invisible\\\"\\u003e\\u003c/span\\u003e\\u003c/a\\u003e\"},{\"type\":\"PropertyValue\",\"name\":\"Soutenir\",\"value\":\"\\u003ca href=\\\"https://soutenir.framasoft.org\\\" rel=\\\"me nofollow noopener\\\" target=\\\"_blank\\\"\\u003e\\u003cspan class=\\\"invisible\\\"\\u003ehttps://\\u003c/span\\u003e\\u003cspan class=\\\"\\\"\\u003esoutenir.framasoft.org\\u003c/span\\u003e\\u003cspan class=\\\"invisible\\\"\\u003e\\u003c/span\\u003e\\u003c/a\\u003e\"}],\"endpoints\":{\"sharedInbox\":\"https://framapiaf.org/inbox\"},\"icon\":{\"type\":\"Image\",\"mediaType\":\"image/jpeg\",\"url\":\"https://framapiaf.s3.framasoft.org/framapiaf/accounts/avatars/000/000/399/original/aa56a445efb72803.jpg\"},\"image\":{\"type\":\"Image\",\"mediaType\":\"image/jpeg\",\"url\":\"https://framapiaf.s3.framasoft.org/framapiaf/accounts/headers/000/000/399/original/94f271e4ef58fc79.jpg\"}}",
"headers": {
"Date": "Sun, 17 Nov 2019 18:09:47 GMT",
"Content-Type": "application/activity+json; charset=utf-8",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Server": "Mastodon",
"X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff",
"X-XSS-Protection": "1; mode=block",
"Vary": "Accept, Accept-Encoding, Origin",
"Cache-Control": "max-age=180, public",
"ETag": "W/\"244f2282ec9b1fac35b0381a673683da\"",
"Set-Cookie": "_mastodon_session=oLAzClz16WslSvWV2DqKE3h8nqfOVIFGE27%2BX5Ih6yqrChtwZCJVz3BghIcYTpBMOU467Or8nJZO2yPLkQPh--iCbklHRx4hwRBwGH--iLFXW%2B3UtBr28kV8Lfuk5A%3D%3D; path=/; secure; HttpOnly",
"X-Request-Id": "9ee29645-1f25-479e-8db5-bc90d7b31f4c",
"X-Runtime": "0.028450",
"X-Cached": "MISS",
"Strict-Transport-Security": "max-age=31536000"
},
"status_code": 200,
"type": "ok"
}
}
]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,40 +0,0 @@
[
{
"request": {
"body": "",
"headers": {
"Accept": "application/activity+json"
},
"method": "get",
"options": {
"follow_redirect": "true"
},
"request_body": "",
"url": "https://framapiaf.org/users/Framasoft"
},
"response": {
"binary": false,
"body": "{\"@context\":[\"https://www.w3.org/ns/activitystreams\",\"https://w3id.org/security/v1\",{\"manuallyApprovesFollowers\":\"as:manuallyApprovesFollowers\",\"toot\":\"http://joinmastodon.org/ns#\",\"featured\":{\"@id\":\"toot:featured\",\"@type\":\"@id\"},\"alsoKnownAs\":{\"@id\":\"as:alsoKnownAs\",\"@type\":\"@id\"},\"movedTo\":{\"@id\":\"as:movedTo\",\"@type\":\"@id\"},\"schema\":\"http://schema.org#\",\"PropertyValue\":\"schema:PropertyValue\",\"value\":\"schema:value\",\"IdentityProof\":\"toot:IdentityProof\",\"discoverable\":\"toot:discoverable\",\"Hashtag\":\"as:Hashtag\",\"focalPoint\":{\"@container\":\"@list\",\"@id\":\"toot:focalPoint\"}}],\"id\":\"https://framapiaf.org/users/Framasoft\",\"type\":\"Person\",\"following\":\"https://framapiaf.org/users/Framasoft/following\",\"followers\":\"https://framapiaf.org/users/Framasoft/followers\",\"inbox\":\"https://framapiaf.org/users/Framasoft/inbox\",\"outbox\":\"https://framapiaf.org/users/Framasoft/outbox\",\"featured\":\"https://framapiaf.org/users/Framasoft/collections/featured\",\"preferredUsername\":\"Framasoft\",\"name\":\"Framasoft\",\"summary\":\"\\u003cp\\u003eLa route est longue mais la voie est libre…\\u003c/p\\u003e\\u003cp\\u003eBesoin d\\u0026apos;aide ? \\u003ca href=\\\"https://contact.framasoft.org\\\" rel=\\\"nofollow noopener\\\" target=\\\"_blank\\\"\\u003e\\u003cspan class=\\\"invisible\\\"\\u003ehttps://\\u003c/span\\u003e\\u003cspan class=\\\"\\\"\\u003econtact.framasoft.org\\u003c/span\\u003e\\u003cspan class=\\\"invisible\\\"\\u003e\\u003c/span\\u003e\\u003c/a\\u003e /!\\\\ Pas de support sur Mastodon /!\\\\\\u003c/p\\u003e\\u003cp\\u003e\\u003ca href=\\\"https://framapiaf.org/tags/Framasoft\\\" class=\\\"mention hashtag\\\" rel=\\\"tag\\\"\\u003e#\\u003cspan\\u003eFramasoft\\u003c/span\\u003e\\u003c/a\\u003e \\u003ca href=\\\"https://framapiaf.org/tags/Libre\\\" class=\\\"mention hashtag\\\" rel=\\\"tag\\\"\\u003e#\\u003cspan\\u003eLibre\\u003c/span\\u003e\\u003c/a\\u003e\\u003c/p\\u003e\",\"url\":\"https://framapiaf.org/@Framasoft\",\"manuallyApprovesFollowers\":false,\"discoverable\":true,\"publicKey\":{\"id\":\"https://framapiaf.org/users/Framasoft#main-key\",\"owner\":\"https://framapiaf.org/users/Framasoft\",\"publicKeyPem\":\"-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0SgyiKbsNd0adHldDHiw\\nCotPzipq0QMrBgvmapnME8obZvrJWTF+imihNBH/DBemQqRb0ABilWvs0hluWCHl\\nouCi4SnlUljjpp2nmMTFUMPeF/GQByZS4ZPmnipgG+/uqkWL0U/206r//6agvw2s\\nmRcuVwo1xR4MZshxdtqXm/Wg9zavDSMLf/66VevieWvVy+5n0ZsqFAFuHrITgrgt\\n6wS8S3IT7de+7F28JeU/zmRFA3/3+IyWrpTx1CY4J+UM11mLbtpLWy3MCAMffchF\\nZh7TAiaJKAVMjT2Ubyr/1nNn9b4FORwOMIgWIGp5OAD1W/xVTW/rmqArAllgUMEW\\nvwIDAQAB\\n-----END PUBLIC KEY-----\\n\"},\"tag\":[{\"type\":\"Hashtag\",\"href\":\"https://framapiaf.org/explore/framasoft\",\"name\":\"#framasoft\"},{\"type\":\"Hashtag\",\"href\":\"https://framapiaf.org/explore/libre\",\"name\":\"#libre\"}],\"attachment\":[{\"type\":\"PropertyValue\",\"name\":\"Contact\",\"value\":\"\\u003ca href=\\\"https://contact.framasoft.org/\\\" rel=\\\"me nofollow noopener\\\" target=\\\"_blank\\\"\\u003e\\u003cspan class=\\\"invisible\\\"\\u003ehttps://\\u003c/span\\u003e\\u003cspan class=\\\"\\\"\\u003econtact.framasoft.org/\\u003c/span\\u003e\\u003cspan class=\\\"invisible\\\"\\u003e\\u003c/span\\u003e\\u003c/a\\u003e\"},{\"type\":\"PropertyValue\",\"name\":\"Découvrir\",\"value\":\"\\u003ca href=\\\"https://framasoft.org\\\" rel=\\\"me nofollow noopener\\\" target=\\\"_blank\\\"\\u003e\\u003cspan class=\\\"invisible\\\"\\u003ehttps://\\u003c/span\\u003e\\u003cspan class=\\\"\\\"\\u003eframasoft.org\\u003c/span\\u003e\\u003cspan class=\\\"invisible\\\"\\u003e\\u003c/span\\u003e\\u003c/a\\u003e\"},{\"type\":\"PropertyValue\",\"name\":\"Soutenir\",\"value\":\"\\u003ca href=\\\"https://soutenir.framasoft.org\\\" rel=\\\"me nofollow noopener\\\" target=\\\"_blank\\\"\\u003e\\u003cspan class=\\\"invisible\\\"\\u003ehttps://\\u003c/span\\u003e\\u003cspan class=\\\"\\\"\\u003esoutenir.framasoft.org\\u003c/span\\u003e\\u003cspan class=\\\"invisible\\\"\\u003e\\u003c/span\\u003e\\u003c/a\\u003e\"}],\"endpoints\":{\"sharedInbox\":\"https://framapiaf.org/inbox\"},\"icon\":{\"type\":\"Image\",\"mediaType\":\"image/jpeg\",\"url\":\"https://framapiaf.s3.framasoft.org/framapiaf/accounts/avatars/000/000/399/original/aa56a445efb72803.jpg\"},\"image\":{\"type\":\"Image\",\"mediaType\":\"image/jpeg\",\"url\":\"https://framapiaf.s3.framasoft.org/framapiaf/accounts/headers/000/000/399/original/94f271e4ef58fc79.jpg\"}}",
"headers": {
"Date": "Sun, 17 Nov 2019 18:09:19 GMT",
"Content-Type": "application/activity+json; charset=utf-8",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Server": "Mastodon",
"X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff",
"X-XSS-Protection": "1; mode=block",
"Vary": "Accept, Accept-Encoding, Origin",
"Cache-Control": "max-age=180, public",
"ETag": "W/\"244f2282ec9b1fac35b0381a673683da\"",
"Set-Cookie": "_mastodon_session=qFu4eHpJm1RgLVk6TyzbLxfQXMGZFqkybY4uqQNKUSUWboKh0edWetZQgoSPIXzAwTTFICfkkEPIhpQ4HnJU--NF09knzR8oukiQAs--2ax%2FdfLh6pkUpm6WDtngbw%3D%3D; path=/; secure; HttpOnly",
"X-Request-Id": "b121b7a6-423e-4378-97e0-e88a9a51928e",
"X-Runtime": "0.006326",
"X-Cached": "MISS",
"Strict-Transport-Security": "max-age=31536000"
},
"status_code": 200,
"type": "ok"
}
}
]

File diff suppressed because one or more lines are too long

View File

@ -1,78 +0,0 @@
[
{
"request": {
"body": "",
"headers": {
"Accept": "application/activity+json",
"Date": "Sun, 15 Dec 2019 20:24:06 GMT",
"Signature": "keyId=\"http://mobilizon.test/relay#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) date host\",signature=\"kUYhmOSdg7kxApgTCEj1CZLwOGn31sLbPdU35xu6Y5f/I3oT65g6KYlzuvchfQTrJ0XTzdzdSpQ5ZC/Y5dQEZrc3yzGw0KOmpSFfDcbtLw0I4Ya3vRjvuw0cDsPUwxoKpW1FqkMIEXP2lTXV/Bywc2rWCytnttiJwoQdeTvPDigmCCLxo2+wNMshl169HjAjYT9T8O0ptlgZXZ+JPuuaMj6EcSnXJDAkDxdBo54D61ED+dIIDxRKJsCTDrnjvZ86E9Z/P8SIbQxPZNw+TpLeofFTi/xt0E42M76iOEk41+kKlWQBd4imwoJesYEU+7CsMRtttt7wK9hMqcQC4UCa8g==\""
},
"method": "get",
"options": {
"follow_redirect": "true",
"recv_timeout": 20000,
"connect_timeout": 10000
},
"request_body": "",
"url": "https://info.pleroma.site/activity.json"
},
"response": {
"binary": false,
"body": "{\n \"@context\": \"https://www.w3.org/ns/activitystreams\",\n \"actor\": \"https://queer.hacktivis.me/users/lanodan\",\n \"announcement_count\": 3,\n \"announcements\": [\n \"https://io.markegli.com/users/mark\",\n \"https://voluntaryism.club/users/sevvie\",\n \"https://pleroma.pla1.net/users/pla\"\n ],\n \"attachment\": [],\n \"attributedTo\": \"https://queer.hacktivis.me/users/lanodan\",\n \"content\": \"<p>this post was not actually written by Haelwenn</p>\",\n \"id\": \"https://info.pleroma.site/activity.json\",\n \"published\": \"2018-09-01T22:15:00Z\",\n \"tag\": [],\n \"to\": [\n \"https://www.w3.org/ns/activitystreams#Public\"\n ],\n \"type\": \"Note\"\n}\n",
"headers": {
"Server": "nginx",
"Date": "Sun, 15 Dec 2019 20:24:07 GMT",
"Content-Type": "application/json",
"Content-Length": "750",
"Last-Modified": "Sat, 01 Sep 2018 22:56:24 GMT",
"Connection": "keep-alive",
"ETag": "\"5b8b1918-2ee\"",
"Accept-Ranges": "bytes"
},
"status_code": 200,
"type": "ok"
}
},
{
"request": {
"body": "",
"headers": {
"Accept": "application/activity+json"
},
"method": "get",
"options": {
"follow_redirect": "true"
},
"request_body": "",
"url": "https://queer.hacktivis.me/users/lanodan"
},
"response": {
"binary": false,
"body": "{\"@context\":[\"https://www.w3.org/ns/activitystreams\",\"https://queer.hacktivis.me/schemas/litepub-0.1.jsonld\",{\"@language\":\"und\"}],\"attachment\":[],\"discoverable\":false,\"endpoints\":{\"oauthAuthorizationEndpoint\":\"https://queer.hacktivis.me/oauth/authorize\",\"oauthRegistrationEndpoint\":\"https://queer.hacktivis.me/api/v1/apps\",\"oauthTokenEndpoint\":\"https://queer.hacktivis.me/oauth/token\",\"sharedInbox\":\"https://queer.hacktivis.me/inbox\",\"uploadMedia\":\"https://queer.hacktivis.me/api/ap/upload_media\"},\"followers\":\"https://queer.hacktivis.me/users/lanodan/followers\",\"following\":\"https://queer.hacktivis.me/users/lanodan/following\",\"icon\":{\"type\":\"Image\",\"url\":\"https://queer.hacktivis.me/media/c8e81887-7d81-4cdc-91b3-c624ea79e6c9/425f089961270eff91b66d45f8faeeb12a725a5f87a6a52bfc54c43bd89f5fe9.png\"},\"id\":\"https://queer.hacktivis.me/users/lanodan\",\"image\":{\"type\":\"Image\",\"url\":\"https://queer.hacktivis.me/media/37b6ce56-8c24-4e64-bd70-a76e84ab0c69/53a48a3a49ed5e5637a84e4f3663df17f8d764244bbc1027ba03cfc446e8b7bd.jpg\"},\"inbox\":\"https://queer.hacktivis.me/users/lanodan/inbox\",\"manuallyApprovesFollowers\":true,\"name\":\"Haelwenn /ɛlwən/ 🐺\",\"outbox\":\"https://queer.hacktivis.me/users/lanodan/outbox\",\"preferredUsername\":\"lanodan\",\"publicKey\":{\"id\":\"https://queer.hacktivis.me/users/lanodan#main-key\",\"owner\":\"https://queer.hacktivis.me/users/lanodan\",\"publicKeyPem\":\"-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsWOgdjSMc010qvxC3njI\\nXJlFWMJ5gJ8QXCW/PajYdsHPM6d+jxBNJ6zp9/tIRa2m7bWHTSkuHQ7QthOpt6vu\\n+dAWpKRLS607SPLItn/qUcyXvgN+H8shfyhMxvkVs9jXdtlBsLUVE7UNpN0dxzqe\\nI79QWbf7o4amgaIWGRYB+OYMnIxKt+GzIkivZdSVSYjfxNnBYkMCeUxm5EpPIxKS\\nP5bBHAVRRambD5NUmyKILuC60/rYuc/C+vmgpY2HCWFS2q6o34dPr9enwL6t4b3m\\nS1t/EJHk9rGaaDqSGkDEfyQI83/7SDebWKuETMKKFLZi1vMgQIFuOYCIhN6bIiZm\\npQIDAQAB\\n-----END PUBLIC KEY-----\\n\\n\"},\"summary\":\"---<br>Website: <a href=\\\"https://hacktivis.me/\\\">https://hacktivis.me/</a><br>Pronouns: she/fae, elle/iel<br>Lang: en, fr, (LSF), ...<br>```<br>🦊🦄⚧🂡ⓥ :anarchy: 👿🐧 :gentoo:<br>Pleroma dev (backend, mastofe)<br><br>banner from: <a href=\\\"https://soc.flyingcube.tech/objects/56f79be2-9013-4559-9826-f7dc392417db\\\">https://soc.flyingcube.tech/objects/56f79be2-9013-4559-9826-f7dc392417db</a><br>Federation-bots: <a class='hashtag' data-tag='nobot' href='https://queer.hacktivis.me/tag/nobot' rel='tag'>#nobot</a>\",\"tag\":[{\"icon\":{\"type\":\"Image\",\"url\":\"https://queer.hacktivis.me/emoji/custom/symbols/anarchy.png\"},\"name\":\":anarchy:\",\"type\":\"Emoji\"},{\"icon\":{\"type\":\"Image\",\"url\":\"https://queer.hacktivis.me/emoji/custom/gentoo.png\"},\"name\":\":gentoo:\",\"type\":\"Emoji\"}],\"type\":\"Person\",\"url\":\"https://queer.hacktivis.me/users/lanodan\"}",
"headers": {
"Server": "nginx/1.16.1",
"Date": "Sun, 15 Dec 2019 20:24:07 GMT",
"Content-Type": "application/activity+json; charset=utf-8",
"Content-Length": "2693",
"Connection": "keep-alive",
"Keep-Alive": "timeout=20",
"access-control-allow-credentials": "true",
"access-control-allow-origin": "*",
"access-control-expose-headers": "Link,X-RateLimit-Reset,X-RateLimit-Limit,X-RateLimit-Remaining,X-Request-Id,Idempotency-Key",
"cache-control": "max-age=0, private, must-revalidate",
"content-security-policy": "default-src 'none'; base-uri 'self'; frame-ancestors 'none'; img-src 'self' data: https:; media-src 'self' https:; style-src 'self' 'unsafe-inline'; font-src 'self'; manifest-src 'self'; connect-src 'self' https://queer.hacktivis.me wss://queer.hacktivis.me; script-src 'self'; upgrade-insecure-requests;",
"expect-ct": "enforce, max-age=2592000",
"referrer-policy": "no-referrer",
"strict-transport-security": "max-age=31536000; includeSubDomains",
"x-content-type-options": "nosniff",
"x-download-options": "noopen",
"x-frame-options": "DENY",
"x-permitted-cross-domain-policies": "none",
"x-request-id": "FeClJPRE1U5AcP8ABtkB",
"x-xss-protection": "1; mode=block"
},
"status_code": 200,
"type": "ok"
}
}
]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,42 +0,0 @@
[
{
"request": {
"body": "",
"headers": {
"Accept": "application/activity+json"
},
"method": "get",
"options": {
"follow_redirect": "true"
},
"request_body": "",
"url": "https://social.tcit.fr/users/tcit"
},
"response": {
"binary": false,
"body": "{\"@context\":[\"https://www.w3.org/ns/activitystreams\",\"https://w3id.org/security/v1\",{\"manuallyApprovesFollowers\":\"as:manuallyApprovesFollowers\",\"toot\":\"http://joinmastodon.org/ns#\",\"featured\":{\"@id\":\"toot:featured\",\"@type\":\"@id\"},\"alsoKnownAs\":{\"@id\":\"as:alsoKnownAs\",\"@type\":\"@id\"},\"movedTo\":{\"@id\":\"as:movedTo\",\"@type\":\"@id\"},\"schema\":\"http://schema.org#\",\"PropertyValue\":\"schema:PropertyValue\",\"value\":\"schema:value\",\"IdentityProof\":\"toot:IdentityProof\",\"discoverable\":\"toot:discoverable\",\"focalPoint\":{\"@container\":\"@list\",\"@id\":\"toot:focalPoint\"}}],\"id\":\"https://social.tcit.fr/users/tcit\",\"type\":\"Person\",\"following\":\"https://social.tcit.fr/users/tcit/following\",\"followers\":\"https://social.tcit.fr/users/tcit/followers\",\"inbox\":\"https://social.tcit.fr/users/tcit/inbox\",\"outbox\":\"https://social.tcit.fr/users/tcit/outbox\",\"featured\":\"https://social.tcit.fr/users/tcit/collections/featured\",\"preferredUsername\":\"tcit\",\"name\":\"🦄 Thomas Citharel\",\"summary\":\"\\u003cp\\u003eHoping to make people\\u0026apos;s life better with free software at \\u003cspan class=\\\"h-card\\\"\\u003e\\u003ca href=\\\"https://framapiaf.org/@Framasoft\\\" class=\\\"u-url mention\\\"\\u003e@\\u003cspan\\u003eFramasoft\\u003c/span\\u003e\\u003c/a\\u003e\\u003c/span\\u003e.\\u003c/p\\u003e\",\"url\":\"https://social.tcit.fr/@tcit\",\"manuallyApprovesFollowers\":false,\"discoverable\":true,\"publicKey\":{\"id\":\"https://social.tcit.fr/users/tcit#main-key\",\"owner\":\"https://social.tcit.fr/users/tcit\",\"publicKeyPem\":\"-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApXwYMUdFg3XUd+bGsh8C\\nyiMRGpRGAWuCdM5pDWx5uM4pW2pM3xbHbcI21j9h8BmlAiPg6hbZD73KGly2N8Rt\\n5iIS0I+l6i8kA1JCCdlAaDTRd41RKMggZDoQvjVZQtsyE1VzMeU2kbqqTFN6ew7H\\nvbd6O0NhixoKoZ5f3jwuBDZoT0p1TAcaMdmG8oqHD97isizkDnRn8cOBA6wtI+xb\\n5xP2zxZMsLpTDZLiKU8XcPKZCw4OfQfmDmKkHtrFb77jCAQj/s/FxjVnvxRwmfhN\\nnWy0D+LUV/g63nHh/b5zXIeV92QZLvDYbgbezmzUzv9UeA1s70GGbaDqCIy85gw9\\n+wIDAQAB\\n-----END PUBLIC KEY-----\\n\"},\"tag\":[],\"attachment\":[{\"type\":\"PropertyValue\",\"name\":\"Works at\",\"value\":\"\\u003cspan class=\\\"h-card\\\"\\u003e\\u003ca href=\\\"https://framapiaf.org/@Framasoft\\\" class=\\\"u-url mention\\\"\\u003e@\\u003cspan\\u003eFramasoft\\u003c/span\\u003e\\u003c/a\\u003e\\u003c/span\\u003e\"},{\"type\":\"PropertyValue\",\"name\":\"Pronouns\",\"value\":\"He/Him\"},{\"type\":\"PropertyValue\",\"name\":\"Work Account\",\"value\":\"\\u003ca href=\\\"https://framapiaf.org/@tcit\\\" rel=\\\"me nofollow noopener noreferrer\\\" target=\\\"_blank\\\"\\u003e\\u003cspan class=\\\"invisible\\\"\\u003ehttps://\\u003c/span\\u003e\\u003cspan class=\\\"\\\"\\u003eframapiaf.org/@tcit\\u003c/span\\u003e\\u003cspan class=\\\"invisible\\\"\\u003e\\u003c/span\\u003e\\u003c/a\\u003e\"},{\"type\":\"PropertyValue\",\"name\":\"Site\",\"value\":\"\\u003ca href=\\\"https://tcit.fr\\\" rel=\\\"me nofollow noopener noreferrer\\\" target=\\\"_blank\\\"\\u003e\\u003cspan class=\\\"invisible\\\"\\u003ehttps://\\u003c/span\\u003e\\u003cspan class=\\\"\\\"\\u003etcit.fr\\u003c/span\\u003e\\u003cspan class=\\\"invisible\\\"\\u003e\\u003c/span\\u003e\\u003c/a\\u003e\"}],\"endpoints\":{\"sharedInbox\":\"https://social.tcit.fr/inbox\"},\"icon\":{\"type\":\"Image\",\"mediaType\":\"image/jpeg\",\"url\":\"https://media.social.tcit.fr/mastodontcit/accounts/avatars/000/000/001/original/a28c50ce5f2b13fd.jpg\"},\"image\":{\"type\":\"Image\",\"mediaType\":\"image/png\",\"url\":\"https://media.social.tcit.fr/mastodontcit/accounts/headers/000/000/001/original/a3f3ec4f1b6f9f50.png\"}}",
"headers": {
"Date": "Sun, 17 Nov 2019 18:12:31 GMT",
"Content-Type": "application/activity+json; charset=utf-8",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Server": "Mastodon",
"X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff",
"X-XSS-Protection": "1; mode=block",
"Referrer-Policy": "same-origin",
"Strict-Transport-Security": "max-age=63072000; includeSubDomains; preload",
"X-Clacks-Overhead": "GNU Natalie Nguyen",
"Vary": "Accept, Accept-Encoding, Origin",
"Cache-Control": "max-age=180, public",
"ETag": "W/\"ff1350ff75d62d3c2cb61a0119576ed0\"",
"Set-Cookie": "_mastodon_session=9eVpoF4UR66ZVzSZin58%2BNuKKLcWiF2icEY1gXXHm1nBjtugdp9H09CrYrAmpvni3ihTxnuUYTF%2BZxmdt%2FC4--ADVuJ0WvPj243aYT--rRarAcYF9GVTGqnDe7HBvg%3D%3D; path=/; secure; HttpOnly",
"X-Request-Id": "16571166-5e85-4699-9c26-367f9035ea89",
"X-Runtime": "0.020868",
"X-Cached": "MISS"
},
"status_code": 200,
"type": "ok"
}
}
]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,39 +0,0 @@
[
{
"request": {
"body": "",
"headers": {
"Accept": "application/activity+json"
},
"method": "get",
"options": {
"follow_redirect": "true"
},
"request_body": "",
"url": "https://social.tcit.fr/users/tcit"
},
"response": {
"binary": false,
"body": "{\"@context\":[\"https://www.w3.org/ns/activitystreams\",\"https://w3id.org/security/v1\",{\"manuallyApprovesFollowers\":\"as:manuallyApprovesFollowers\",\"sensitive\":\"as:sensitive\",\"movedTo\":{\"@id\":\"as:movedTo\",\"@type\":\"@id\"},\"Hashtag\":\"as:Hashtag\",\"ostatus\":\"http://ostatus.org#\",\"atomUri\":\"ostatus:atomUri\",\"inReplyToAtomUri\":\"ostatus:inReplyToAtomUri\",\"conversation\":\"ostatus:conversation\",\"toot\":\"http://joinmastodon.org/ns#\",\"Emoji\":\"toot:Emoji\",\"focalPoint\":{\"@container\":\"@list\",\"@id\":\"toot:focalPoint\"},\"featured\":{\"@id\":\"toot:featured\",\"@type\":\"@id\"},\"schema\":\"http://schema.org#\",\"PropertyValue\":\"schema:PropertyValue\",\"value\":\"schema:value\"}],\"id\":\"https://social.tcit.fr/users/tcit\",\"type\":\"Person\",\"following\":\"https://social.tcit.fr/users/tcit/following\",\"followers\":\"https://social.tcit.fr/users/tcit/followers\",\"inbox\":\"https://social.tcit.fr/users/tcit/inbox\",\"outbox\":\"https://social.tcit.fr/users/tcit/outbox\",\"featured\":\"https://social.tcit.fr/users/tcit/collections/featured\",\"preferredUsername\":\"tcit\",\"name\":\"🦄 Thomas Citharel\",\"summary\":\"\\u003cp\\u003eHoping to make people\\u0026apos;s life better with free software at \\u003cspan class=\\\"h-card\\\"\\u003e\\u003ca href=\\\"https://framapiaf.org/@Framasoft\\\" class=\\\"u-url mention\\\"\\u003e@\\u003cspan\\u003eFramasoft\\u003c/span\\u003e\\u003c/a\\u003e\\u003c/span\\u003e.\\u003c/p\\u003e\",\"url\":\"https://social.tcit.fr/@tcit\",\"manuallyApprovesFollowers\":false,\"publicKey\":{\"id\":\"https://social.tcit.fr/users/tcit#main-key\",\"owner\":\"https://social.tcit.fr/users/tcit\",\"publicKeyPem\":\"-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApXwYMUdFg3XUd+bGsh8C\\nyiMRGpRGAWuCdM5pDWx5uM4pW2pM3xbHbcI21j9h8BmlAiPg6hbZD73KGly2N8Rt\\n5iIS0I+l6i8kA1JCCdlAaDTRd41RKMggZDoQvjVZQtsyE1VzMeU2kbqqTFN6ew7H\\nvbd6O0NhixoKoZ5f3jwuBDZoT0p1TAcaMdmG8oqHD97isizkDnRn8cOBA6wtI+xb\\n5xP2zxZMsLpTDZLiKU8XcPKZCw4OfQfmDmKkHtrFb77jCAQj/s/FxjVnvxRwmfhN\\nnWy0D+LUV/g63nHh/b5zXIeV92QZLvDYbgbezmzUzv9UeA1s70GGbaDqCIy85gw9\\n+wIDAQAB\\n-----END PUBLIC KEY-----\\n\"},\"tag\":[],\"attachment\":[{\"type\":\"PropertyValue\",\"name\":\"Works at\",\"value\":\"\\u003cspan class=\\\"h-card\\\"\\u003e\\u003ca href=\\\"https://framapiaf.org/@Framasoft\\\" class=\\\"u-url mention\\\"\\u003e@\\u003cspan\\u003eFramasoft\\u003c/span\\u003e\\u003c/a\\u003e\\u003c/span\\u003e\"},{\"type\":\"PropertyValue\",\"name\":\"Pronouns\",\"value\":\"He/Him\"},{\"type\":\"PropertyValue\",\"name\":\"Work Account\",\"value\":\"\\u003cspan class=\\\"h-card\\\"\\u003e\\u003ca href=\\\"https://framapiaf.org/@tcit\\\" class=\\\"u-url mention\\\"\\u003e@\\u003cspan\\u003etcit\\u003c/span\\u003e\\u003c/a\\u003e\\u003c/span\\u003e\"},{\"type\":\"PropertyValue\",\"name\":\"Pixelfed Account\",\"value\":\"@tcit@pix.tcit.fr\"}],\"endpoints\":{\"sharedInbox\":\"https://social.tcit.fr/inbox\"},\"icon\":{\"type\":\"Image\",\"mediaType\":\"image/jpeg\",\"url\":\"https://media.social.tcit.fr/mastodontcit/accounts/avatars/000/000/001/original/a28c50ce5f2b13fd.jpg\"},\"image\":{\"type\":\"Image\",\"mediaType\":\"image/jpeg\",\"url\":\"https://media.social.tcit.fr/mastodontcit/accounts/headers/000/000/001/original/4d1ab77c20265ee9.jpg\"}}",
"headers": {
"Date": "Tue, 13 Nov 2018 11:29:32 GMT",
"Content-Type": "application/activity+json; charset=utf-8",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Server": "Mastodon",
"X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff",
"X-XSS-Protection": "1; mode=block",
"Link": "<https://social.tcit.fr/.well-known/webfinger?resource=acct%3Atcit%40social.tcit.fr>; rel=\"lrdd\"; type=\"application/xrd+xml\", <https://social.tcit.fr/users/tcit.atom>; rel=\"alternate\"; type=\"application/atom+xml\", <https://social.tcit.fr/users/tcit>; rel=\"alternate\"; type=\"application/activity+json\"",
"Vary": "Accept,Accept-Encoding",
"Cache-Control": "max-age=180, public",
"ETag": "W/\"928f8a090d8c180ccc82fc1699f6c2a5\"",
"X-Request-Id": "ab17a9c9-7dd4-4f21-b70a-e35a3ca02b90",
"X-Runtime": "0.052812",
"X-Cached": "MISS"
},
"status_code": 410,
"type": "ok"
}
}
]

View File

@ -1,39 +0,0 @@
[
{
"request": {
"body": "",
"headers": {
"Accept": "application/activity+json"
},
"method": "get",
"options": {
"follow_redirect": "true"
},
"request_body": "",
"url": "https://social.tcit.fr/users/tcit"
},
"response": {
"binary": false,
"body": "{\"@context\":[\"https://www.w3.org/ns/activitystreams\",\"https://w3id.org/security/v1\",{\"manuallyApprovesFollowers\":\"as:manuallyApprovesFollowers\",\"sensitive\":\"as:sensitive\",\"movedTo\":{\"@id\":\"as:movedTo\",\"@type\":\"@id\"},\"Hashtag\":\"as:Hashtag\",\"ostatus\":\"http://ostatus.org#\",\"atomUri\":\"ostatus:atomUri\",\"inReplyToAtomUri\":\"ostatus:inReplyToAtomUri\",\"conversation\":\"ostatus:conversation\",\"toot\":\"http://joinmastodon.org/ns#\",\"Emoji\":\"toot:Emoji\",\"focalPoint\":{\"@container\":\"@list\",\"@id\":\"toot:focalPoint\"},\"featured\":{\"@id\":\"toot:featured\",\"@type\":\"@id\"},\"schema\":\"http://schema.org#\",\"PropertyValue\":\"schema:PropertyValue\",\"value\":\"schema:value\"}],\"id\":\"https://social.tcit.fr/users/tcit\",\"type\":\"Person\",\"following\":\"https://social.tcit.fr/users/tcit/following\",\"followers\":\"https://social.tcit.fr/users/tcit/followers\",\"inbox\":\"https://social.tcit.fr/users/tcit/inbox\",\"outbox\":\"https://social.tcit.fr/users/tcit/outbox\",\"featured\":\"https://social.tcit.fr/users/tcit/collections/featured\",\"preferredUsername\":\"tcit\",\"name\":\"🦄 Thomas Citharel\",\"summary\":\"\\u003cp\\u003eHoping to make people\\u0026apos;s life better with free software at \\u003cspan class=\\\"h-card\\\"\\u003e\\u003ca href=\\\"https://framapiaf.org/@Framasoft\\\" class=\\\"u-url mention\\\"\\u003e@\\u003cspan\\u003eFramasoft\\u003c/span\\u003e\\u003c/a\\u003e\\u003c/span\\u003e.\\u003c/p\\u003e\",\"url\":\"https://social.tcit.fr/@tcit\",\"manuallyApprovesFollowers\":false,\"publicKey\":{\"id\":\"https://social.tcit.fr/users/tcit#main-key\",\"owner\":\"https://social.tcit.fr/users/tcit\",\"publicKeyPem\":\"-----BEGIN PUBLIC KEY-----yolo-----END PUBLIC KEY-----\\n\"},\"tag\":[],\"attachment\":[{\"type\":\"PropertyValue\",\"name\":\"Works at\",\"value\":\"\\u003cspan class=\\\"h-card\\\"\\u003e\\u003ca href=\\\"https://framapiaf.org/@Framasoft\\\" class=\\\"u-url mention\\\"\\u003e@\\u003cspan\\u003eFramasoft\\u003c/span\\u003e\\u003c/a\\u003e\\u003c/span\\u003e\"},{\"type\":\"PropertyValue\",\"name\":\"Pronouns\",\"value\":\"He/Him\"},{\"type\":\"PropertyValue\",\"name\":\"Work Account\",\"value\":\"\\u003cspan class=\\\"h-card\\\"\\u003e\\u003ca href=\\\"https://framapiaf.org/@tcit\\\" class=\\\"u-url mention\\\"\\u003e@\\u003cspan\\u003etcit\\u003c/span\\u003e\\u003c/a\\u003e\\u003c/span\\u003e\"},{\"type\":\"PropertyValue\",\"name\":\"Pixelfed Account\",\"value\":\"@tcit@pix.tcit.fr\"}],\"endpoints\":{\"sharedInbox\":\"https://social.tcit.fr/inbox\"},\"icon\":{\"type\":\"Image\",\"mediaType\":\"image/jpeg\",\"url\":\"https://media.social.tcit.fr/mastodontcit/accounts/avatars/000/000/001/original/a28c50ce5f2b13fd.jpg\"},\"image\":{\"type\":\"Image\",\"mediaType\":\"image/jpeg\",\"url\":\"https://media.social.tcit.fr/mastodontcit/accounts/headers/000/000/001/original/4d1ab77c20265ee9.jpg\"}}",
"headers": {
"Date": "Tue, 13 Nov 2018 11:21:24 GMT",
"Content-Type": "application/activity+json; charset=utf-8",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Server": "Mastodon",
"X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff",
"X-XSS-Protection": "1; mode=block",
"Link": "<https://social.tcit.fr/.well-known/webfinger?resource=acct%3Atcit%40social.tcit.fr>; rel=\"lrdd\"; type=\"application/xrd+xml\", <https://social.tcit.fr/users/tcit.atom>; rel=\"alternate\"; type=\"application/atom+xml\", <https://social.tcit.fr/users/tcit>; rel=\"alternate\"; type=\"application/activity+json\"",
"Vary": "Accept,Accept-Encoding",
"Cache-Control": "max-age=180, public",
"ETag": "W/\"928f8a090d8c180ccc82fc1699f6c2a5\"",
"X-Request-Id": "ed9c4b9e-b29c-4f79-b704-3092a5d951a6",
"X-Runtime": "0.041257",
"X-Cached": "MISS"
},
"status_code": 200,
"type": "ok"
}
}
]

View File

@ -1,88 +0,0 @@
[
{
"request": {
"body": "",
"headers": {
"User-Agent": "localhost - Mobilizon 1.1.0-32-gbd53bfc4-dirty",
"Accept": "application/xrd+xml, application/xml, text/xml"
},
"method": "get",
"options": {
"recv_timeout": 20000
},
"request_body": "",
"url": "http://squeet.me/.well-known/host-meta"
},
"response": {
"binary": false,
"body": "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>301 Moved Permanently</title>\n</head><body>\n<h1>Moved Permanently</h1>\n<p>The document has moved <a href=\"https://squeet.me/.well-known/host-meta\">here</a>.</p>\n<hr>\n<address>Apache/2.4.25 (Debian) Server at squeet.me Port 80</address>\n</body></html>\n",
"headers": {
"Date": "Fri, 09 Apr 2021 08:08:52 GMT",
"Server": "Apache/2.4.25 (Debian)",
"Location": "https://squeet.me/.well-known/host-meta",
"Content-Length": "322",
"Content-Type": "text/html; charset=iso-8859-1"
},
"status_code": 301,
"type": "ok"
}
},
{
"request": {
"body": "",
"headers": {
"User-Agent": "localhost - Mobilizon 1.1.0-32-gbd53bfc4-dirty",
"Accept": "application/xrd+xml, application/xml, text/xml"
},
"method": "get",
"options": {
"recv_timeout": 20000
},
"request_body": "",
"url": "https://squeet.me/.well-known/host-meta"
},
"response": {
"binary": false,
"body": "<?xml version='1.0' encoding='UTF-8'?>\n<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'\n xmlns:hm='http://host-meta.net/xrd/1.0'>\n \n <hm:Host>squeet.me</hm:Host>\n \n <Link rel='lrdd' type='application/xrd+xml' template='https://squeet.me/xrd?uri={uri}' />\n <Link rel='lrdd' type='application/json' template='https://squeet.me/.well-known/webfinger?resource={uri}' />\n <Link rel='acct-mgmt' href='https://squeet.me/amcd' />\n <Link rel='http://services.mozilla.com/amcd/0.1' href='https://squeet.me/amcd' />\n\t<Link rel=\"http://oexchange.org/spec/0.8/rel/resident-target\" type=\"application/xrd+xml\" \n href=\"https://squeet.me/oexchange/xrd\" />\n\n <Property xmlns:mk=\"http://salmon-protocol.org/ns/magic-key\"\n type=\"http://salmon-protocol.org/ns/magic-key\"\n mk:key_id=\"1\">RSA.xlM2BNDH9hnO3W6vOUfJ5-tcUCaX-rx-kKydQd4ht21At4D4d1MrZ6nAQu7rnf5or9YZRhIpgvJvXBqWSo0zmALkUZUVrsS9WhH65I0qt24XNTPZJ1FdPDd7c1C131GzkymCbXBie3U2JaT7t0oimhWKUeA45gNfXk1T1l-7v4k.AQAB</Property>\n</XRD>\n",
"headers": {
"Date": "Fri, 09 Apr 2021 08:08:52 GMT",
"Server": "Apache/2.4.25 (Debian)",
"X-Account-Management-Status": "none",
"Vary": "Accept-Encoding",
"Transfer-Encoding": "chunked",
"Content-Type": "text/xml;charset=UTF-8"
},
"status_code": 200,
"type": "ok"
}
},
{
"request": {
"body": "",
"headers": {
"User-Agent": "localhost - Mobilizon 1.1.0-32-gbd53bfc4-dirty",
"Accept": "application/json, application/activity+json, application/jrd+json"
},
"method": "get",
"options": {
"recv_timeout": 20000
},
"request_body": "",
"url": "https://squeet.me/.well-known/webfinger?resource=acct:lain@squeet.me"
},
"response": {
"binary": false,
"body": "{\"subject\":\"acct:lain@squeet.me\",\"aliases\":[\"https:\\/\\/squeet.me\\/~lain\",\"https:\\/\\/squeet.me\\/profile\\/lain\"],\"links\":[{\"rel\":\"http:\\/\\/purl.org\\/macgirvin\\/dfrn\\/1.0\",\"href\":\"https:\\/\\/squeet.me\\/profile\\/lain\"},{\"rel\":\"http:\\/\\/schemas.google.com\\/g\\/2010#updates-from\",\"type\":\"application\\/atom+xml\",\"href\":\"https:\\/\\/squeet.me\\/dfrn_poll\\/lain\"},{\"rel\":\"http:\\/\\/webfinger.net\\/rel\\/profile-page\",\"type\":\"text\\/html\",\"href\":\"https:\\/\\/squeet.me\\/profile\\/lain\"},{\"rel\":\"self\",\"type\":\"application\\/activity+json\",\"href\":\"https:\\/\\/squeet.me\\/profile\\/lain\"},{\"rel\":\"http:\\/\\/microformats.org\\/profile\\/hcard\",\"type\":\"text\\/html\",\"href\":\"https:\\/\\/squeet.me\\/hcard\\/lain\"},{\"rel\":\"http:\\/\\/portablecontacts.net\\/spec\\/1.0\",\"href\":\"https:\\/\\/squeet.me\\/poco\\/lain\"},{\"rel\":\"http:\\/\\/webfinger.net\\/rel\\/avatar\",\"type\":\"image\\/jpeg\",\"href\":\"https:\\/\\/squeet.me\\/photo\\/abf2ee40bfcb044ac7fd1d143c82f63a-4.jpg?ts=1526641378\"},{\"rel\":\"http:\\/\\/joindiaspora.com\\/seed_location\",\"type\":\"text\\/html\",\"href\":\"https:\\/\\/squeet.me\"},{\"rel\":\"salmon\",\"href\":\"https:\\/\\/squeet.me\\/salmon\\/lain\"},{\"rel\":\"http:\\/\\/salmon-protocol.org\\/ns\\/salmon-replies\",\"href\":\"https:\\/\\/squeet.me\\/salmon\\/lain\"},{\"rel\":\"http:\\/\\/salmon-protocol.org\\/ns\\/salmon-mention\",\"href\":\"https:\\/\\/squeet.me\\/salmon\\/lain\\/mention\"},{\"rel\":\"http:\\/\\/ostatus.org\\/schema\\/1.0\\/subscribe\",\"template\":\"https:\\/\\/squeet.me\\/follow?url={uri}\"},{\"rel\":\"magic-public-key\",\"href\":\"data:application\\/magic-public-key,RSA.zBrwVSzZ9YSNfTE3vJFCB6BB9-EGm4o0Lp9rlU1JWisWMZmFGuU8yftNA56KGVz2UHPY6weUh51tifa4nvIKzQ.AQAB\"},{\"rel\":\"http:\\/\\/purl.org\\/openwebauth\\/v1\",\"type\":\"application\\/x-zot+json\",\"href\":\"https:\\/\\/squeet.me\\/owa\"}]}",
"headers": {
"Date": "Fri, 09 Apr 2021 08:08:52 GMT",
"Server": "Apache/2.4.25 (Debian)",
"X-Account-Management-Status": "none",
"Access-Control-Allow-Origin": "*",
"Transfer-Encoding": "chunked",
"Content-Type": "application/json; charset=utf-8"
},
"status_code": 200,
"type": "ok"
}
}
]

View File

@ -1,111 +0,0 @@
[
{
"request": {
"body": "",
"headers": {
"User-Agent": "localhost - Mobilizon 1.1.0-32-gbd53bfc4-dirty",
"Accept": "application/xrd+xml, application/xml, text/xml"
},
"method": "get",
"options": {
"recv_timeout": 20000
},
"request_body": "",
"url": "http://social.tcit.fr/.well-known/host-meta"
},
"response": {
"binary": false,
"body": "<html>\r\n<head><title>301 Moved Permanently</title></head>\r\n<body bgcolor=\"white\">\r\n<center><h1>301 Moved Permanently</h1></center>\r\n<hr><center>nginx/1.14.2</center>\r\n</body>\r\n</html>\r\n",
"headers": {
"Server": "nginx/1.14.2",
"Date": "Thu, 08 Apr 2021 18:59:56 GMT",
"Content-Type": "text/html",
"Content-Length": "185",
"Connection": "keep-alive",
"Location": "https://social.tcit.fr/.well-known/host-meta"
},
"status_code": 301,
"type": "ok"
}
},
{
"request": {
"body": "",
"headers": {
"User-Agent": "localhost - Mobilizon 1.1.0-32-gbd53bfc4-dirty",
"Accept": "application/xrd+xml, application/xml, text/xml"
},
"method": "get",
"options": {
"recv_timeout": 20000
},
"request_body": "",
"url": "https://social.tcit.fr/.well-known/host-meta"
},
"response": {
"binary": false,
"body": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<XRD xmlns=\"http://docs.oasis-open.org/ns/xri/xrd-1.0\">\n <Link rel=\"lrdd\" template=\"https://social.tcit.fr/.well-known/webfinger?resource={uri}\"/>\n</XRD>\n",
"headers": {
"Date": "Thu, 08 Apr 2021 18:59:56 GMT",
"Content-Type": "application/xrd+xml; charset=utf-8",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Server": "Mastodon",
"X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff",
"X-XSS-Protection": "1; mode=block",
"Referrer-Policy": "same-origin",
"Strict-Transport-Security": "max-age=63072000; includeSubDomains; preload",
"X-Clacks-Overhead": "GNU Natalie Nguyen",
"Vary": "Accept, Accept-Encoding, Origin",
"Cache-Control": "max-age=259200, public",
"ETag": "W/\"b397089bfee005b03360ba4435bb4aad\"",
"X-Request-Id": "41e837ba-21a6-4324-bda8-cac28a8d1778",
"X-Runtime": "0.004198",
"X-Cached": "MISS"
},
"status_code": 200,
"type": "ok"
}
},
{
"request": {
"body": "",
"headers": {
"User-Agent": "localhost - Mobilizon 1.1.0-32-gbd53bfc4-dirty",
"Accept": "application/json, application/activity+json, application/jrd+json"
},
"method": "get",
"options": {
"recv_timeout": 20000
},
"request_body": "",
"url": "https://social.tcit.fr/.well-known/webfinger?resource=acct:tcit@social.tcit.fr"
},
"response": {
"binary": false,
"body": "{\"subject\":\"acct:tcit@social.tcit.fr\",\"aliases\":[\"https://social.tcit.fr/@tcit\",\"https://social.tcit.fr/users/tcit\"],\"links\":[{\"rel\":\"http://webfinger.net/rel/profile-page\",\"type\":\"text/html\",\"href\":\"https://social.tcit.fr/@tcit\"},{\"rel\":\"self\",\"type\":\"application/activity+json\",\"href\":\"https://social.tcit.fr/users/tcit\"},{\"rel\":\"http://ostatus.org/schema/1.0/subscribe\",\"template\":\"https://social.tcit.fr/authorize_interaction?uri={uri}\"}]}",
"headers": {
"Date": "Thu, 08 Apr 2021 18:59:56 GMT",
"Content-Type": "application/jrd+json; charset=utf-8",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Server": "Mastodon",
"X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff",
"X-XSS-Protection": "1; mode=block",
"Referrer-Policy": "same-origin",
"Strict-Transport-Security": "max-age=63072000; includeSubDomains; preload",
"X-Clacks-Overhead": "GNU Natalie Nguyen",
"Vary": "Accept, Accept-Encoding, Origin",
"Cache-Control": "max-age=259200, public",
"ETag": "W/\"37760e35c1537b8e02b6d4b4f9ebfe82\"",
"X-Request-Id": "4c8384d6-d921-4ef6-8a18-1fcbf35ee6bc",
"X-Runtime": "0.009277",
"X-Cached": "MISS"
},
"status_code": 200,
"type": "ok"
}
}
]

View File

@ -1,93 +0,0 @@
[
{
"request": {
"body": "",
"headers": {
"User-Agent": "localhost - Mobilizon 1.1.0-32-gbd53bfc4-dirty",
"Accept": "application/xrd+xml, application/xml, text/xml"
},
"method": "get",
"options": {
"recv_timeout": 20000
},
"request_body": "",
"url": "http://framatube.org/.well-known/host-meta"
},
"response": {
"binary": false,
"body": "<html>\r\n<head><title>301 Moved Permanently</title></head>\r\n<body bgcolor=\"white\">\r\n<center><h1>301 Moved Permanently</h1></center>\r\n<hr><center>nginx/1.14.2</center>\r\n</body>\r\n</html>\r\n",
"headers": {
"Server": "nginx/1.14.2",
"Date": "Thu, 08 Apr 2021 18:59:59 GMT",
"Content-Type": "text/html",
"Content-Length": "185",
"Connection": "keep-alive",
"Location": "https://framatube.org/.well-known/host-meta"
},
"status_code": 301,
"type": "ok"
}
},
{
"request": {
"body": "",
"headers": {
"User-Agent": "localhost - Mobilizon 1.1.0-32-gbd53bfc4-dirty",
"Accept": "application/xrd+xml, application/xml, text/xml"
},
"method": "get",
"options": {
"recv_timeout": 20000
},
"request_body": "",
"url": "https://framatube.org/.well-known/host-meta"
},
"response": {
"binary": false,
"body": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<XRD xmlns=\"http://docs.oasis-open.org/ns/xri/xrd-1.0\">\n <Link rel=\"lrdd\" type=\"application/xrd+xml\" template=\"https://framatube.org/.well-known/webfinger?resource={uri}\"/>\n</XRD>",
"headers": {
"Server": "nginx/1.14.2",
"Date": "Thu, 08 Apr 2021 18:59:59 GMT",
"Content-Type": "application/xml; charset=utf-8",
"Content-Length": "219",
"Connection": "keep-alive",
"Tk": "N",
"Access-Control-Allow-Origin": "*",
"ETag": "W/\"db-l6RCFQ8UK40DPZ9VQ8G/SKn3A64\""
},
"status_code": 200,
"type": "ok"
}
},
{
"request": {
"body": "",
"headers": {
"User-Agent": "localhost - Mobilizon 1.1.0-32-gbd53bfc4-dirty",
"Accept": "application/json, application/activity+json, application/jrd+json"
},
"method": "get",
"options": {
"recv_timeout": 20000
},
"request_body": "",
"url": "https://framatube.org/.well-known/webfinger?resource=acct:framasoft@framatube.org"
},
"response": {
"binary": false,
"body": "{\"subject\":\"acct:framasoft@framatube.org\",\"aliases\":[\"https://framatube.org/accounts/framasoft\"],\"links\":[{\"rel\":\"self\",\"type\":\"application/activity+json\",\"href\":\"https://framatube.org/accounts/framasoft\"},{\"rel\":\"http://ostatus.org/schema/1.0/subscribe\",\"template\":\"https://framatube.org/remote-interaction?uri={uri}\"}]}",
"headers": {
"Server": "nginx/1.14.2",
"Date": "Thu, 08 Apr 2021 18:59:59 GMT",
"Content-Type": "application/json; charset=utf-8",
"Content-Length": "321",
"Connection": "keep-alive",
"Tk": "N",
"Access-Control-Allow-Origin": "*",
"ETag": "W/\"141-yxvvlAPayX5y2q2Yra8qYVtz4VU\""
},
"status_code": 200,
"type": "ok"
}
}
]

View File

@ -1,112 +0,0 @@
[
{
"request": {
"body": "",
"headers": {
"User-Agent": "localhost - Mobilizon 1.1.0-32-gbd53bfc4-dirty",
"Accept": "application/xrd+xml, application/xml, text/xml"
},
"method": "get",
"options": {
"recv_timeout": 20000
},
"request_body": "",
"url": "http://pleroma.soykaf.com/.well-known/host-meta"
},
"response": {
"binary": false,
"body": "<html>\r\n<head><title>301 Moved Permanently</title></head>\r\n<body>\r\n<center><h1>301 Moved Permanently</h1></center>\r\n<hr><center>nginx/1.18.0 (Ubuntu)</center>\r\n</body>\r\n</html>\r\n",
"headers": {
"Server": "nginx/1.18.0 (Ubuntu)",
"Date": "Thu, 08 Apr 2021 18:59:57 GMT",
"Content-Type": "text/html",
"Content-Length": "178",
"Connection": "keep-alive",
"Location": "https://pleroma.soykaf.com/.well-known/host-meta"
},
"status_code": 301,
"type": "ok"
}
},
{
"request": {
"body": "",
"headers": {
"User-Agent": "localhost - Mobilizon 1.1.0-32-gbd53bfc4-dirty",
"Accept": "application/xrd+xml, application/xml, text/xml"
},
"method": "get",
"options": {
"recv_timeout": 20000
},
"request_body": "",
"url": "https://pleroma.soykaf.com/.well-known/host-meta"
},
"response": {
"binary": false,
"body": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><XRD xmlns=\"http://docs.oasis-open.org/ns/xri/xrd-1.0\"><Link rel=\"lrdd\" template=\"https://pleroma.soykaf.com/.well-known/webfinger?resource={uri}\" type=\"application/xrd+xml\" /></XRD>",
"headers": {
"Server": "nginx/1.18.0 (Ubuntu)",
"Date": "Thu, 08 Apr 2021 18:59:57 GMT",
"Content-Type": "application/xrd+xml; charset=utf-8",
"Content-Length": "220",
"Connection": "keep-alive",
"access-control-allow-credentials": "true",
"access-control-allow-origin": "*",
"access-control-expose-headers": "Link,X-RateLimit-Reset,X-RateLimit-Limit,X-RateLimit-Remaining,X-Request-Id,Idempotency-Key",
"cache-control": "max-age=0, private, must-revalidate",
"content-security-policy": "upgrade-insecure-requests;script-src 'self';connect-src 'self' blob: https://pleroma.soykaf.com wss://pleroma.soykaf.com;media-src 'self';img-src 'self' data: blob:;default-src 'none';base-uri 'self';frame-ancestors 'none';style-src 'self' 'unsafe-inline';font-src 'self';manifest-src 'self';",
"referrer-policy": "same-origin",
"x-content-type-options": "nosniff",
"x-download-options": "noopen",
"x-frame-options": "DENY",
"x-permitted-cross-domain-policies": "none",
"x-request-id": "FnP3HZA8tRWC7E4EYzyS",
"x-xss-protection": "1; mode=block"
},
"status_code": 200,
"type": "ok"
}
},
{
"request": {
"body": "",
"headers": {
"User-Agent": "localhost - Mobilizon 1.1.0-32-gbd53bfc4-dirty",
"Accept": "application/json, application/activity+json, application/jrd+json"
},
"method": "get",
"options": {
"recv_timeout": 20000
},
"request_body": "",
"url": "https://pleroma.soykaf.com/.well-known/webfinger?resource=acct:lain@pleroma.soykaf.com"
},
"response": {
"binary": false,
"body": "{\"aliases\":[\"https://pleroma.soykaf.com/users/lain\"],\"links\":[{\"href\":\"https://pleroma.soykaf.com/users/lain\",\"rel\":\"http://webfinger.net/rel/profile-page\",\"type\":\"text/html\"},{\"href\":\"https://pleroma.soykaf.com/users/lain\",\"rel\":\"self\",\"type\":\"application/activity+json\"},{\"href\":\"https://pleroma.soykaf.com/users/lain\",\"rel\":\"self\",\"type\":\"application/ld+json; profile=\\\"https://www.w3.org/ns/activitystreams\\\"\"},{\"rel\":\"http://ostatus.org/schema/1.0/subscribe\",\"template\":\"https://pleroma.soykaf.com/ostatus_subscribe?acct={uri}\"}],\"subject\":\"acct:lain@pleroma.soykaf.com\"}",
"headers": {
"Server": "nginx/1.18.0 (Ubuntu)",
"Date": "Thu, 08 Apr 2021 18:59:57 GMT",
"Content-Type": "application/json; charset=utf-8",
"Content-Length": "576",
"Connection": "keep-alive",
"Vary": "Accept-Encoding",
"access-control-allow-credentials": "true",
"access-control-allow-origin": "*",
"access-control-expose-headers": "Link,X-RateLimit-Reset,X-RateLimit-Limit,X-RateLimit-Remaining,X-Request-Id,Idempotency-Key",
"cache-control": "max-age=0, private, must-revalidate",
"content-security-policy": "upgrade-insecure-requests;script-src 'self';connect-src 'self' blob: https://pleroma.soykaf.com wss://pleroma.soykaf.com;media-src 'self';img-src 'self' data: blob:;default-src 'none';base-uri 'self';frame-ancestors 'none';style-src 'self' 'unsafe-inline';font-src 'self';manifest-src 'self';",
"referrer-policy": "same-origin",
"x-content-type-options": "nosniff",
"x-download-options": "noopen",
"x-frame-options": "DENY",
"x-permitted-cross-domain-policies": "none",
"x-request-id": "FnP3HZJ_kh8ymy8E1OCx",
"x-xss-protection": "1; mode=block"
},
"status_code": 200,
"type": "ok"
}
}
]

View File

@ -0,0 +1,10 @@
<?xml version='1.0' encoding='UTF-8'?>
<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0' xmlns:hm='http://host-meta.net/xrd/1.0'>
<hm:Host>squeet.me</hm:Host>
<Link rel='lrdd' type='application/xrd+xml' template='https://squeet.me/xrd?uri={uri}' />
<Link rel='lrdd' type='application/json' template='https://squeet.me/.well-known/webfinger?resource={uri}' />
<Link rel='acct-mgmt' href='https://squeet.me/amcd' />
<Link rel='http://services.mozilla.com/amcd/0.1' href='https://squeet.me/amcd' />
<Link rel="http://oexchange.org/spec/0.8/rel/resident-target" type="application/xrd+xml" href="https://squeet.me/oexchange/xrd" />
<Property xmlns:mk="http://salmon-protocol.org/ns/magic-key" type="http://salmon-protocol.org/ns/magic-key" mk:key_id="1">RSA.xlM2BNDH9hnO3W6vOUfJ5-tcUCaX-rx-kKydQd4ht21At4D4d1MrZ6nAQu7rnf5or9YZRhIpgvJvXBqWSo0zmALkUZUVrsS9WhH65I0qt24XNTPZJ1FdPDd7c1C131GzkymCbXBie3U2JaT7t0oimhWKUeA45gNfXk1T1l-7v4k.AQAB</Property>
</XRD>

View File

@ -0,0 +1,66 @@
{
"subject": "acct:lain@squeet.me",
"aliases": ["https://squeet.me/~lain", "https://squeet.me/profile/lain"],
"links": [
{
"rel": "http://purl.org/macgirvin/dfrn/1.0",
"href": "https://squeet.me/profile/lain"
},
{
"rel": "http://schemas.google.com/g/2010#updates-from",
"type": "application/atom+xml",
"href": "https://squeet.me/dfrn_poll/lain"
},
{
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html",
"href": "https://squeet.me/profile/lain"
},
{
"rel": "self",
"type": "application/activity+json",
"href": "https://squeet.me/profile/lain"
},
{
"rel": "http://microformats.org/profile/hcard",
"type": "text/html",
"href": "https://squeet.me/hcard/lain"
},
{
"rel": "http://portablecontacts.net/spec/1.0",
"href": "https://squeet.me/poco/lain"
},
{
"rel": "http://webfinger.net/rel/avatar",
"type": "image/jpeg",
"href": "https://squeet.me/photo/abf2ee40bfcb044ac7fd1d143c82f63a-4.jpg?ts=1526641378"
},
{
"rel": "http://joindiaspora.com/seed_location",
"type": "text/html",
"href": "https://squeet.me"
},
{ "rel": "salmon", "href": "https://squeet.me/salmon/lain" },
{
"rel": "http://salmon-protocol.org/ns/salmon-replies",
"href": "https://squeet.me/salmon/lain"
},
{
"rel": "http://salmon-protocol.org/ns/salmon-mention",
"href": "https://squeet.me/salmon/lain/mention"
},
{
"rel": "http://ostatus.org/schema/1.0/subscribe",
"template": "https://squeet.me/follow?url={uri}"
},
{
"rel": "magic-public-key",
"href": "data:application/magic-public-key,RSA.zBrwVSzZ9YSNfTE3vJFCB6BB9-EGm4o0Lp9rlU1JWisWMZmFGuU8yftNA56KGVz2UHPY6weUh51tifa4nvIKzQ.AQAB"
},
{
"rel": "http://purl.org/openwebauth/v1",
"type": "application/x-zot+json",
"href": "https://squeet.me/owa"
}
]
}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
<Link rel="lrdd" type="application/xrd+xml" template="https://demo.gancio.org/.well-known/webfinger?resource={uri}" />
</XRD>

View File

@ -0,0 +1,10 @@
{
"subject": "acct:gancio@demo.gancio.org",
"links": [
{
"rel": "self",
"type": "application/activity+json",
"href": "https://demo.gancio.org/federation/u/gancio"
}
]
}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
<Link rel="lrdd" template="https://social.tcit.fr/.well-known/webfinger?resource={uri}" />
</XRD>

View File

@ -0,0 +1,23 @@
{
"subject": "acct:tcit@social.tcit.fr",
"aliases": [
"https://social.tcit.fr/@tcit",
"https://social.tcit.fr/users/tcit"
],
"links": [
{
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html",
"href": "https://social.tcit.fr/@tcit"
},
{
"rel": "self",
"type": "application/activity+json",
"href": "https://social.tcit.fr/users/tcit"
},
{
"rel": "http://ostatus.org/schema/1.0/subscribe",
"template": "https://social.tcit.fr/authorize_interaction?uri={uri}"
}
]
}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
<Link rel="lrdd" type="application/xrd+xml" template="https://framatube.org/.well-known/webfinger?resource={uri}" />
</XRD>

View File

@ -0,0 +1,15 @@
{
"subject": "acct:framasoft@framatube.org",
"aliases": ["https://framatube.org/accounts/framasoft"],
"links": [
{
"rel": "self",
"type": "application/activity+json",
"href": "https://framatube.org/accounts/framasoft"
},
{
"rel": "http://ostatus.org/schema/1.0/subscribe",
"template": "https://framatube.org/remote-interaction?uri={uri}"
}
]
}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
<Link rel="lrdd" template="https://pleroma.soykaf.com/.well-known/webfinger?resource={uri}" type="application/xrd+xml" />
</XRD>

View File

@ -0,0 +1,25 @@
{
"aliases": ["https://pleroma.soykaf.com/users/lain"],
"links": [
{
"href": "https://pleroma.soykaf.com/users/lain",
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html"
},
{
"href": "https://pleroma.soykaf.com/users/lain",
"rel": "self",
"type": "application/activity+json"
},
{
"href": "https://pleroma.soykaf.com/users/lain",
"rel": "self",
"type": "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
},
{
"rel": "http://ostatus.org/schema/1.0/subscribe",
"template": "https://pleroma.soykaf.com/ostatus_subscribe?acct={uri}"
}
],
"subject": "acct:lain@pleroma.soykaf.com"
}

View File

@ -112,6 +112,9 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
organizer_actor { organizer_actor {
id id
}, },
attributed_to {
id
},
online_address, online_address,
phone_address, phone_address,
category, category,
@ -320,6 +323,56 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
assert res["data"]["person"]["participations"]["elements"] == [] assert res["data"]["person"]["participations"]["elements"] == []
end end
test "create_event/3 creates an event as a draft for a group", %{
conn: conn,
actor: actor,
user: user
} do
%Actor{id: group_id} = group = insert(:group)
insert(:member, parent: group, actor: actor, role: :moderator)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @create_event_mutation,
variables: %{
title: "come to my event",
description: "it will be fine",
begins_on: "#{DateTime.utc_now()}",
organizer_actor_id: "#{actor.id}",
attributed_to_id: group_id,
draft: true
}
)
assert res["data"]["createEvent"]["title"] == "come to my event"
assert res["data"]["createEvent"]["draft"] == true
assert res["data"]["createEvent"]["attributed_to"]["id"] == to_string(group_id)
event_uuid = res["data"]["createEvent"]["uuid"]
event_id = res["data"]["createEvent"]["id"]
refute_enqueued(
worker: Workers.BuildSearch,
args: %{event_id: String.to_integer(event_id), op: :insert_search_event}
)
res =
conn
|> AbsintheHelpers.graphql_query(query: @find_event_query, variables: %{uuid: event_uuid})
assert hd(res["errors"])["message"] =~ "not found"
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(query: @find_event_query, variables: %{uuid: event_uuid})
assert res["errors"] == nil
assert res["data"]["event"]["draft"] == true
end
test "create_event/3 creates an event with options", %{conn: conn, actor: actor, user: user} do test "create_event/3 creates an event with options", %{conn: conn, actor: actor, user: user} do
begins_on = DateTime.utc_now() |> DateTime.truncate(:second) |> DateTime.to_iso8601() begins_on = DateTime.utc_now() |> DateTime.truncate(:second) |> DateTime.to_iso8601()
ends_on = DateTime.utc_now() |> DateTime.truncate(:second) |> DateTime.to_iso8601() ends_on = DateTime.utc_now() |> DateTime.truncate(:second) |> DateTime.to_iso8601()

Some files were not shown because too many files have changed in this diff Show More