Merge branch 'event/create-with-address' into 'master'
Add address input and refactor federation stuff See merge request framasoft/mobilizon!163
This commit is contained in:
commit
3fa2bd35d8
@ -50,6 +50,8 @@ config :mobilizon, MobilizonWeb.Endpoint,
|
|||||||
# Do not include metadata nor timestamps in development logs
|
# Do not include metadata nor timestamps in development logs
|
||||||
config :logger, :console, format: "[$level] $message\n", level: :debug
|
config :logger, :console, format: "[$level] $message\n", level: :debug
|
||||||
|
|
||||||
|
config :mobilizon, Mobilizon.Service.Geospatial, service: Mobilizon.Service.Geospatial.Nominatim
|
||||||
|
|
||||||
# Set a higher stacktrace during development. Avoid configuring such
|
# Set a higher stacktrace during development. Avoid configuring such
|
||||||
# in production as building large stacktraces may be expensive.
|
# in production as building large stacktraces may be expensive.
|
||||||
config :phoenix, :stacktrace_depth, 20
|
config :phoenix, :stacktrace_depth, 20
|
||||||
|
53
js/src/components/Event/AddressAutoComplete.vue
Normal file
53
js/src/components/Event/AddressAutoComplete.vue
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<template>
|
||||||
|
<b-field label="Find an address">
|
||||||
|
<b-autocomplete
|
||||||
|
:data="data"
|
||||||
|
placeholder="e.g. 10 Rue Jangot"
|
||||||
|
field="description"
|
||||||
|
:loading="isFetching"
|
||||||
|
@typing="getAsyncData"
|
||||||
|
@select="option => selected = option">
|
||||||
|
|
||||||
|
<template slot-scope="{option}">
|
||||||
|
<b>{{ option.description }}</b>
|
||||||
|
<p>
|
||||||
|
<small>{{ option.street }}</small>, 
|
||||||
|
<small>{{ option.locality }}</small>
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
</b-autocomplete>
|
||||||
|
</b-field>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
|
||||||
|
import { IAddress } from '@/types/address.model';
|
||||||
|
import { ADDRESS } from '@/graphql/address';
|
||||||
|
@Component
|
||||||
|
export default class AddressAutoComplete extends Vue {
|
||||||
|
|
||||||
|
@Prop({ required: false, default: () => [] }) initialData!: IAddress[];
|
||||||
|
|
||||||
|
data: IAddress[] = this.initialData;
|
||||||
|
selected: IAddress|null = null;
|
||||||
|
isFetching: boolean = false;
|
||||||
|
|
||||||
|
async getAsyncData(query) {
|
||||||
|
if (!query.length) {
|
||||||
|
this.data = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.isFetching = true;
|
||||||
|
const result = await this.$apollo.query({
|
||||||
|
query: ADDRESS,
|
||||||
|
variables: { query },
|
||||||
|
});
|
||||||
|
|
||||||
|
this.data = result.data.searchAddress as IAddress[];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Watch("selected")
|
||||||
|
updateSelected() {
|
||||||
|
this.$emit('input', this.selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
18
js/src/graphql/address.ts
Normal file
18
js/src/graphql/address.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
|
export const ADDRESS = gql`
|
||||||
|
query($query:String!) {
|
||||||
|
searchAddress(
|
||||||
|
query: $query
|
||||||
|
) {
|
||||||
|
description,
|
||||||
|
geom,
|
||||||
|
floor,
|
||||||
|
street,
|
||||||
|
locality,
|
||||||
|
postalCode,
|
||||||
|
region,
|
||||||
|
country
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
@ -144,7 +144,8 @@ export const CREATE_EVENT = gql`
|
|||||||
$category: String!,
|
$category: String!,
|
||||||
$beginsOn: DateTime!,
|
$beginsOn: DateTime!,
|
||||||
$picture: PictureInput,
|
$picture: PictureInput,
|
||||||
$tags: [String]
|
$tags: [String],
|
||||||
|
$physicalAddress: AddressInput!
|
||||||
) {
|
) {
|
||||||
createEvent(
|
createEvent(
|
||||||
title: $title,
|
title: $title,
|
||||||
@ -153,7 +154,8 @@ export const CREATE_EVENT = gql`
|
|||||||
organizerActorId: $organizerActorId,
|
organizerActorId: $organizerActorId,
|
||||||
category: $category,
|
category: $category,
|
||||||
picture: $picture,
|
picture: $picture,
|
||||||
tags: $tags
|
tags: $tags,
|
||||||
|
physicalAddress: $physicalAddress
|
||||||
) {
|
) {
|
||||||
id,
|
id,
|
||||||
uuid,
|
uuid,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
export interface IAddress {
|
export interface IAddress {
|
||||||
|
id: number;
|
||||||
description: string;
|
description: string;
|
||||||
floor: string;
|
floor: string;
|
||||||
street: string;
|
street: string;
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
<tag-input v-model="event.tags" :data="tags" path="title" />
|
<tag-input v-model="event.tags" :data="tags" path="title" />
|
||||||
|
|
||||||
|
<address-auto-complete v-model="event.physicalAddress" />
|
||||||
|
|
||||||
<date-time-picker v-model="event.beginsOn" :label="$gettext('Starts on…')" :step="15"/>
|
<date-time-picker v-model="event.beginsOn" :label="$gettext('Starts on…')" :step="15"/>
|
||||||
<date-time-picker v-model="event.endsOn" :label="$gettext('Ends on…')" :step="15" />
|
<date-time-picker v-model="event.endsOn" :label="$gettext('Ends on…')" :step="15" />
|
||||||
|
|
||||||
@ -57,9 +59,10 @@ import DateTimePicker from '@/components/Event/DateTimePicker.vue';
|
|||||||
import TagInput from '@/components/Event/TagInput.vue';
|
import TagInput from '@/components/Event/TagInput.vue';
|
||||||
import { TAGS } from '@/graphql/tags';
|
import { TAGS } from '@/graphql/tags';
|
||||||
import { ITag } from '@/types/tag.model';
|
import { ITag } from '@/types/tag.model';
|
||||||
|
import AddressAutoComplete from '@/components/Event/AddressAutoComplete.vue';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: { TagInput, DateTimePicker, PictureUpload, Editor },
|
components: { AddressAutoComplete, TagInput, DateTimePicker, PictureUpload, Editor },
|
||||||
apollo: {
|
apollo: {
|
||||||
loggedPerson: {
|
loggedPerson: {
|
||||||
query: LOGGED_PERSON,
|
query: LOGGED_PERSON,
|
||||||
@ -134,9 +137,13 @@ export default class CreateEvent extends Vue {
|
|||||||
const obj = {
|
const obj = {
|
||||||
organizerActorId: this.loggedPerson.id,
|
organizerActorId: this.loggedPerson.id,
|
||||||
beginsOn: this.event.beginsOn.toISOString(),
|
beginsOn: this.event.beginsOn.toISOString(),
|
||||||
tags: this.event.tags.map((tag: ITag) => tag.title),
|
tags: this.event.tags.map((tag: ITag) => tag.title)
|
||||||
};
|
};
|
||||||
const res = Object.assign({}, this.event, obj);
|
let res = Object.assign({}, this.event, obj);
|
||||||
|
|
||||||
|
if (this.event.physicalAddress) {
|
||||||
|
delete this.event.physicalAddress['__typename'];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform picture files
|
* Transform picture files
|
||||||
|
@ -11,10 +11,10 @@ defmodule Mix.Tasks.Mobilizon.Toot do
|
|||||||
Mix.Task.run("app.start")
|
Mix.Task.run("app.start")
|
||||||
|
|
||||||
case MobilizonWeb.API.Comments.create_comment(from, content) do
|
case MobilizonWeb.API.Comments.create_comment(from, content) do
|
||||||
{:ok, _} ->
|
{:ok, _, _} ->
|
||||||
Mix.shell().info("Tooted")
|
Mix.shell().info("Tooted")
|
||||||
|
|
||||||
{:local_actor, _} ->
|
{:local_actor, _, _} ->
|
||||||
Mix.shell().error("Failed to toot.\nActor #{from} doesn't exist")
|
Mix.shell().error("Failed to toot.\nActor #{from} doesn't exist")
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
|
@ -6,6 +6,20 @@ defmodule Mobilizon.Addresses.Address do
|
|||||||
alias Mobilizon.Addresses.Address
|
alias Mobilizon.Addresses.Address
|
||||||
alias Mobilizon.Events.Event
|
alias Mobilizon.Events.Event
|
||||||
# alias Mobilizon.Actors.Actor
|
# alias Mobilizon.Actors.Actor
|
||||||
|
@attrs [
|
||||||
|
:description,
|
||||||
|
:floor,
|
||||||
|
:geom,
|
||||||
|
:country,
|
||||||
|
:locality,
|
||||||
|
:region,
|
||||||
|
:postal_code,
|
||||||
|
:street,
|
||||||
|
:url
|
||||||
|
]
|
||||||
|
@required [
|
||||||
|
:url
|
||||||
|
]
|
||||||
|
|
||||||
schema "addresses" do
|
schema "addresses" do
|
||||||
field(:country, :string)
|
field(:country, :string)
|
||||||
@ -16,8 +30,8 @@ defmodule Mobilizon.Addresses.Address do
|
|||||||
field(:geom, Geo.PostGIS.Geometry)
|
field(:geom, Geo.PostGIS.Geometry)
|
||||||
field(:postal_code, :string)
|
field(:postal_code, :string)
|
||||||
field(:street, :string)
|
field(:street, :string)
|
||||||
has_one(:event, Event, foreign_key: :physical_address_id)
|
field(:url, :string)
|
||||||
# has_one(:group, Actor)
|
has_many(:event, Event, foreign_key: :physical_address_id)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
@ -25,15 +39,15 @@ defmodule Mobilizon.Addresses.Address do
|
|||||||
@doc false
|
@doc false
|
||||||
def changeset(%Address{} = address, attrs) do
|
def changeset(%Address{} = address, attrs) do
|
||||||
address
|
address
|
||||||
|> cast(attrs, [
|
|> cast(attrs, @attrs)
|
||||||
:description,
|
|> set_url()
|
||||||
:floor,
|
|> validate_required(@required)
|
||||||
:geom,
|
end
|
||||||
:country,
|
|
||||||
:locality,
|
defp set_url(%Ecto.Changeset{changes: changes} = changeset) do
|
||||||
:region,
|
url =
|
||||||
:postal_code,
|
Map.get(changes, :url, MobilizonWeb.Endpoint.url() <> "/address/#{Ecto.UUID.generate()}")
|
||||||
:street
|
|
||||||
])
|
put_change(changeset, :url, url)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -50,6 +50,21 @@ defmodule Mobilizon.Addresses do
|
|||||||
"""
|
"""
|
||||||
def get_address!(id), do: Repo.get!(Address, id)
|
def get_address!(id), do: Repo.get!(Address, id)
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Gets a single address by it's url
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> get_address_by_url("https://mobilizon.social/addresses/4572")
|
||||||
|
%Address{}
|
||||||
|
|
||||||
|
iex> get_address_by_url("https://mobilizon.social/addresses/099")
|
||||||
|
nil
|
||||||
|
"""
|
||||||
|
def get_address_by_url(url) do
|
||||||
|
Repo.get_by(Address, url: url)
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Creates a address.
|
Creates a address.
|
||||||
|
|
||||||
@ -163,7 +178,7 @@ defmodule Mobilizon.Addresses do
|
|||||||
We only look at the description for now, and eventually order by object distance
|
We only look at the description for now, and eventually order by object distance
|
||||||
"""
|
"""
|
||||||
@spec search_addresses(String.t(), list()) :: list(Address.t())
|
@spec search_addresses(String.t(), list()) :: list(Address.t())
|
||||||
def search_addresses(search, options) do
|
def search_addresses(search, options \\ []) do
|
||||||
limit = Keyword.get(options, :limit, 5)
|
limit = Keyword.get(options, :limit, 5)
|
||||||
|
|
||||||
query = from(a in Address, where: ilike(a.description, ^"%#{search}%"), limit: ^limit)
|
query = from(a in Address, where: ilike(a.description, ^"%#{search}%"), limit: ^limit)
|
||||||
@ -181,7 +196,7 @@ defmodule Mobilizon.Addresses do
|
|||||||
do: from(a in query, where: ilike(a.country, ^"%#{country}%")),
|
do: from(a in query, where: ilike(a.country, ^"%#{country}%")),
|
||||||
else: query
|
else: query
|
||||||
|
|
||||||
Repo.all(query)
|
if Keyword.get(options, :single, false) == true, do: Repo.one(query), else: Repo.all(query)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -84,9 +84,9 @@ defmodule Mobilizon.Events.Event do
|
|||||||
:online_address,
|
:online_address,
|
||||||
:phone_address,
|
:phone_address,
|
||||||
:uuid,
|
:uuid,
|
||||||
:picture_id
|
:picture_id,
|
||||||
|
:physical_address_id
|
||||||
])
|
])
|
||||||
|> cast_assoc(:physical_address)
|
|
||||||
|> validate_required([
|
|> validate_required([
|
||||||
:title,
|
:title,
|
||||||
:begins_on,
|
:begins_on,
|
||||||
|
@ -382,7 +382,8 @@ defmodule Mobilizon.Events do
|
|||||||
|
|
||||||
defp do_create_event(attrs) do
|
defp do_create_event(attrs) do
|
||||||
with {:ok, %Event{} = event} <- %Event{} |> Event.changeset(attrs) |> Repo.insert(),
|
with {:ok, %Event{} = event} <- %Event{} |> Event.changeset(attrs) |> Repo.insert(),
|
||||||
%Event{} = event <- event |> Repo.preload([:tags, :organizer_actor]),
|
%Event{} = event <-
|
||||||
|
event |> Repo.preload([:tags, :organizer_actor, :physical_address, :picture]),
|
||||||
{:has_tags, true, _} <- {:has_tags, Map.has_key?(attrs, "tags"), event} do
|
{:has_tags, true, _} <- {:has_tags, Map.has_key?(attrs, "tags"), event} do
|
||||||
event
|
event
|
||||||
|> Ecto.Changeset.change()
|
|> Ecto.Changeset.change()
|
||||||
@ -513,8 +514,10 @@ defmodule Mobilizon.Events do
|
|||||||
@doc """
|
@doc """
|
||||||
Get an existing tag or create one
|
Get an existing tag or create one
|
||||||
"""
|
"""
|
||||||
@spec get_or_create_tag(String.t()) :: {:ok, Tag.t()} | {:error, any()}
|
@spec get_or_create_tag(map()) :: {:ok, Tag.t()} | {:error, any()}
|
||||||
def get_or_create_tag(title) do
|
def get_or_create_tag(tag) do
|
||||||
|
"#" <> title = tag["name"]
|
||||||
|
|
||||||
case Repo.get_by(Tag, title: title) do
|
case Repo.get_by(Tag, title: title) do
|
||||||
%Tag{} = tag ->
|
%Tag{} = tag ->
|
||||||
{:ok, tag}
|
{:ok, tag}
|
||||||
@ -1223,9 +1226,13 @@ defmodule Mobilizon.Events do
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
def create_comment(attrs \\ %{}) do
|
def create_comment(attrs \\ %{}) do
|
||||||
|
with {:ok, %Comment{} = comment} <-
|
||||||
%Comment{}
|
%Comment{}
|
||||||
|> Comment.changeset(attrs)
|
|> Comment.changeset(attrs)
|
||||||
|> Repo.insert()
|
|> Repo.insert(),
|
||||||
|
%Comment{} = comment <- Repo.preload(comment, [:actor, :in_reply_to_comment]) do
|
||||||
|
{:ok, comment}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -15,7 +15,8 @@ defmodule MobilizonWeb.API.Comments do
|
|||||||
|
|
||||||
Creates a comment from an actor and a status
|
Creates a comment from an actor and a status
|
||||||
"""
|
"""
|
||||||
@spec create_comment(String.t(), String.t(), String.t()) :: {:ok, Activity.t()} | any()
|
@spec create_comment(String.t(), String.t(), String.t()) ::
|
||||||
|
{:ok, Activity.t(), Comment.t()} | any()
|
||||||
def create_comment(
|
def create_comment(
|
||||||
from_username,
|
from_username,
|
||||||
status,
|
status,
|
||||||
|
@ -2,6 +2,7 @@ defmodule MobilizonWeb.API.Events do
|
|||||||
@moduledoc """
|
@moduledoc """
|
||||||
API for Events
|
API for Events
|
||||||
"""
|
"""
|
||||||
|
alias Mobilizon.Addresses
|
||||||
alias Mobilizon.Actors
|
alias Mobilizon.Actors
|
||||||
alias Mobilizon.Actors.Actor
|
alias Mobilizon.Actors.Actor
|
||||||
alias Mobilizon.Service.ActivityPub
|
alias Mobilizon.Service.ActivityPub
|
||||||
@ -11,7 +12,7 @@ defmodule MobilizonWeb.API.Events do
|
|||||||
@doc """
|
@doc """
|
||||||
Create an event
|
Create an event
|
||||||
"""
|
"""
|
||||||
@spec create_event(map()) :: {:ok, Activity.t()} | any()
|
@spec create_event(map()) :: {:ok, Activity.t(), Event.t()} | any()
|
||||||
def create_event(
|
def create_event(
|
||||||
%{
|
%{
|
||||||
title: title,
|
title: title,
|
||||||
@ -22,10 +23,9 @@ defmodule MobilizonWeb.API.Events do
|
|||||||
tags: tags
|
tags: tags
|
||||||
} = args
|
} = args
|
||||||
) do
|
) do
|
||||||
require Logger
|
|
||||||
|
|
||||||
with %Actor{url: url} = actor <-
|
with %Actor{url: url} = actor <-
|
||||||
Actors.get_local_actor_with_everything(organizer_actor_id),
|
Actors.get_local_actor_with_everything(organizer_actor_id),
|
||||||
|
physical_address <- Map.get(args, :physical_address, nil),
|
||||||
title <- String.trim(title),
|
title <- String.trim(title),
|
||||||
visibility <- Map.get(args, :visibility, :public),
|
visibility <- Map.get(args, :visibility, :public),
|
||||||
picture <- Map.get(args, :picture, nil),
|
picture <- Map.get(args, :picture, nil),
|
||||||
@ -34,14 +34,12 @@ defmodule MobilizonWeb.API.Events do
|
|||||||
event <-
|
event <-
|
||||||
ActivityPubUtils.make_event_data(
|
ActivityPubUtils.make_event_data(
|
||||||
url,
|
url,
|
||||||
to,
|
%{to: to, cc: cc},
|
||||||
title,
|
title,
|
||||||
content_html,
|
content_html,
|
||||||
picture,
|
picture,
|
||||||
tags,
|
tags,
|
||||||
cc,
|
%{begins_on: begins_on, physical_address: physical_address, category: category}
|
||||||
%{begins_on: begins_on},
|
|
||||||
category
|
|
||||||
) do
|
) do
|
||||||
ActivityPub.create(%{
|
ActivityPub.create(%{
|
||||||
to: ["https://www.w3.org/ns/activitystreams#Public"],
|
to: ["https://www.w3.org/ns/activitystreams#Public"],
|
||||||
@ -51,4 +49,15 @@ defmodule MobilizonWeb.API.Events do
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp get_physical_address(address_id) when is_number(address_id),
|
||||||
|
do: Addresses.get_address!(address_id)
|
||||||
|
|
||||||
|
defp get_physical_address(address_id) when is_binary(address_id) do
|
||||||
|
with {address_id, ""} <- Integer.parse(address_id) do
|
||||||
|
get_physical_address(address_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp get_physical_address(nil), do: nil
|
||||||
end
|
end
|
||||||
|
@ -11,7 +11,7 @@ defmodule MobilizonWeb.API.Groups do
|
|||||||
@doc """
|
@doc """
|
||||||
Create a group
|
Create a group
|
||||||
"""
|
"""
|
||||||
@spec create_group(map()) :: {:ok, Activity.t()} | any()
|
@spec create_group(map()) :: {:ok, Activity.t(), Group.t()} | any()
|
||||||
def create_group(
|
def create_group(
|
||||||
%{
|
%{
|
||||||
preferred_username: title,
|
preferred_username: title,
|
||||||
|
@ -11,7 +11,7 @@ defmodule MobilizonWeb.Resolvers.Address do
|
|||||||
Search an address
|
Search an address
|
||||||
"""
|
"""
|
||||||
@spec search(map(), map(), map()) :: {:ok, list(Address.t())}
|
@spec search(map(), map(), map()) :: {:ok, list(Address.t())}
|
||||||
def search(_parent, %{query: query}, %{context: %{ip: ip}}) do
|
def search(_parent, %{query: query, page: _page, limit: _limit}, %{context: %{ip: ip}}) do
|
||||||
country = Geolix.lookup(ip) |> Map.get(:country, nil)
|
country = Geolix.lookup(ip) |> Map.get(:country, nil)
|
||||||
|
|
||||||
local_addresses = Task.async(fn -> Addresses.search_addresses(query, country: country) end)
|
local_addresses = Task.async(fn -> Addresses.search_addresses(query, country: country) end)
|
||||||
|
@ -11,14 +11,10 @@ defmodule MobilizonWeb.Resolvers.Comment do
|
|||||||
def create_comment(_parent, %{text: comment, actor_username: username}, %{
|
def create_comment(_parent, %{text: comment, actor_username: username}, %{
|
||||||
context: %{current_user: %User{} = _user}
|
context: %{current_user: %User{} = _user}
|
||||||
}) do
|
}) do
|
||||||
with {:ok, %Activity{data: %{"object" => %{"type" => "Note"} = object}}} <-
|
with {:ok, %Activity{data: %{"object" => %{"type" => "Note"} = _object}},
|
||||||
|
%Comment{} = comment} <-
|
||||||
Comments.create_comment(username, comment) do
|
Comments.create_comment(username, comment) do
|
||||||
{:ok,
|
{:ok, comment}
|
||||||
%Comment{
|
|
||||||
text: object["content"],
|
|
||||||
url: object["id"],
|
|
||||||
uuid: object["uuid"]
|
|
||||||
}}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@ defmodule MobilizonWeb.Resolvers.Event do
|
|||||||
Handles the event-related GraphQL calls
|
Handles the event-related GraphQL calls
|
||||||
"""
|
"""
|
||||||
alias Mobilizon.Activity
|
alias Mobilizon.Activity
|
||||||
|
alias Mobilizon.Addresses
|
||||||
|
alias Mobilizon.Addresses.Address
|
||||||
alias Mobilizon.Events
|
alias Mobilizon.Events
|
||||||
alias Mobilizon.Events.{Event, Participant}
|
alias Mobilizon.Events.{Event, Participant}
|
||||||
alias Mobilizon.Media.Picture
|
alias Mobilizon.Media.Picture
|
||||||
@ -190,25 +192,10 @@ defmodule MobilizonWeb.Resolvers.Event do
|
|||||||
"""
|
"""
|
||||||
def create_event(_parent, args, %{context: %{current_user: _user}} = _resolution) do
|
def create_event(_parent, args, %{context: %{current_user: _user}} = _resolution) do
|
||||||
with {:ok, args} <- save_attached_picture(args),
|
with {:ok, args} <- save_attached_picture(args),
|
||||||
{:ok, %Activity{data: %{"object" => %{"type" => "Event"} = object}}} <-
|
{:ok, args} <- save_physical_address(args),
|
||||||
|
{:ok, %Activity{data: %{"object" => %{"type" => "Event"} = _object}}, %Event{} = event} <-
|
||||||
MobilizonWeb.API.Events.create_event(args) do
|
MobilizonWeb.API.Events.create_event(args) do
|
||||||
res = %{
|
{:ok, event}
|
||||||
title: object["name"],
|
|
||||||
description: object["content"],
|
|
||||||
uuid: object["uuid"],
|
|
||||||
url: object["id"]
|
|
||||||
}
|
|
||||||
|
|
||||||
res =
|
|
||||||
if Map.has_key?(object, "attachment"),
|
|
||||||
do:
|
|
||||||
Map.put(res, :picture, %{
|
|
||||||
name: object["attachment"] |> hd() |> Map.get("name"),
|
|
||||||
url: object["attachment"] |> hd() |> Map.get("url") |> hd() |> Map.get("href")
|
|
||||||
}),
|
|
||||||
else: res
|
|
||||||
|
|
||||||
{:ok, res}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -237,6 +224,25 @@ defmodule MobilizonWeb.Resolvers.Event do
|
|||||||
@spec save_attached_picture(map()) :: {:ok, map()}
|
@spec save_attached_picture(map()) :: {:ok, map()}
|
||||||
defp save_attached_picture(args), do: {:ok, args}
|
defp save_attached_picture(args), do: {:ok, args}
|
||||||
|
|
||||||
|
@spec save_physical_address(map()) :: {:ok, map()}
|
||||||
|
defp save_physical_address(%{physical_address: %{url: physical_address_url}} = args) do
|
||||||
|
with %Address{} = address <- Addresses.get_address_by_url(physical_address_url),
|
||||||
|
args <- Map.put(args, :physical_address, address) do
|
||||||
|
{:ok, args}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# @spec save_physical_address(map()) :: {:ok, map()}
|
||||||
|
# defp save_physical_address(%{physical_address: address} = args) do
|
||||||
|
# with {:ok, %Address{} = address} <- Addresses.create_address(address),
|
||||||
|
# args <- Map.put(args, :physical_address, address) do
|
||||||
|
# {:ok, args}
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
|
||||||
|
@spec save_physical_address(map()) :: {:ok, map()}
|
||||||
|
defp save_physical_address(args), do: {:ok, args}
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Delete an event
|
Delete an event
|
||||||
"""
|
"""
|
||||||
|
@ -47,20 +47,15 @@ defmodule MobilizonWeb.Resolvers.Group do
|
|||||||
:ok,
|
:ok,
|
||||||
%Activity{
|
%Activity{
|
||||||
data: %{
|
data: %{
|
||||||
"object" => %{"type" => "Group"} = object
|
"object" => %{"type" => "Group"} = _object
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
%Actor{} = group
|
||||||
} <-
|
} <-
|
||||||
MobilizonWeb.API.Groups.create_group(args) do
|
MobilizonWeb.API.Groups.create_group(args) do
|
||||||
{
|
{
|
||||||
:ok,
|
:ok,
|
||||||
%Actor{
|
group
|
||||||
preferred_username: object["preferredUsername"],
|
|
||||||
summary: object["summary"],
|
|
||||||
type: :Group,
|
|
||||||
# uuid: object["uuid"],
|
|
||||||
url: object["id"]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ defmodule MobilizonWeb.Schema.AddressType do
|
|||||||
field(:region, :string)
|
field(:region, :string)
|
||||||
field(:country, :string)
|
field(:country, :string)
|
||||||
field(:description, :string)
|
field(:description, :string)
|
||||||
|
field(:url, :string)
|
||||||
end
|
end
|
||||||
|
|
||||||
object :phone_address do
|
object :phone_address do
|
||||||
@ -26,10 +27,25 @@ defmodule MobilizonWeb.Schema.AddressType do
|
|||||||
field(:info, :string)
|
field(:info, :string)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
input_object :address_input do
|
||||||
|
# Either a full picture object
|
||||||
|
field(:geom, :point, description: "The geocoordinates for the point where this address is")
|
||||||
|
field(:floor, :string, description: "The floor this event is at")
|
||||||
|
field(:street, :string, description: "The address's street name (with number)")
|
||||||
|
field(:locality, :string, description: "The address's locality")
|
||||||
|
field(:postal_code, :string)
|
||||||
|
field(:region, :string)
|
||||||
|
field(:country, :string)
|
||||||
|
field(:description, :string)
|
||||||
|
field(:url, :string)
|
||||||
|
end
|
||||||
|
|
||||||
object :address_queries do
|
object :address_queries do
|
||||||
@desc "Search for an address"
|
@desc "Search for an address"
|
||||||
field :search_address, type: list_of(:address) do
|
field :search_address, type: list_of(:address) do
|
||||||
arg(:query, non_null(:string))
|
arg(:query, non_null(:string))
|
||||||
|
arg(:page, :integer, default_value: 1)
|
||||||
|
arg(:limit, :integer, default_value: 10)
|
||||||
|
|
||||||
resolve(&Resolvers.Address.search/3)
|
resolve(&Resolvers.Address.search/3)
|
||||||
end
|
end
|
||||||
|
@ -132,6 +132,7 @@ defmodule MobilizonWeb.Schema.EventType do
|
|||||||
arg(:phone_address, :string)
|
arg(:phone_address, :string)
|
||||||
arg(:organizer_actor_id, non_null(:id))
|
arg(:organizer_actor_id, non_null(:id))
|
||||||
arg(:category, non_null(:string))
|
arg(:category, non_null(:string))
|
||||||
|
arg(:physical_address, :address_input)
|
||||||
|
|
||||||
resolve(&Event.create_event/3)
|
resolve(&Event.create_event/3)
|
||||||
end
|
end
|
||||||
|
@ -70,10 +70,11 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||||||
def fetch_object_from_url(url) do
|
def fetch_object_from_url(url) do
|
||||||
Logger.info("Fetching object from url #{url}")
|
Logger.info("Fetching object from url #{url}")
|
||||||
|
|
||||||
with true <- String.starts_with?(url, "http"),
|
with {:not_http, true} <- {:not_http, String.starts_with?(url, "http")},
|
||||||
nil <- Events.get_event_by_url(url),
|
{:existing_event, nil} <- {:existing_event, Events.get_event_by_url(url)},
|
||||||
nil <- Events.get_comment_from_url(url),
|
{:existing_comment, nil} <- {:existing_comment, Events.get_comment_from_url(url)},
|
||||||
{:error, :actor_not_found} <- Actors.get_actor_by_url(url),
|
{:existing_actor, {:error, :actor_not_found}} <-
|
||||||
|
{:existing_actor, Actors.get_actor_by_url(url)},
|
||||||
{:ok, %{body: body, status_code: code}} when code in 200..299 <-
|
{:ok, %{body: body, status_code: code}} when code in 200..299 <-
|
||||||
HTTPoison.get(
|
HTTPoison.get(
|
||||||
url,
|
url,
|
||||||
@ -90,25 +91,32 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||||||
"actor" => data["attributedTo"],
|
"actor" => data["attributedTo"],
|
||||||
"object" => data
|
"object" => data
|
||||||
},
|
},
|
||||||
{:ok, activity} <- Transmogrifier.handle_incoming(params) do
|
{:ok, _activity, %{url: object_url} = _object} <- Transmogrifier.handle_incoming(params) do
|
||||||
case data["type"] do
|
case data["type"] do
|
||||||
"Event" ->
|
"Event" ->
|
||||||
{:ok, Events.get_event_by_url!(activity.data["object"]["id"])}
|
{:ok, Events.get_event_by_url!(object_url)}
|
||||||
|
|
||||||
"Note" ->
|
"Note" ->
|
||||||
{:ok, Events.get_comment_full_from_url!(activity.data["object"]["id"])}
|
{:ok, Events.get_comment_full_from_url!(object_url)}
|
||||||
|
|
||||||
"Actor" ->
|
"Actor" ->
|
||||||
{:ok, Actors.get_actor_by_url!(activity.data["object"]["id"], true)}
|
{:ok, Actors.get_actor_by_url!(object_url, true)}
|
||||||
|
|
||||||
other ->
|
other ->
|
||||||
{:error, other}
|
{:error, other}
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
%Event{url: event_url} -> {:ok, Events.get_event_by_url!(event_url)}
|
{:existing_event, %Event{url: event_url}} ->
|
||||||
%Comment{url: comment_url} -> {:ok, Events.get_comment_full_from_url!(comment_url)}
|
{:ok, Events.get_event_by_url!(event_url)}
|
||||||
%Actor{url: actor_url} -> {:ok, Actors.get_actor_by_url!(actor_url, true)}
|
|
||||||
e -> {:error, e}
|
{:existing_comment, %Comment{url: comment_url}} ->
|
||||||
|
{:ok, Events.get_comment_full_from_url!(comment_url)}
|
||||||
|
|
||||||
|
{:existing_actor, %Actor{url: actor_url}} ->
|
||||||
|
{:ok, Actors.get_actor_by_url!(actor_url, true)}
|
||||||
|
|
||||||
|
e ->
|
||||||
|
{:error, e}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -130,10 +138,10 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||||||
additional
|
additional
|
||||||
),
|
),
|
||||||
:ok <- Logger.debug(inspect(create_data)),
|
:ok <- Logger.debug(inspect(create_data)),
|
||||||
{:ok, activity, _object} <- insert(create_data, local),
|
{:ok, activity, object} <- insert(create_data, local),
|
||||||
:ok <- maybe_federate(activity) do
|
:ok <- maybe_federate(activity) do
|
||||||
# {:ok, actor} <- Actors.increase_event_count(actor) do
|
# {:ok, actor} <- Actors.increase_event_count(actor) do
|
||||||
{:ok, activity}
|
{:ok, activity, object}
|
||||||
else
|
else
|
||||||
err ->
|
err ->
|
||||||
Logger.error("Something went wrong")
|
Logger.error("Something went wrong")
|
||||||
@ -147,9 +155,9 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||||||
local = !(params[:local] == false)
|
local = !(params[:local] == false)
|
||||||
|
|
||||||
with data <- %{"to" => to, "type" => "Accept", "actor" => actor, "object" => object},
|
with data <- %{"to" => to, "type" => "Accept", "actor" => actor, "object" => object},
|
||||||
{:ok, activity, _object} <- insert(data, local),
|
{:ok, activity, object} <- insert(data, local),
|
||||||
:ok <- maybe_federate(activity) do
|
:ok <- maybe_federate(activity) do
|
||||||
{:ok, activity}
|
{:ok, activity, object}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -164,9 +172,9 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||||||
"actor" => actor,
|
"actor" => actor,
|
||||||
"object" => object
|
"object" => object
|
||||||
},
|
},
|
||||||
{:ok, activity, _object} <- insert(data, local),
|
{:ok, activity, object} <- insert(data, local),
|
||||||
:ok <- maybe_federate(activity) do
|
:ok <- maybe_federate(activity) do
|
||||||
{:ok, activity}
|
{:ok, activity, object}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -179,7 +187,7 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||||||
# ) do
|
# ) do
|
||||||
# with nil <- get_existing_like(url, object),
|
# with nil <- get_existing_like(url, object),
|
||||||
# like_data <- make_like_data(user, object, activity_id),
|
# like_data <- make_like_data(user, object, activity_id),
|
||||||
# {:ok, activity, _object} <- insert(like_data, local),
|
# {:ok, activity, object} <- insert(like_data, local),
|
||||||
# {:ok, object} <- add_like_to_object(activity, object),
|
# {:ok, object} <- add_like_to_object(activity, object),
|
||||||
# :ok <- maybe_federate(activity) do
|
# :ok <- maybe_federate(activity) do
|
||||||
# {:ok, activity, object}
|
# {:ok, activity, object}
|
||||||
@ -215,7 +223,7 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||||||
# ) do
|
# ) do
|
||||||
# #with true <- is_public?(object),
|
# #with true <- is_public?(object),
|
||||||
# with announce_data <- make_announce_data(actor, object, activity_id),
|
# with announce_data <- make_announce_data(actor, object, activity_id),
|
||||||
# {:ok, activity, _object} <- insert(announce_data, local),
|
# {:ok, activity, object} <- insert(announce_data, local),
|
||||||
# # {:ok, object} <- add_announce_to_object(activity, object),
|
# # {:ok, object} <- add_announce_to_object(activity, object),
|
||||||
# :ok <- maybe_federate(activity) do
|
# :ok <- maybe_federate(activity) do
|
||||||
# {:ok, activity, object}
|
# {:ok, activity, object}
|
||||||
@ -250,9 +258,9 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||||||
activity_follow_id <-
|
activity_follow_id <-
|
||||||
activity_id || "#{MobilizonWeb.Endpoint.url()}/follow/#{follow_id}/activity",
|
activity_id || "#{MobilizonWeb.Endpoint.url()}/follow/#{follow_id}/activity",
|
||||||
data <- make_follow_data(followed, follower, activity_follow_id),
|
data <- make_follow_data(followed, follower, activity_follow_id),
|
||||||
{:ok, activity, _object} <- insert(data, local),
|
{:ok, activity, object} <- insert(data, local),
|
||||||
:ok <- maybe_federate(activity) do
|
:ok <- maybe_federate(activity) do
|
||||||
{:ok, activity}
|
{:ok, activity, object}
|
||||||
else
|
else
|
||||||
{err, _} when err in [:already_following, :suspended] ->
|
{err, _} when err in [:already_following, :suspended] ->
|
||||||
{:error, err}
|
{:error, err}
|
||||||
@ -269,9 +277,9 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||||||
data <- make_follow_data(followed, follower, follow_id),
|
data <- make_follow_data(followed, follower, follow_id),
|
||||||
{:ok, follow_activity, _object} <- insert(data, local),
|
{:ok, follow_activity, _object} <- insert(data, local),
|
||||||
unfollow_data <- make_unfollow_data(follower, followed, follow_activity, activity_id),
|
unfollow_data <- make_unfollow_data(follower, followed, follow_activity, activity_id),
|
||||||
{:ok, activity, _object} <- insert(unfollow_data, local),
|
{:ok, activity, object} <- insert(unfollow_data, local),
|
||||||
:ok <- maybe_federate(activity) do
|
:ok <- maybe_federate(activity) do
|
||||||
{:ok, activity}
|
{:ok, activity, object}
|
||||||
else
|
else
|
||||||
err ->
|
err ->
|
||||||
Logger.error(inspect(err))
|
Logger.error(inspect(err))
|
||||||
@ -290,9 +298,9 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||||||
}
|
}
|
||||||
|
|
||||||
with {:ok, _} <- Events.delete_event(event),
|
with {:ok, _} <- Events.delete_event(event),
|
||||||
{:ok, activity, _object} <- insert(data, local),
|
{:ok, activity, object} <- insert(data, local),
|
||||||
:ok <- maybe_federate(activity) do
|
:ok <- maybe_federate(activity) do
|
||||||
{:ok, activity}
|
{:ok, activity, object}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -305,9 +313,9 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||||||
}
|
}
|
||||||
|
|
||||||
with {:ok, _} <- Events.delete_comment(comment),
|
with {:ok, _} <- Events.delete_comment(comment),
|
||||||
{:ok, activity, _object} <- insert(data, local),
|
{:ok, activity, object} <- insert(data, local),
|
||||||
:ok <- maybe_federate(activity) do
|
:ok <- maybe_federate(activity) do
|
||||||
{:ok, activity}
|
{:ok, activity, object}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -320,9 +328,9 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||||||
}
|
}
|
||||||
|
|
||||||
with {:ok, _} <- Actors.delete_actor(actor),
|
with {:ok, _} <- Actors.delete_actor(actor),
|
||||||
{:ok, activity, _object} <- insert(data, local),
|
{:ok, activity, object} <- insert(data, local),
|
||||||
:ok <- maybe_federate(activity) do
|
:ok <- maybe_federate(activity) do
|
||||||
{:ok, activity}
|
{:ok, activity, object}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
58
lib/service/activity_pub/converters/address.ex
Normal file
58
lib/service/activity_pub/converters/address.ex
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
defmodule Mobilizon.Service.ActivityPub.Converters.Address do
|
||||||
|
@moduledoc """
|
||||||
|
Flag converter
|
||||||
|
|
||||||
|
This module allows to convert reports from ActivityStream format to our own internal one, and back.
|
||||||
|
|
||||||
|
Note: Reports are named Flag in AS.
|
||||||
|
"""
|
||||||
|
alias Mobilizon.Addresses.Address, as: AddressModel
|
||||||
|
alias Mobilizon.Service.ActivityPub.Converter
|
||||||
|
|
||||||
|
@behaviour Converter
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Converts an AP object data to our internal data structure
|
||||||
|
"""
|
||||||
|
@impl Converter
|
||||||
|
@spec as_to_model_data(map()) :: map()
|
||||||
|
def as_to_model_data(object) do
|
||||||
|
res = %{
|
||||||
|
"description" => object["name"],
|
||||||
|
"url" => object["url"]
|
||||||
|
}
|
||||||
|
|
||||||
|
res =
|
||||||
|
if is_nil(object["address"]) do
|
||||||
|
res
|
||||||
|
else
|
||||||
|
Map.merge(res, %{
|
||||||
|
"country" => object["address"]["addressCountry"],
|
||||||
|
"postal_code" => object["address"]["postalCode"],
|
||||||
|
"region" => object["address"]["addressRegion"],
|
||||||
|
"street" => object["address"]["streetAddress"],
|
||||||
|
"locality" => object["address"]["addressLocality"]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
if is_nil(object["geo"]) do
|
||||||
|
res
|
||||||
|
else
|
||||||
|
geo = %Geo.Point{
|
||||||
|
coordinates: {object["geo"]["latitude"], object["geo"]["longitude"]},
|
||||||
|
srid: 4326
|
||||||
|
}
|
||||||
|
|
||||||
|
Map.put(res, "geom", geo)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Convert an event struct to an ActivityStream representation
|
||||||
|
"""
|
||||||
|
@impl Converter
|
||||||
|
@spec model_to_as(AddressModel.t()) :: map()
|
||||||
|
def model_to_as(%AddressModel{} = _address) do
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
@ -12,19 +12,28 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Event do
|
|||||||
alias Mobilizon.Service.ActivityPub.Converter
|
alias Mobilizon.Service.ActivityPub.Converter
|
||||||
alias Mobilizon.Events
|
alias Mobilizon.Events
|
||||||
alias Mobilizon.Events.Tag
|
alias Mobilizon.Events.Tag
|
||||||
|
alias Mobilizon.Addresses
|
||||||
|
alias Mobilizon.Addresses.Address
|
||||||
|
|
||||||
@behaviour Converter
|
@behaviour Converter
|
||||||
|
|
||||||
|
require Logger
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Converts an AP object data to our internal data structure
|
Converts an AP object data to our internal data structure
|
||||||
"""
|
"""
|
||||||
@impl Converter
|
@impl Converter
|
||||||
@spec as_to_model_data(map()) :: map()
|
@spec as_to_model_data(map()) :: map()
|
||||||
def as_to_model_data(object) do
|
def as_to_model_data(object) do
|
||||||
with {:ok, %Actor{id: actor_id}} <- Actors.get_actor_by_url(object["actor"]),
|
Logger.debug("event as_to_model_data")
|
||||||
tags <- fetch_tags(object["tag"]) do
|
|
||||||
|
with {:actor, {:ok, %Actor{id: actor_id}}} <-
|
||||||
|
{:actor, Actors.get_actor_by_url(object["actor"])},
|
||||||
|
{:address, address_id} <-
|
||||||
|
{:address, get_address(object["location"])},
|
||||||
|
{:tags, tags} <- {:tags, fetch_tags(object["tag"])} do
|
||||||
picture_id =
|
picture_id =
|
||||||
with true <- Map.has_key?(object, "attachment"),
|
with true <- Map.has_key?(object, "attachment") && length(object["attachment"]) > 0,
|
||||||
%Picture{id: picture_id} <-
|
%Picture{id: picture_id} <-
|
||||||
Media.get_picture_by_url(
|
Media.get_picture_by_url(
|
||||||
object["attachment"]
|
object["attachment"]
|
||||||
@ -38,27 +47,64 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Event do
|
|||||||
_ -> nil
|
_ -> nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
{:ok,
|
||||||
%{
|
%{
|
||||||
"title" => object["name"],
|
"title" => object["name"],
|
||||||
"description" => object["content"],
|
"description" => object["content"],
|
||||||
"organizer_actor_id" => actor_id,
|
"organizer_actor_id" => actor_id,
|
||||||
"picture_id" => picture_id,
|
"picture_id" => picture_id,
|
||||||
"begins_on" => object["begins_on"],
|
"begins_on" => object["startTime"],
|
||||||
"category" => object["category"],
|
"category" => object["category"],
|
||||||
"url" => object["id"],
|
"url" => object["id"],
|
||||||
"uuid" => object["uuid"],
|
"uuid" => object["uuid"],
|
||||||
"tags" => tags
|
"tags" => tags,
|
||||||
}
|
"physical_address_id" => address_id
|
||||||
|
}}
|
||||||
|
else
|
||||||
|
err ->
|
||||||
|
{:error, err}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp get_address(%{"id" => url} = map) when is_map(map) and is_binary(url) do
|
||||||
|
Logger.debug("Address with an URL, let's check against our own database")
|
||||||
|
|
||||||
|
case Addresses.get_address_by_url(url) do
|
||||||
|
%Address{id: address_id} ->
|
||||||
|
address_id
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
Logger.debug("not in our database, let's try to create it")
|
||||||
|
map = Map.put(map, "url", map["id"])
|
||||||
|
do_get_address(map)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp get_address(map) when is_map(map) do
|
||||||
|
do_get_address(map)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp get_address(nil), do: nil
|
||||||
|
|
||||||
|
defp do_get_address(map) do
|
||||||
|
map = Mobilizon.Service.ActivityPub.Converters.Address.as_to_model_data(map)
|
||||||
|
|
||||||
|
case Addresses.create_address(map) do
|
||||||
|
{:ok, %Address{id: address_id}} ->
|
||||||
|
address_id
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp fetch_tags(tags) do
|
defp fetch_tags(tags) do
|
||||||
Enum.reduce(tags, [], fn tag, acc ->
|
Enum.reduce(tags, [], fn tag, acc ->
|
||||||
case Events.get_or_create_tag(tag) do
|
with true <- tag["type"] == "Hashtag",
|
||||||
{:ok, %Tag{} = tag} ->
|
{:ok, %Tag{} = tag} <- Events.get_or_create_tag(tag) do
|
||||||
acc ++ [tag]
|
acc ++ [tag]
|
||||||
|
else
|
||||||
_ ->
|
_err ->
|
||||||
acc
|
acc
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
@ -132,9 +132,6 @@ defmodule Mobilizon.Service.ActivityPub.Transmogrifier do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: validate those with a Ecto scheme
|
|
||||||
# - tags
|
|
||||||
# - emoji
|
|
||||||
def handle_incoming(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do
|
def handle_incoming(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do
|
||||||
Logger.info("Handle incoming to create notes")
|
Logger.info("Handle incoming to create notes")
|
||||||
|
|
||||||
@ -159,15 +156,39 @@ defmodule Mobilizon.Service.ActivityPub.Transmogrifier do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def handle_incoming(%{"type" => "Create", "object" => %{"type" => "Event"} = object} = data) do
|
||||||
|
Logger.info("Handle incoming to create event")
|
||||||
|
|
||||||
|
with {:ok, %Actor{} = actor} <- Actors.get_or_fetch_by_url(data["actor"]) do
|
||||||
|
Logger.debug("found actor")
|
||||||
|
Logger.debug(inspect(actor))
|
||||||
|
|
||||||
|
params = %{
|
||||||
|
to: data["to"],
|
||||||
|
object: object |> fix_object,
|
||||||
|
actor: actor,
|
||||||
|
local: false,
|
||||||
|
published: data["published"],
|
||||||
|
additional:
|
||||||
|
Map.take(data, [
|
||||||
|
"cc",
|
||||||
|
"id"
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
ActivityPub.create(params)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def handle_incoming(
|
def handle_incoming(
|
||||||
%{"type" => "Follow", "object" => followed, "actor" => follower, "id" => id} = data
|
%{"type" => "Follow", "object" => followed, "actor" => follower, "id" => id} = data
|
||||||
) do
|
) do
|
||||||
with {:ok, %Actor{} = followed} <- Actors.get_or_fetch_by_url(followed, true),
|
with {:ok, %Actor{} = followed} <- Actors.get_or_fetch_by_url(followed, true),
|
||||||
{:ok, %Actor{} = follower} <- Actors.get_or_fetch_by_url(follower),
|
{:ok, %Actor{} = follower} <- Actors.get_or_fetch_by_url(follower),
|
||||||
{:ok, activity} <- ActivityPub.follow(follower, followed, id, false) do
|
{:ok, activity, object} <- ActivityPub.follow(follower, followed, id, false) do
|
||||||
ActivityPub.accept(%{to: [follower.url], actor: followed.url, object: data, local: true})
|
ActivityPub.accept(%{to: [follower.url], actor: followed.url, object: data, local: true})
|
||||||
|
|
||||||
{:ok, activity}
|
{:ok, activity, object}
|
||||||
else
|
else
|
||||||
e ->
|
e ->
|
||||||
Logger.error("Unable to handle Follow activity")
|
Logger.error("Unable to handle Follow activity")
|
||||||
@ -257,9 +278,9 @@ defmodule Mobilizon.Service.ActivityPub.Transmogrifier do
|
|||||||
) do
|
) do
|
||||||
with {:ok, %Actor{domain: nil} = followed} <- Actors.get_actor_by_url(followed),
|
with {:ok, %Actor{domain: nil} = followed} <- Actors.get_actor_by_url(followed),
|
||||||
{:ok, %Actor{} = follower} <- Actors.get_actor_by_url(follower),
|
{:ok, %Actor{} = follower} <- Actors.get_actor_by_url(follower),
|
||||||
{:ok, activity} <- ActivityPub.unfollow(followed, follower, id, false) do
|
{:ok, activity, object} <- ActivityPub.unfollow(followed, follower, id, false) do
|
||||||
Actor.unfollow(follower, followed)
|
Actor.unfollow(follower, followed)
|
||||||
{:ok, activity}
|
{:ok, activity, object}
|
||||||
else
|
else
|
||||||
e ->
|
e ->
|
||||||
Logger.error(inspect(e))
|
Logger.error(inspect(e))
|
||||||
@ -282,11 +303,11 @@ defmodule Mobilizon.Service.ActivityPub.Transmogrifier do
|
|||||||
{:ok, object} <- get_obj_helper(object_id) || fetch_obj_helper(object_id),
|
{:ok, object} <- get_obj_helper(object_id) || fetch_obj_helper(object_id),
|
||||||
# TODO : Validate that DELETE comes indeed form right domain (see above)
|
# TODO : Validate that DELETE comes indeed form right domain (see above)
|
||||||
# :ok <- contain_origin(actor_url, object.data),
|
# :ok <- contain_origin(actor_url, object.data),
|
||||||
{:ok, activity} <- ActivityPub.delete(object, false) do
|
{:ok, activity, object} <- ActivityPub.delete(object, false) do
|
||||||
{:ok, activity}
|
{:ok, activity, object}
|
||||||
else
|
else
|
||||||
e ->
|
e ->
|
||||||
Logger.debug(inspect(e))
|
Logger.error(inspect(e))
|
||||||
:error
|
:error
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -11,6 +11,7 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
alias Mobilizon.Repo
|
alias Mobilizon.Repo
|
||||||
|
alias Mobilizon.Addresses.Address
|
||||||
alias Mobilizon.Actors
|
alias Mobilizon.Actors
|
||||||
alias Mobilizon.Actors.Actor
|
alias Mobilizon.Actors.Actor
|
||||||
alias Mobilizon.Events.Event
|
alias Mobilizon.Events.Event
|
||||||
@ -122,7 +123,7 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
|
|||||||
"""
|
"""
|
||||||
def insert_full_object(%{"object" => %{"type" => "Event"} = object_data})
|
def insert_full_object(%{"object" => %{"type" => "Event"} = object_data})
|
||||||
when is_map(object_data) do
|
when is_map(object_data) do
|
||||||
with object_data <-
|
with {:ok, object_data} <-
|
||||||
Converters.Event.as_to_model_data(object_data),
|
Converters.Event.as_to_model_data(object_data),
|
||||||
{:ok, %Event{} = event} <- Events.create_event(object_data) do
|
{:ok, %Event{} = event} <- Events.create_event(object_data) do
|
||||||
{:ok, event}
|
{:ok, event}
|
||||||
@ -260,26 +261,21 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
|
|||||||
"""
|
"""
|
||||||
@spec make_event_data(
|
@spec make_event_data(
|
||||||
String.t(),
|
String.t(),
|
||||||
String.t(),
|
map(),
|
||||||
String.t(),
|
String.t(),
|
||||||
String.t(),
|
String.t(),
|
||||||
map(),
|
map(),
|
||||||
list(),
|
list(),
|
||||||
list(),
|
map()
|
||||||
map(),
|
|
||||||
String.t()
|
|
||||||
) :: map()
|
) :: map()
|
||||||
def make_event_data(
|
def make_event_data(
|
||||||
actor,
|
actor,
|
||||||
to,
|
%{to: to, cc: cc} = _audience,
|
||||||
title,
|
title,
|
||||||
content_html,
|
content_html,
|
||||||
picture \\ nil,
|
picture \\ nil,
|
||||||
tags \\ [],
|
tags \\ [],
|
||||||
# _cw \\ nil,
|
metadata \\ %{}
|
||||||
cc \\ [],
|
|
||||||
metadata \\ %{},
|
|
||||||
category \\ ""
|
|
||||||
) do
|
) do
|
||||||
Logger.debug("Making event data")
|
Logger.debug("Making event data")
|
||||||
uuid = Ecto.UUID.generate()
|
uuid = Ecto.UUID.generate()
|
||||||
@ -287,21 +283,58 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
|
|||||||
res = %{
|
res = %{
|
||||||
"type" => "Event",
|
"type" => "Event",
|
||||||
"to" => to,
|
"to" => to,
|
||||||
"cc" => cc,
|
"cc" => cc || [],
|
||||||
"content" => content_html,
|
"content" => content_html,
|
||||||
"name" => title,
|
"name" => title,
|
||||||
# "summary" => cw,
|
"startTime" => metadata.begins_on,
|
||||||
"begins_on" => metadata.begins_on,
|
"category" => metadata.category,
|
||||||
"category" => category,
|
|
||||||
"actor" => actor,
|
"actor" => actor,
|
||||||
"id" => Routes.page_url(Endpoint, :event, uuid),
|
"id" => Routes.page_url(Endpoint, :event, uuid),
|
||||||
"uuid" => uuid,
|
"uuid" => uuid,
|
||||||
"tag" => tags |> Enum.uniq()
|
"tag" =>
|
||||||
|
tags |> Enum.uniq() |> Enum.map(fn tag -> %{"type" => "Hashtag", "name" => "##{tag}"} end)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res =
|
||||||
|
if is_nil(metadata.physical_address),
|
||||||
|
do: res,
|
||||||
|
else: Map.put(res, "location", make_address_data(metadata.physical_address))
|
||||||
|
|
||||||
if is_nil(picture), do: res, else: Map.put(res, "attachment", [make_picture_data(picture)])
|
if is_nil(picture), do: res, else: Map.put(res, "attachment", [make_picture_data(picture)])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def make_address_data(%Address{} = address) do
|
||||||
|
res = %{
|
||||||
|
"type" => "Place",
|
||||||
|
"name" => address.description,
|
||||||
|
"id" => address.url,
|
||||||
|
"address" => %{
|
||||||
|
"type" => "PostalAddress",
|
||||||
|
"streetAddress" => address.street,
|
||||||
|
"postalCode" => address.postal_code,
|
||||||
|
"addressLocality" => address.locality,
|
||||||
|
"addressRegion" => address.region,
|
||||||
|
"addressCountry" => address.country
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_nil(address.geom) do
|
||||||
|
res
|
||||||
|
else
|
||||||
|
Map.put(res, "geo", %{
|
||||||
|
"type" => "GeoCoordinates",
|
||||||
|
"latitude" => address.geom.coordinates |> elem(0),
|
||||||
|
"longitude" => address.geom.coordinates |> elem(1)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def make_address_data(address) do
|
||||||
|
Address
|
||||||
|
|> struct(address)
|
||||||
|
|> make_address_data()
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Make an AP comment object from an set of values
|
Make an AP comment object from an set of values
|
||||||
"""
|
"""
|
||||||
|
@ -52,7 +52,7 @@ defmodule Mobilizon.Service.Federator do
|
|||||||
Logger.debug(inspect(params))
|
Logger.debug(inspect(params))
|
||||||
|
|
||||||
case Transmogrifier.handle_incoming(params) do
|
case Transmogrifier.handle_incoming(params) do
|
||||||
{:ok, activity} ->
|
{:ok, activity, _} ->
|
||||||
{:ok, activity}
|
{:ok, activity}
|
||||||
|
|
||||||
%Activity{} ->
|
%Activity{} ->
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
defmodule :"Elixir.Mobilizon.Repo.Migrations.Add-url-to-addresses" do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
alter table(:addresses) do
|
||||||
|
add(:url, :string, null: false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -1,5 +1,5 @@
|
|||||||
# source: http://localhost:4000/api
|
# source: http://localhost:4000/api
|
||||||
# timestamp: Fri Jul 26 2019 11:28:32 GMT+0200 (GMT+02:00)
|
# timestamp: Mon Jul 29 2019 15:24:10 GMT+0200 (GMT+02:00)
|
||||||
|
|
||||||
schema {
|
schema {
|
||||||
query: RootQueryType
|
query: RootQueryType
|
||||||
@ -121,6 +121,25 @@ type Address {
|
|||||||
street: String
|
street: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input AddressInput {
|
||||||
|
country: String
|
||||||
|
description: String
|
||||||
|
|
||||||
|
"""The floor this event is at"""
|
||||||
|
floor: String
|
||||||
|
|
||||||
|
"""The geocoordinates for the point where this address is"""
|
||||||
|
geom: Point
|
||||||
|
|
||||||
|
"""The address's locality"""
|
||||||
|
locality: String
|
||||||
|
postalCode: String
|
||||||
|
region: String
|
||||||
|
|
||||||
|
"""The address's street name (with number)"""
|
||||||
|
street: String
|
||||||
|
}
|
||||||
|
|
||||||
"""A comment"""
|
"""A comment"""
|
||||||
type Comment {
|
type Comment {
|
||||||
"""Internal ID for this comment"""
|
"""Internal ID for this comment"""
|
||||||
@ -675,6 +694,7 @@ type RootMutationType {
|
|||||||
onlineAddress: String
|
onlineAddress: String
|
||||||
organizerActorId: ID!
|
organizerActorId: ID!
|
||||||
phoneAddress: String
|
phoneAddress: String
|
||||||
|
physicalAddress: AddressInput
|
||||||
|
|
||||||
"""
|
"""
|
||||||
The picture for the event, either as an object or directly the ID of an existing Picture
|
The picture for the event, either as an object or directly the ID of an existing Picture
|
||||||
@ -891,7 +911,7 @@ type RootQueryType {
|
|||||||
reverseGeocode(latitude: Float!, longitude: Float!): [Address]
|
reverseGeocode(latitude: Float!, longitude: Float!): [Address]
|
||||||
|
|
||||||
"""Search for an address"""
|
"""Search for an address"""
|
||||||
searchAddress(query: String!): [Address]
|
searchAddress(limit: Int = 10, page: Int = 1, query: String!): [Address]
|
||||||
|
|
||||||
"""Search events"""
|
"""Search events"""
|
||||||
searchEvents(limit: Int = 10, page: Int = 1, search: String!): Events
|
searchEvents(limit: Int = 10, page: Int = 1, search: String!): Events
|
||||||
|
66
test/fixtures/mobilizon-post-activity.json
vendored
Normal file
66
test/fixtures/mobilizon-post-activity.json
vendored
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1",
|
||||||
|
{
|
||||||
|
"mblzn": "https://joinmobilizon.org/ns#",
|
||||||
|
"Hashtag": "as:Hashtag",
|
||||||
|
"sc": "http://schema.org#",
|
||||||
|
"Place": "sc:Place",
|
||||||
|
"PostalAddress": "sc:PostalAddress",
|
||||||
|
"uuid": "sc:identifier"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"actor": "https://event1.tcit.fr/@tcit",
|
||||||
|
"cc": [
|
||||||
|
"https://framapiaf.org/users/admin/followers",
|
||||||
|
"http://localtesting.pleroma.lol/users/lain"
|
||||||
|
],
|
||||||
|
"id": "https://event1.tcit.fr/@tcit/events/109ccdfd-ee3e-46e1-a877-6c228763df0c/activity",
|
||||||
|
"object": {
|
||||||
|
"attachment": [],
|
||||||
|
"attributedTo": "https://event1.tcit.fr/@tcit",
|
||||||
|
"startTime": "2018-02-12T14:08:20Z",
|
||||||
|
"cc": [
|
||||||
|
"https://framapiaf.org/users/admin/followers",
|
||||||
|
"http://localtesting.pleroma.lol/users/lain"
|
||||||
|
],
|
||||||
|
"content": "<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span></p>",
|
||||||
|
"category": "TODO remove me",
|
||||||
|
"id": "https://event1.tcit.fr/@tcit/events/109ccdfd-ee3e-46e1-a877-6c228763df0c",
|
||||||
|
"inReplyTo": null,
|
||||||
|
"location": {
|
||||||
|
"type": "Place",
|
||||||
|
"name": "Locaux de Framasoft",
|
||||||
|
"id": "https://event1.tcit.fr/address/eeecc11d-0030-43e8-a897-6422876372jd",
|
||||||
|
"address": {
|
||||||
|
"type": "PostalAddress",
|
||||||
|
"streetAddress": "10 Rue Jangot",
|
||||||
|
"postalCode": "69007",
|
||||||
|
"addressLocality": "Lyon",
|
||||||
|
"addressRegion": "Auvergne Rhône Alpes",
|
||||||
|
"addressCountry": "France"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "My first event",
|
||||||
|
"published": "2018-02-12T14:08:20Z",
|
||||||
|
"tag": [
|
||||||
|
{
|
||||||
|
"href": "http://localtesting.pleroma.lol/users/lain",
|
||||||
|
"name": "@lain@localtesting.pleroma.lol",
|
||||||
|
"type": "Mention"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"to": [
|
||||||
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
],
|
||||||
|
"type": "Event",
|
||||||
|
"url": "https://event1.tcit.fr/@tcit/events/109ccdfd-ee3e-46e1-a877-6c228763df0c",
|
||||||
|
"uuid": "109ccdfd-ee3e-46e1-a877-6c228763df0c"
|
||||||
|
},
|
||||||
|
"published": "2018-02-12T14:08:20Z",
|
||||||
|
"to": [
|
||||||
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
],
|
||||||
|
"type": "Create"
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
defmodule Mobilizon.AddressesTest do
|
defmodule Mobilizon.AddressesTest do
|
||||||
use Mobilizon.DataCase
|
use Mobilizon.DataCase
|
||||||
|
|
||||||
|
import Mobilizon.Factory
|
||||||
alias Mobilizon.Addresses
|
alias Mobilizon.Addresses
|
||||||
|
|
||||||
describe "addresses" do
|
describe "addresses" do
|
||||||
@ -37,22 +38,13 @@ defmodule Mobilizon.AddressesTest do
|
|||||||
# geom: nil
|
# geom: nil
|
||||||
# }
|
# }
|
||||||
|
|
||||||
def address_fixture(attrs \\ %{}) do
|
|
||||||
{:ok, address} =
|
|
||||||
attrs
|
|
||||||
|> Enum.into(@valid_attrs)
|
|
||||||
|> Addresses.create_address()
|
|
||||||
|
|
||||||
address
|
|
||||||
end
|
|
||||||
|
|
||||||
test "list_addresses/0 returns all addresses" do
|
test "list_addresses/0 returns all addresses" do
|
||||||
address = address_fixture()
|
address = insert(:address)
|
||||||
assert [address.id] == Addresses.list_addresses() |> Enum.map(& &1.id)
|
assert [address.id] == Addresses.list_addresses() |> Enum.map(& &1.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "get_address!/1 returns the address with given id" do
|
test "get_address!/1 returns the address with given id" do
|
||||||
address = address_fixture()
|
address = insert(:address)
|
||||||
assert Addresses.get_address!(address.id).id == address.id
|
assert Addresses.get_address!(address.id).id == address.id
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -68,7 +60,7 @@ defmodule Mobilizon.AddressesTest do
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "update_address/2 with valid data updates the address" do
|
test "update_address/2 with valid data updates the address" do
|
||||||
address = address_fixture()
|
address = insert(:address)
|
||||||
assert {:ok, %Address{} = address} = Addresses.update_address(address, @update_attrs)
|
assert {:ok, %Address{} = address} = Addresses.update_address(address, @update_attrs)
|
||||||
assert address.country == "some updated addressCountry"
|
assert address.country == "some updated addressCountry"
|
||||||
assert address.locality == "some updated addressLocality"
|
assert address.locality == "some updated addressLocality"
|
||||||
@ -80,13 +72,13 @@ defmodule Mobilizon.AddressesTest do
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "delete_address/1 deletes the address" do
|
test "delete_address/1 deletes the address" do
|
||||||
address = address_fixture()
|
address = insert(:address)
|
||||||
assert {:ok, %Address{}} = Addresses.delete_address(address)
|
assert {:ok, %Address{}} = Addresses.delete_address(address)
|
||||||
assert_raise Ecto.NoResultsError, fn -> Addresses.get_address!(address.id) end
|
assert_raise Ecto.NoResultsError, fn -> Addresses.get_address!(address.id) end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "change_address/1 returns a address changeset" do
|
test "change_address/1 returns a address changeset" do
|
||||||
address = address_fixture()
|
address = insert(:address)
|
||||||
assert %Ecto.Changeset{} = Addresses.change_address(address)
|
assert %Ecto.Changeset{} = Addresses.change_address(address)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ defmodule Mobilizon.Service.ActivityPub.ActivityPubTest do
|
|||||||
test "removes doubled 'to' recipients" do
|
test "removes doubled 'to' recipients" do
|
||||||
actor = insert(:actor)
|
actor = insert(:actor)
|
||||||
|
|
||||||
{:ok, activity} =
|
{:ok, activity, _} =
|
||||||
ActivityPub.create(%{
|
ActivityPub.create(%{
|
||||||
to: ["user1", "user1", "user2"],
|
to: ["user1", "user1", "user2"],
|
||||||
actor: actor,
|
actor: actor,
|
||||||
@ -113,7 +113,7 @@ defmodule Mobilizon.Service.ActivityPub.ActivityPubTest do
|
|||||||
test "it creates a delete activity and deletes the original event" do
|
test "it creates a delete activity and deletes the original event" do
|
||||||
event = insert(:event)
|
event = insert(:event)
|
||||||
event = Events.get_event_full_by_url!(event.url)
|
event = Events.get_event_full_by_url!(event.url)
|
||||||
{:ok, delete} = ActivityPub.delete(event)
|
{:ok, delete, _} = ActivityPub.delete(event)
|
||||||
|
|
||||||
assert delete.data["type"] == "Delete"
|
assert delete.data["type"] == "Delete"
|
||||||
assert delete.data["actor"] == event.organizer_actor.url
|
assert delete.data["actor"] == event.organizer_actor.url
|
||||||
@ -125,7 +125,7 @@ defmodule Mobilizon.Service.ActivityPub.ActivityPubTest do
|
|||||||
test "it creates a delete activity and deletes the original comment" do
|
test "it creates a delete activity and deletes the original comment" do
|
||||||
comment = insert(:comment)
|
comment = insert(:comment)
|
||||||
comment = Events.get_comment_full_from_url!(comment.url)
|
comment = Events.get_comment_full_from_url!(comment.url)
|
||||||
{:ok, delete} = ActivityPub.delete(comment)
|
{:ok, delete, _} = ActivityPub.delete(comment)
|
||||||
|
|
||||||
assert delete.data["type"] == "Delete"
|
assert delete.data["type"] == "Delete"
|
||||||
assert delete.data["actor"] == comment.actor.url
|
assert delete.data["actor"] == comment.actor.url
|
||||||
@ -140,7 +140,7 @@ defmodule Mobilizon.Service.ActivityPub.ActivityPubTest do
|
|||||||
actor = insert(:actor)
|
actor = insert(:actor)
|
||||||
actor_data = MobilizonWeb.ActivityPub.ActorView.render("actor.json", %{actor: actor})
|
actor_data = MobilizonWeb.ActivityPub.ActorView.render("actor.json", %{actor: actor})
|
||||||
|
|
||||||
{:ok, update} =
|
{:ok, update, _} =
|
||||||
ActivityPub.update(%{
|
ActivityPub.update(%{
|
||||||
actor: actor_data["url"],
|
actor: actor_data["url"],
|
||||||
to: [actor.url <> "/followers"],
|
to: [actor.url <> "/followers"],
|
||||||
|
@ -12,7 +12,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
alias Mobilizon.Actors
|
alias Mobilizon.Actors
|
||||||
alias Mobilizon.Actors.Actor
|
alias Mobilizon.Actors.Actor
|
||||||
alias Mobilizon.Events
|
alias Mobilizon.Events
|
||||||
alias Mobilizon.Events.Comment
|
alias Mobilizon.Events.{Comment, Event}
|
||||||
alias Mobilizon.Service.ActivityPub.Utils
|
alias Mobilizon.Service.ActivityPub.Utils
|
||||||
alias Mobilizon.Service.ActivityPub.Transmogrifier
|
alias Mobilizon.Service.ActivityPub.Transmogrifier
|
||||||
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
|
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
|
||||||
@ -21,7 +21,51 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
HTTPoison.start()
|
HTTPoison.start()
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "handle_incoming" do
|
describe "handle incoming events" do
|
||||||
|
test "it works for incoming events" do
|
||||||
|
data = File.read!("test/fixtures/mobilizon-post-activity.json") |> Jason.decode!()
|
||||||
|
|
||||||
|
{:ok, %Mobilizon.Activity{data: data, local: false}, %Event{} = event} =
|
||||||
|
Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
|
assert data["id"] ==
|
||||||
|
"https://event1.tcit.fr/@tcit/events/109ccdfd-ee3e-46e1-a877-6c228763df0c/activity"
|
||||||
|
|
||||||
|
assert data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
|
||||||
|
#
|
||||||
|
# assert data["cc"] == [
|
||||||
|
# "https://framapiaf.org/users/admin/followers",
|
||||||
|
# "http://localtesting.pleroma.lol/users/lain"
|
||||||
|
# ]
|
||||||
|
|
||||||
|
assert data["actor"] == "https://event1.tcit.fr/@tcit"
|
||||||
|
|
||||||
|
object = data["object"]
|
||||||
|
|
||||||
|
assert object["id"] ==
|
||||||
|
"https://event1.tcit.fr/@tcit/events/109ccdfd-ee3e-46e1-a877-6c228763df0c"
|
||||||
|
|
||||||
|
assert object["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
|
||||||
|
|
||||||
|
# assert object["cc"] == [
|
||||||
|
# "https://framapiaf.org/users/admin/followers",
|
||||||
|
# "http://localtesting.pleroma.lol/users/lain"
|
||||||
|
# ]
|
||||||
|
|
||||||
|
assert object["actor"] == "https://event1.tcit.fr/@tcit"
|
||||||
|
assert object["location"]["name"] == "Locaux de Framasoft"
|
||||||
|
assert object["attributedTo"] == "https://event1.tcit.fr/@tcit"
|
||||||
|
|
||||||
|
assert event.physical_address.street == "10 Rue Jangot"
|
||||||
|
|
||||||
|
assert event.physical_address.url ==
|
||||||
|
"https://event1.tcit.fr/address/eeecc11d-0030-43e8-a897-6422876372jd"
|
||||||
|
|
||||||
|
{:ok, %Actor{}} = Actors.get_actor_by_url(object["actor"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "handle incoming notices" do
|
||||||
# test "it ignores an incoming comment if we already have it" do
|
# test "it ignores an incoming comment if we already have it" do
|
||||||
# comment = insert(:comment)
|
# comment = insert(:comment)
|
||||||
|
|
||||||
@ -37,7 +81,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
# |> Jason.decode!()
|
# |> Jason.decode!()
|
||||||
# |> Map.put("object", activity["object"])
|
# |> Map.put("object", activity["object"])
|
||||||
|
|
||||||
# {:ok, returned_activity} = Transmogrifier.handle_incoming(data)
|
# {:ok, returned_activity, _} = Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
# assert activity == returned_activity.data
|
# assert activity == returned_activity.data
|
||||||
# end
|
# end
|
||||||
@ -55,7 +99,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
# data
|
# data
|
||||||
# |> Map.put("object", object)
|
# |> Map.put("object", object)
|
||||||
|
|
||||||
# {:ok, returned_activity} = Transmogrifier.handle_incoming(data)
|
# {:ok, returned_activity, _} = Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
# assert activity =
|
# assert activity =
|
||||||
# Activity.get_create_activity_by_object_ap_id(
|
# Activity.get_create_activity_by_object_ap_id(
|
||||||
@ -71,7 +115,8 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
test "it works for incoming notices" do
|
test "it works for incoming notices" do
|
||||||
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!()
|
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!()
|
||||||
|
|
||||||
{:ok, %Mobilizon.Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
{:ok, %Mobilizon.Activity{data: data, local: false}, _} =
|
||||||
|
Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
assert data["id"] == "https://framapiaf.org/users/admin/statuses/99512778738411822/activity"
|
assert data["id"] == "https://framapiaf.org/users/admin/statuses/99512778738411822/activity"
|
||||||
|
|
||||||
@ -105,7 +150,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
test "it works for incoming notices with hashtags" do
|
test "it works for incoming notices with hashtags" do
|
||||||
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)
|
||||||
assert Enum.at(data["object"]["tag"], 2) == "moo"
|
assert Enum.at(data["object"]["tag"], 2) == "moo"
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -113,7 +158,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
# data =
|
# data =
|
||||||
# File.read!("test/fixtures/mastodon-post-activity-contentmap.json") |> Jason.decode!()
|
# File.read!("test/fixtures/mastodon-post-activity-contentmap.json") |> Jason.decode!()
|
||||||
|
|
||||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
# {:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
# assert data["object"]["content"] ==
|
# assert data["object"]["content"] ==
|
||||||
# "<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span></p>"
|
# "<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span></p>"
|
||||||
@ -122,7 +167,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
# test "it works for incoming notices with to/cc not being an array (kroeg)" do
|
# test "it works for incoming notices with to/cc not being an array (kroeg)" do
|
||||||
# data = File.read!("test/fixtures/kroeg-post-activity.json") |> Jason.decode!()
|
# data = File.read!("test/fixtures/kroeg-post-activity.json") |> Jason.decode!()
|
||||||
|
|
||||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
# {:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
# assert data["object"]["content"] ==
|
# assert data["object"]["content"] ==
|
||||||
# "<p>henlo from my Psion netBook</p><p>message sent from my Psion netBook</p>"
|
# "<p>henlo from my Psion netBook</p><p>message sent from my Psion netBook</p>"
|
||||||
@ -131,7 +176,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
# test "it works for incoming announces with actor being inlined (kroeg)" do
|
# test "it works for incoming announces with actor being inlined (kroeg)" do
|
||||||
# data = File.read!("test/fixtures/kroeg-announce-with-inline-actor.json") |> Jason.decode!()
|
# data = File.read!("test/fixtures/kroeg-announce-with-inline-actor.json") |> Jason.decode!()
|
||||||
|
|
||||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
# {:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
# assert data["actor"] == "https://puckipedia.com/"
|
# assert data["actor"] == "https://puckipedia.com/"
|
||||||
# end
|
# end
|
||||||
@ -139,7 +184,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
# test "it works for incoming notices with tag not being an array (kroeg)" do
|
# test "it works for incoming notices with tag not being an array (kroeg)" do
|
||||||
# data = File.read!("test/fixtures/kroeg-array-less-emoji.json") |> Jason.decode!()
|
# data = File.read!("test/fixtures/kroeg-array-less-emoji.json") |> Jason.decode!()
|
||||||
|
|
||||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
# {:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
# assert data["object"]["emoji"] == %{
|
# assert data["object"]["emoji"] == %{
|
||||||
# "icon_e_smile" => "https://puckipedia.com/forum/images/smilies/icon_e_smile.png"
|
# "icon_e_smile" => "https://puckipedia.com/forum/images/smilies/icon_e_smile.png"
|
||||||
@ -147,7 +192,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
|
|
||||||
# data = File.read!("test/fixtures/kroeg-array-less-hashtag.json") |> Jason.decode!()
|
# data = File.read!("test/fixtures/kroeg-array-less-hashtag.json") |> Jason.decode!()
|
||||||
|
|
||||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
# {:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
# assert "test" in data["object"]["tag"]
|
# assert "test" in data["object"]["tag"]
|
||||||
# end
|
# end
|
||||||
@ -170,7 +215,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
|> Jason.decode!()
|
|> Jason.decode!()
|
||||||
|> Map.put("object", actor.url)
|
|> Map.put("object", actor.url)
|
||||||
|
|
||||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
assert data["actor"] == "https://social.tcit.fr/users/tcit"
|
assert data["actor"] == "https://social.tcit.fr/users/tcit"
|
||||||
assert data["type"] == "Follow"
|
assert data["type"] == "Follow"
|
||||||
@ -289,7 +334,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
test "it works for incoming update activities" do
|
test "it works for incoming update activities" do
|
||||||
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!()
|
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!()
|
||||||
|
|
||||||
{: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!()
|
||||||
|
|
||||||
object =
|
object =
|
||||||
@ -302,7 +347,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest 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}} = Transmogrifier.handle_incoming(update_data)
|
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(update_data)
|
||||||
|
|
||||||
{:ok, %Actor{} = actor} = Actors.get_actor_by_url(data["actor"])
|
{:ok, %Actor{} = actor} = Actors.get_actor_by_url(data["actor"])
|
||||||
assert actor.name == "gargle"
|
assert actor.name == "gargle"
|
||||||
@ -352,7 +397,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
|
|
||||||
assert Events.get_comment_from_url(comment_url)
|
assert Events.get_comment_from_url(comment_url)
|
||||||
|
|
||||||
{:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
|
{:ok, %Activity{local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
refute Events.get_comment_from_url(comment_url)
|
refute Events.get_comment_from_url(comment_url)
|
||||||
end
|
end
|
||||||
@ -413,14 +458,14 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
|> Jason.decode!()
|
|> Jason.decode!()
|
||||||
|> Map.put("object", actor.url)
|
|> Map.put("object", actor.url)
|
||||||
|
|
||||||
{:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(follow_data)
|
{:ok, %Activity{data: _, local: false}, _} = Transmogrifier.handle_incoming(follow_data)
|
||||||
|
|
||||||
data =
|
data =
|
||||||
File.read!("test/fixtures/mastodon-unfollow-activity.json")
|
File.read!("test/fixtures/mastodon-unfollow-activity.json")
|
||||||
|> Jason.decode!()
|
|> Jason.decode!()
|
||||||
|> Map.put("object", follow_data)
|
|> Map.put("object", follow_data)
|
||||||
|
|
||||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
assert data["type"] == "Undo"
|
assert data["type"] == "Undo"
|
||||||
assert data["object"]["type"] == "Follow"
|
assert data["object"]["type"] == "Follow"
|
||||||
@ -706,7 +751,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
actor = insert(:actor)
|
actor = insert(:actor)
|
||||||
other_actor = insert(:actor)
|
other_actor = insert(:actor)
|
||||||
|
|
||||||
{:ok, activity} =
|
{:ok, activity, _} =
|
||||||
MobilizonWeb.API.Comments.create_comment(
|
MobilizonWeb.API.Comments.create_comment(
|
||||||
actor.preferred_username,
|
actor.preferred_username,
|
||||||
"hey, @#{other_actor.preferred_username}, how are ya? #2hu"
|
"hey, @#{other_actor.preferred_username}, how are ya? #2hu"
|
||||||
@ -743,7 +788,9 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
test "it adds the json-ld context and the conversation property" do
|
test "it adds the json-ld context and the conversation property" do
|
||||||
actor = insert(:actor)
|
actor = insert(:actor)
|
||||||
|
|
||||||
{:ok, activity} = MobilizonWeb.API.Comments.create_comment(actor.preferred_username, "hey")
|
{:ok, activity, _} =
|
||||||
|
MobilizonWeb.API.Comments.create_comment(actor.preferred_username, "hey")
|
||||||
|
|
||||||
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
|
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
|
||||||
|
|
||||||
assert modified["@context"] == Utils.make_json_ld_header()["@context"]
|
assert modified["@context"] == Utils.make_json_ld_header()["@context"]
|
||||||
@ -752,7 +799,9 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
test "it sets the 'attributedTo' property to the actor of the object if it doesn't have one" do
|
test "it sets the 'attributedTo' property to the actor of the object if it doesn't have one" do
|
||||||
actor = insert(:actor)
|
actor = insert(:actor)
|
||||||
|
|
||||||
{:ok, activity} = MobilizonWeb.API.Comments.create_comment(actor.preferred_username, "hey")
|
{:ok, activity, _} =
|
||||||
|
MobilizonWeb.API.Comments.create_comment(actor.preferred_username, "hey")
|
||||||
|
|
||||||
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
|
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
|
||||||
|
|
||||||
assert modified["object"]["actor"] == modified["object"]["attributedTo"]
|
assert modified["object"]["actor"] == modified["object"]["attributedTo"]
|
||||||
@ -761,7 +810,8 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
test "it strips internal hashtag data" do
|
test "it strips internal hashtag data" do
|
||||||
actor = insert(:actor)
|
actor = insert(:actor)
|
||||||
|
|
||||||
{:ok, activity} = MobilizonWeb.API.Comments.create_comment(actor.preferred_username, "#2hu")
|
{:ok, activity, _} =
|
||||||
|
MobilizonWeb.API.Comments.create_comment(actor.preferred_username, "#2hu")
|
||||||
|
|
||||||
expected_tag = %{
|
expected_tag = %{
|
||||||
"href" => MobilizonWeb.Endpoint.url() <> "/tags/2hu",
|
"href" => MobilizonWeb.Endpoint.url() <> "/tags/2hu",
|
||||||
@ -777,7 +827,8 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
|
|||||||
test "it strips internal fields" do
|
test "it strips internal fields" do
|
||||||
actor = insert(:actor)
|
actor = insert(:actor)
|
||||||
|
|
||||||
{:ok, activity} = MobilizonWeb.API.Comments.create_comment(actor.preferred_username, "#2hu")
|
{:ok, activity, _} =
|
||||||
|
MobilizonWeb.API.Comments.create_comment(actor.preferred_username, "#2hu")
|
||||||
|
|
||||||
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
|
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
|
||||||
|
|
||||||
|
@ -122,6 +122,95 @@ defmodule MobilizonWeb.Resolvers.EventResolverTest do
|
|||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "create_event/3 creates an event with an address", %{
|
||||||
|
conn: conn,
|
||||||
|
actor: actor,
|
||||||
|
user: user
|
||||||
|
} do
|
||||||
|
address = insert(:address)
|
||||||
|
|
||||||
|
mutation = """
|
||||||
|
mutation {
|
||||||
|
createEvent(
|
||||||
|
title: "my event is referenced",
|
||||||
|
description: "with tags!",
|
||||||
|
begins_on: "#{
|
||||||
|
DateTime.utc_now() |> DateTime.truncate(:second) |> DateTime.to_iso8601()
|
||||||
|
}",
|
||||||
|
organizer_actor_id: "#{actor.id}",
|
||||||
|
category: "birthday",
|
||||||
|
physical_address: {
|
||||||
|
street: "#{address.street}",
|
||||||
|
locality: "#{address.locality}"
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
title,
|
||||||
|
uuid,
|
||||||
|
physicalAddress {
|
||||||
|
url,
|
||||||
|
geom,
|
||||||
|
street
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
res =
|
||||||
|
conn
|
||||||
|
|> auth_conn(user)
|
||||||
|
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation))
|
||||||
|
|
||||||
|
assert json_response(res, 200)["errors"] == nil
|
||||||
|
|
||||||
|
assert json_response(res, 200)["data"]["createEvent"]["title"] == "my event is referenced"
|
||||||
|
|
||||||
|
assert json_response(res, 200)["data"]["createEvent"]["physicalAddress"]["street"] ==
|
||||||
|
address.street
|
||||||
|
|
||||||
|
refute json_response(res, 200)["data"]["createEvent"]["physicalAddress"]["url"] ==
|
||||||
|
address.url
|
||||||
|
|
||||||
|
mutation = """
|
||||||
|
mutation {
|
||||||
|
createEvent(
|
||||||
|
title: "my event is referenced",
|
||||||
|
description: "with tags!",
|
||||||
|
begins_on: "#{
|
||||||
|
DateTime.utc_now() |> DateTime.truncate(:second) |> DateTime.to_iso8601()
|
||||||
|
}",
|
||||||
|
organizer_actor_id: "#{actor.id}",
|
||||||
|
category: "birthday",
|
||||||
|
physical_address: {
|
||||||
|
url: "#{address.url}"
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
title,
|
||||||
|
uuid,
|
||||||
|
physicalAddress {
|
||||||
|
url,
|
||||||
|
geom,
|
||||||
|
street
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
res =
|
||||||
|
conn
|
||||||
|
|> auth_conn(user)
|
||||||
|
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation))
|
||||||
|
|
||||||
|
assert json_response(res, 200)["errors"] == nil
|
||||||
|
|
||||||
|
assert json_response(res, 200)["data"]["createEvent"]["title"] == "my event is referenced"
|
||||||
|
|
||||||
|
assert json_response(res, 200)["data"]["createEvent"]["physicalAddress"]["street"] ==
|
||||||
|
address.street
|
||||||
|
|
||||||
|
assert json_response(res, 200)["data"]["createEvent"]["physicalAddress"]["url"] ==
|
||||||
|
address.url
|
||||||
|
end
|
||||||
|
|
||||||
test "create_event/3 creates an event with an attached picture", %{
|
test "create_event/3 creates an event with an attached picture", %{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
actor: actor,
|
actor: actor,
|
||||||
|
@ -78,6 +78,7 @@ defmodule Mobilizon.Factory do
|
|||||||
%Mobilizon.Addresses.Address{
|
%Mobilizon.Addresses.Address{
|
||||||
description: sequence("MyAddress"),
|
description: sequence("MyAddress"),
|
||||||
geom: %Geo.Point{coordinates: {45.75, 4.85}, srid: 4326},
|
geom: %Geo.Point{coordinates: {45.75, 4.85}, srid: 4326},
|
||||||
|
url: "http://mobilizon.test/address/#{Ecto.UUID.generate()}",
|
||||||
floor: "Myfloor",
|
floor: "Myfloor",
|
||||||
country: "My Country",
|
country: "My Country",
|
||||||
locality: "My Locality",
|
locality: "My Locality",
|
||||||
|
Loading…
Reference in New Issue
Block a user