Commit 73e74770 authored by Alex Castaño's avatar Alex Castaño

Merge branch 'release/0.0.18'

parents 69ddc990 f87aa9c5
...@@ -38,3 +38,5 @@ config/secret.exs ...@@ -38,3 +38,5 @@ config/secret.exs
cover cover
priv/repo/structure.sql priv/repo/structure.sql
*.dump
...@@ -68,4 +68,5 @@ run: ## Run the app in Docker ...@@ -68,4 +68,5 @@ run: ## Run the app in Docker
docker run\ docker run\
--env-file config/docker.env \ --env-file config/docker.env \
--expose 4000 -p 4000:4000 \ --expose 4000 -p 4000:4000 \
--rm -it moodlenet:latest --link postgres \
--rm -it moodlenet/moodlenet:$(APP_VSN)-$(APP_BUILD)
...@@ -4042,7 +4042,8 @@ ...@@ -4042,7 +4042,8 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
...@@ -4457,7 +4458,8 @@ ...@@ -4457,7 +4458,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.1", "version": "5.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
...@@ -4513,6 +4515,7 @@ ...@@ -4513,6 +4515,7 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
...@@ -4556,12 +4559,14 @@ ...@@ -4556,12 +4559,14 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.0.2", "version": "3.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
} }
} }
}, },
......
...@@ -81,3 +81,5 @@ config :moodle_net, MoodleNet.Repo, ...@@ -81,3 +81,5 @@ config :moodle_net, MoodleNet.Repo,
database: "moodle_net_dev", database: "moodle_net_dev",
hostname: "localhost", hostname: "localhost",
pool_size: 10 pool_size: 10
config :moodle_net, :ap_base_url, "http://dev.localhost:4000/activity_pub"
HOSTNAME=localhost HOSTNAME=localhost
SECRET_KEY_BASE="U1QXlca4ZEZKb1o3HL/aUlznI1qstCNAQ6yme/lFbFIs0Iqiq/annZ+Ty8JyUCDc" SECRET_KEY_BASE="U1QXlca4ZEZKb1o3HL/aUlznI1qstCNAQ6yme/lFbFIs0Iqiq/annZ+Ty8JyUCDc"
DATABASE_HOST=db DATABASE_HOST=postgres
DATABASE_USER=postgres DATABASE_USER=postgres
DATABASE_PASS=postgres DATABASE_PASS=postgres
DATABASE_NAME=moodle_net_prod DATABASE_NAME=moodle_net_prod
...@@ -8,3 +8,4 @@ PORT=4000 ...@@ -8,3 +8,4 @@ PORT=4000
LANG=en_US.UTF-8 LANG=en_US.UTF-8
REPLACE_OS_VARS=true REPLACE_OS_VARS=true
ERLANG_COOKIE=moodle_net_cookie ERLANG_COOKIE=moodle_net_cookie
AP_BASE_URL=http://localhost:4000/activity_pub
...@@ -27,3 +27,5 @@ config :phoenix_integration, ...@@ -27,3 +27,5 @@ config :phoenix_integration,
config :moodle_net, MoodleNet.Mailer, config :moodle_net, MoodleNet.Mailer,
adapter: Bamboo.TestAdapter adapter: Bamboo.TestAdapter
config :moodle_net, :ap_base_url, "http://test.localhost:4001/activity_pub"
...@@ -8,7 +8,8 @@ defmodule ActivityPub.CollectionAspect do ...@@ -8,7 +8,8 @@ defmodule ActivityPub.CollectionAspect do
# assoc(:current, functional: true) # assoc(:current, functional: true)
# assoc(:first, functional: true) # assoc(:first, functional: true)
# assoc(:last, functional: true) # assoc(:last, functional: true)
assoc(:items) # assoc(:items)
field(:items, :any, virtual: true)
# FIXME private attribute for the field? # FIXME private attribute for the field?
field(:__ordered__, :boolean) field(:__ordered__, :boolean)
......
defmodule ActivityPub.CollectionPageAspect do
use ActivityPub.Aspect, persistence: ActivityPub.SQLCollectionPageAspect
aspect do
# FIXME make just single
assoc(:part_of)
assoc(:next)
assoc(:prev)
end
end
...@@ -5,5 +5,6 @@ defmodule ActivityPub.Association do ...@@ -5,5 +5,6 @@ defmodule ActivityPub.Association do
functional: false, functional: false,
type: :any, type: :any,
autogenerated: false, autogenerated: false,
repeated: false,
inv: false inv: false
end end
...@@ -69,10 +69,11 @@ defmodule ActivityPub.Builder do ...@@ -69,10 +69,11 @@ defmodule ActivityPub.Builder do
defp build(:new, value, _, parent_key), defp build(:new, value, _, parent_key),
do: {:error, %BuildError{path: [parent_key], value: value, message: "is invalid"}} do: {:error, %BuildError{path: [parent_key], value: value, message: "is invalid"}}
defp build_new(%{"id" => value}, _, parent_key) do # FIXME !!! This was commented to create CollectionPage
msg = "is an autogenerated field" # defp build_new(%{"id" => value}, _, parent_key) do
build_error("id", value, msg, parent_key) # msg = "is an autogenerated field"
end # build_error("id", value, msg, parent_key)
# end
defp build_new(params, parent, parent_key) when is_map(params) do defp build_new(params, parent, parent_key) when is_map(params) do
{raw_context, params} = Map.pop(params, "@context") {raw_context, params} = Map.pop(params, "@context")
...@@ -81,7 +82,7 @@ defmodule ActivityPub.Builder do ...@@ -81,7 +82,7 @@ defmodule ActivityPub.Builder do
with {:ok, context} <- context(:new, raw_context, parent), with {:ok, context} <- context(:new, raw_context, parent),
{:ok, type} <- Types.build(raw_type), {:ok, type} <- Types.build(raw_type),
meta = Metadata.new(type), meta = Metadata.new(type),
entity = %{__ap__: meta, id: nil, type: type, "@context": context}, entity = %{__ap__: meta, id: params["id"], type: type, "@context": context},
{:ok, entity, params} <- merge_aspects_fields(entity, params), {:ok, entity, params} <- merge_aspects_fields(entity, params),
{:ok, entity, extension_fields} <- merge_aspects_assocs(entity, params), {:ok, entity, extension_fields} <- merge_aspects_assocs(entity, params),
entity = Map.merge(entity, extension_fields) do entity = Map.merge(entity, extension_fields) do
...@@ -163,12 +164,13 @@ defmodule ActivityPub.Builder do ...@@ -163,12 +164,13 @@ defmodule ActivityPub.Builder do
end end
end end
defp cast_and_put(_entity, raw_value, %{autogenerated: true} = field_def) do # FIXME !!! This was commented to create CollectionPage
msg = "is an autogenerated field, but data is received" # defp cast_and_put(_entity, raw_value, %{autogenerated: true} = field_def) do
field_name = to_string(field_def.name) # msg = "is an autogenerated field, but data is received"
error = %BuildError{path: [field_name], value: raw_value, message: msg} # field_name = to_string(field_def.name)
{:error, error} # error = %BuildError{path: [field_name], value: raw_value, message: msg}
end # {:error, error}
# end
defp cast_and_put(entity, raw_value, %{type: LanguageValueType, functional: true} = field_def) do defp cast_and_put(entity, raw_value, %{type: LanguageValueType, functional: true} = field_def) do
lang = entity[:"@context"].language lang = entity[:"@context"].language
......
...@@ -14,6 +14,12 @@ defmodule ActivityPub.Entity do ...@@ -14,6 +14,12 @@ defmodule ActivityPub.Entity do
def fields_for(_, _), do: %{} def fields_for(_, _), do: %{}
def fields(entity) when APG.is_entity(entity) do
entity
|> aspects()
|> Enum.flat_map(&fields_for(entity, &1))
end
def assocs_for(entity, aspect) when APG.has_aspect(entity, aspect), def assocs_for(entity, aspect) when APG.has_aspect(entity, aspect),
do: Map.take(entity, aspect.__aspect__(:associations)) do: Map.take(entity, aspect.__aspect__(:associations))
...@@ -35,10 +41,7 @@ defmodule ActivityPub.Entity do ...@@ -35,10 +41,7 @@ defmodule ActivityPub.Entity do
end) end)
end end
def local?(%{id: id} = e) when APG.is_entity(e) and not is_nil(id), def local?(%{__ap__: ap} = e) when APG.is_entity(e), do: Metadata.local?(ap)
do: ActivityPub.UrlBuilder.local?(id)
def local?(%{id: nil} = e) when APG.has_local_id(e), do: true
def local?(%{id: nil} = e) when APG.is_entity(e), do: status(e) == :new
def status(%{__ap__: %{status: status}} = e) when APG.is_entity(e), do: status def status(%{__ap__: %{status: status}} = e) when APG.is_entity(e), do: status
......
...@@ -6,6 +6,7 @@ defmodule ActivityPub.Field do ...@@ -6,6 +6,7 @@ defmodule ActivityPub.Field do
type: nil, type: nil,
default: nil, default: nil,
autogenerated: false, autogenerated: false,
repeated: false,
virtual: false virtual: false
def build(opts) do def build(opts) do
......
...@@ -3,6 +3,7 @@ defmodule ActivityPub.Guards do ...@@ -3,6 +3,7 @@ defmodule ActivityPub.Guards do
require APMG require APMG
defguard is_entity(e) when APMG.is_metadata(:erlang.map_get(:__ap__, e)) defguard is_entity(e) when APMG.is_metadata(:erlang.map_get(:__ap__, e))
defguard is_local(e) when APMG.is_local(:erlang.map_get(:__ap__, e))
defguard has_type(e, type) when APMG.has_type(:erlang.map_get(:__ap__, e), type) defguard has_type(e, type) when APMG.has_type(:erlang.map_get(:__ap__, e), type)
defguard has_aspect(e, aspect) when APMG.has_aspect(:erlang.map_get(:__ap__, e), aspect) defguard has_aspect(e, aspect) when APMG.has_aspect(:erlang.map_get(:__ap__, e), aspect)
defguard has_status(e, status) when APMG.has_status(:erlang.map_get(:__ap__, e), status) defguard has_status(e, status) when APMG.has_status(:erlang.map_get(:__ap__, e), status)
......
...@@ -6,7 +6,8 @@ defmodule ActivityPub.Metadata do ...@@ -6,7 +6,8 @@ defmodule ActivityPub.Metadata do
status: nil, status: nil,
persistence: nil, persistence: nil,
local_id: nil, local_id: nil,
verified: false verified: false,
local: true,
] ]
def new(type_list) do def new(type_list) do
...@@ -18,7 +19,8 @@ defmodule ActivityPub.Metadata do ...@@ -18,7 +19,8 @@ defmodule ActivityPub.Metadata do
aspects: aspects, aspects: aspects,
status: :new, status: :new,
persistence: nil, persistence: nil,
verified: true verified: true,
local: true,
} }
end end
...@@ -29,6 +31,7 @@ defmodule ActivityPub.Metadata do ...@@ -29,6 +31,7 @@ defmodule ActivityPub.Metadata do
status: :not_loaded, status: :not_loaded,
persistence: nil, persistence: nil,
verified: false, verified: false,
local: true,
local_id: nil local_id: nil
} }
end end
...@@ -38,6 +41,7 @@ defmodule ActivityPub.Metadata do ...@@ -38,6 +41,7 @@ defmodule ActivityPub.Metadata do
status: :not_loaded, status: :not_loaded,
persistence: nil, persistence: nil,
verified: true, verified: true,
local: true,
local_id: local_id local_id: local_id
} }
end end
...@@ -52,6 +56,7 @@ defmodule ActivityPub.Metadata do ...@@ -52,6 +56,7 @@ defmodule ActivityPub.Metadata do
status: :loaded, status: :loaded,
persistence: sql, persistence: sql,
local_id: sql.local_id, local_id: sql.local_id,
local: sql.local,
verified: true verified: true
} }
end end
...@@ -66,6 +71,9 @@ defmodule ActivityPub.Metadata do ...@@ -66,6 +71,9 @@ defmodule ActivityPub.Metadata do
def local_id(%__MODULE__{local_id: local_id}), do: local_id def local_id(%__MODULE__{local_id: local_id}), do: local_id
def local?(%__MODULE__{local: true}), do: true
def local?(%__MODULE__{}), do: false
def inspect(%__MODULE__{} = meta, opts) do def inspect(%__MODULE__{} = meta, opts) do
pruned = %{ pruned = %{
status: meta.status, status: meta.status,
...@@ -84,6 +92,7 @@ end ...@@ -84,6 +92,7 @@ end
defmodule ActivityPub.Metadata.Guards do defmodule ActivityPub.Metadata.Guards do
defguard is_metadata(meta) when :erlang.map_get(:__struct__, meta) == ActivityPub.Metadata defguard is_metadata(meta) when :erlang.map_get(:__struct__, meta) == ActivityPub.Metadata
defguard is_local(meta) when :erlang.map_get(:local, meta) == true
defguard has_type(meta, type) defguard has_type(meta, type)
when is_metadata(meta) and :erlang.map_get(type, :erlang.map_get(:types, meta)) when is_metadata(meta) and :erlang.map_get(type, :erlang.map_get(:types, meta))
......
...@@ -8,5 +8,6 @@ defmodule ActivityPub.SQL.Associations.Collection do ...@@ -8,5 +8,6 @@ defmodule ActivityPub.SQL.Associations.Collection do
autogenerated: true, autogenerated: true,
table_name: "activity_pub_collection_items", table_name: "activity_pub_collection_items",
join_keys: [:subject_id, :target_id], join_keys: [:subject_id, :target_id],
repeated: false,
foreign_key: nil foreign_key: nil
end end
...@@ -26,12 +26,16 @@ defmodule ActivityPub.SQL.Paginate do ...@@ -26,12 +26,16 @@ defmodule ActivityPub.SQL.Paginate do
%{ %{
limit: calc_limit(query_params), limit: calc_limit(query_params),
after: query_params[:after] || query_params["after"], after: query_params[:after] || query_params["after"] |> to_integer(),
before: query_params[:before] || query_params["before"] before: query_params[:before] || query_params["before"] |> to_integer()
} }
|> calc_order() |> calc_order()
end end
defp to_integer(binary) when is_binary(binary), do: String.to_integer(binary)
defp to_integer(integer) when is_integer(integer), do: integer
defp to_integer(nil), do: nil
defp calc_limit(query_params) do defp calc_limit(query_params) do
Enum.min([query_params[:limit] || query_params["limit"] || 100, 100]) Enum.min([query_params[:limit] || query_params["limit"] || 100, 100])
end end
......
...@@ -29,6 +29,12 @@ defmodule ActivityPub.SQL.Query do ...@@ -29,6 +29,12 @@ defmodule ActivityPub.SQL.Query do
|> Repo.delete_all() |> Repo.delete_all()
end end
# FIXME this should not be here?
def update_all(%Ecto.Query{} = query, updates) do
query
|> Repo.update_all(updates)
end
def one(%Ecto.Query{} = query) do def one(%Ecto.Query{} = query) do
query query
# |> print_query() # |> print_query()
...@@ -70,6 +76,11 @@ defmodule ActivityPub.SQL.Query do ...@@ -70,6 +76,11 @@ defmodule ActivityPub.SQL.Query do
def get_by_id(id, opts \\ []) when is_binary(id) do def get_by_id(id, opts \\ []) when is_binary(id) do
case UrlBuilder.get_local_id(id) do case UrlBuilder.get_local_id(id) do
{:ok, {:page, collection_id, params}} ->
collection = get_by_local_id(collection_id, opts)
{:ok, page} = ActivityPub.CollectionPage.new(collection, params)
page
{:ok, local_id} -> {:ok, local_id} ->
get_by_local_id(local_id, opts) get_by_local_id(local_id, opts)
...@@ -128,7 +139,7 @@ defmodule ActivityPub.SQL.Query do ...@@ -128,7 +139,7 @@ defmodule ActivityPub.SQL.Query do
def without_type(%Ecto.Query{} = query, type) when is_binary(type) do def without_type(%Ecto.Query{} = query, type) when is_binary(type) do
from([entity: entity] in query, from([entity: entity] in query,
where: not(fragment("? @> array[?]", entity.type, ^type)) where: not fragment("? @> array[?]", entity.type, ^type)
) )
end end
...@@ -233,6 +244,16 @@ defmodule ActivityPub.SQL.Query do ...@@ -233,6 +244,16 @@ defmodule ActivityPub.SQL.Query do
when APG.is_entity(subject) and APG.has_status(subject, :loaded) and is_integer(target), when APG.is_entity(subject) and APG.has_status(subject, :loaded) and is_integer(target),
do: do_has?(subject, rel, target) do: do_has?(subject, rel, target)
def belongs_to(%Ecto.Query{} = query, collection) when APG.has_type(collection, "Collection") do
collection_local_id = ActivityPub.local_id(collection)
from([entity: entity] in query,
inner_join: rel in "activity_pub_collection_items",
as: :items,
on: entity.local_id == rel.target_id,
where: rel.subject_id == ^collection_local_id
)
end
for sql_aspect <- ActivityPub.SQLAspect.all() do for sql_aspect <- ActivityPub.SQLAspect.all() do
Enum.map(sql_aspect.__sql_aspect__(:associations), fn Enum.map(sql_aspect.__sql_aspect__(:associations), fn
%ManyToMany{ %ManyToMany{
...@@ -427,6 +448,11 @@ defmodule ActivityPub.SQL.Query do ...@@ -427,6 +448,11 @@ defmodule ActivityPub.SQL.Query do
def preload_assoc([], _preload), do: [] def preload_assoc([], _preload), do: []
def preload_assoc(entity, :all) when APG.is_entity(entity) do
assoc_keys = Map.keys(Entity.assocs(entity))
preload_assoc(entity, assoc_keys)
end
def preload_assoc(entity, preload) when not is_list(preload), def preload_assoc(entity, preload) when not is_list(preload),
do: preload_assoc(entity, List.wrap(preload)) do: preload_assoc(entity, List.wrap(preload))
......
...@@ -3,12 +3,4 @@ defmodule ActivityPub.SQLActivityAspect do ...@@ -3,12 +3,4 @@ defmodule ActivityPub.SQLActivityAspect do
aspect: ActivityPub.ActivityAspect, aspect: ActivityPub.ActivityAspect,
persistence_method: :table, persistence_method: :table,
table_name: "activity_pub_activity_aspects" table_name: "activity_pub_activity_aspects"
# alias ActivityPub.SQLObject
# @primary_key {:local_id, :id, autogenerate: true}
# schema "activity_pub_activity_aspects" do
# # many_to_many :actor, SQLObject, join_through: "activity_pub_activity_actors",
# # join_keys: [local_id: :activity_id, object_id: :local_id]
# end
end end
...@@ -3,8 +3,7 @@ defmodule ActivityPub.SQLAspect do ...@@ -3,8 +3,7 @@ defmodule ActivityPub.SQLAspect do
SQLObjectAspect, SQLObjectAspect,
SQLActorAspect, SQLActorAspect,
SQLActivityAspect, SQLActivityAspect,
SQLCollectionAspect, SQLCollectionAspect
SQLResourceAspect
} }
alias ActivityPub.SQL.Associations.{ManyToMany, BelongsTo, Collection} alias ActivityPub.SQL.Associations.{ManyToMany, BelongsTo, Collection}
...@@ -15,7 +14,9 @@ defmodule ActivityPub.SQLAspect do ...@@ -15,7 +14,9 @@ defmodule ActivityPub.SQLAspect do
SQLActorAspect, SQLActorAspect,
SQLActivityAspect, SQLActivityAspect,
SQLCollectionAspect, SQLCollectionAspect,
SQLResourceAspect MoodleNet.AP.SQLCommunityAspect,
MoodleNet.AP.SQLCollectionAspect,
MoodleNet.AP.SQLResourceAspect
] ]
# FIXME make this similar to aspect where the user can redifine # FIXME make this similar to aspect where the user can redifine
...@@ -140,6 +141,9 @@ defmodule ActivityPub.SQLAspect do ...@@ -140,6 +141,9 @@ defmodule ActivityPub.SQLAspect do
join_keys: [{subject_key, :local_id}, {target_key, :local_id}] join_keys: [{subject_key, :local_id}, {target_key, :local_id}]
) )
%Collection{repeated: true} ->
nil
%Collection{} = assoc -> %Collection{} = assoc ->
belongs_to(assoc.name, ActivityPub.SQLEntity, references: :local_id) belongs_to(assoc.name, ActivityPub.SQLEntity, references: :local_id)
...@@ -188,6 +192,7 @@ defmodule ActivityPub.SQLAspect do ...@@ -188,6 +192,7 @@ defmodule ActivityPub.SQLAspect do
name: assoc.name, name: assoc.name,
type: assoc.type, type: assoc.type,
autogenerated: assoc.autogenerated, autogenerated: assoc.autogenerated,
repeated: assoc.repeated,
foreign_key: foreign_key foreign_key: foreign_key
} }
end end
......
...@@ -4,17 +4,4 @@ defmodule ActivityPub.SQLObjectAspect do ...@@ -4,17 +4,4 @@ defmodule ActivityPub.SQLObjectAspect do
use ActivityPub.SQLAspect, use ActivityPub.SQLAspect,
aspect: ObjectAspect, aspect: ObjectAspect,
persistence_method: :fields persistence_method: :fields
# sql_aspect do
# persistence_method(:fields)
# join_through_assoc(:attachment, table_name: "activity_pub_object_attachments",
# keys: {:subject_id, :target_id})
# virtual_col_assoc
# assoc(:name, VirtualCollectionAssoc)
# assoc(:name, VirtualCollectionAssoc)
# # assoc(:attachment, method: {:table, "activity_pub_object_attachments"},
# # keys: {:subject_id, :target_id}
# end
end end
defmodule ActivityPub.Types do defmodule ActivityPub.Types do
alias ActivityPub.{ alias ActivityPub.{ObjectAspect, ActorAspect, ActivityAspect, CollectionAspect}
ObjectAspect,
ActorAspect,
ActivityAspect,
# LinkAspect,
CollectionAspect,
ResourceAspect,
}
alias ActivityPub.BuildError alias ActivityPub.BuildError
@type_map %{ @type_map %{
# "Link" => {[], [LinkAspect]},
"Link" => {[], []}, "Link" => {[], []},
"Object" => {[], [ObjectAspect]}, "Object" => {[], [ObjectAspect]},
"Collection" => {~w[Object], [CollectionAspect]}, "Collection" => {~w[Object], [CollectionAspect]},
"OrderedCollection" => {~w[Object Collection], []}, "OrderedCollection" => {~w[Object Collection], []},
# "CollectionPage" => {~w[Object Collection], [CollectionPageAspect]},
"CollectionPage" => {~w[Object Collection], []}, "CollectionPage" => {~w[Object Collection], []},
"OrderedCollectionPage" => {~w[Object Collection OrderedCollection CollectionPage], []}, "OrderedCollectionPage" => {~w[Object Collection OrderedCollection CollectionPage], []},
"Actor" => {~w[Object], [ActorAspect]}, "Actor" => {~w[Object], [ActorAspect]},
...@@ -68,10 +59,9 @@ defmodule ActivityPub.Types do ...@@ -68,10 +59,9 @@ defmodule ActivityPub.Types do
"Tombstone" => {~w[Object], []}, "Tombstone" => {~w[Object], []},
"Video" => {~w[Object], []}, "Video" => {~w[Object], []},
"Mention" => {~w[Link], []}, "Mention" => {~w[Link], []},
"MoodleNet:Community" => {~w[Object Actor Group Collection], []}, "MoodleNet:Community" => {~w[Object Actor Group], [MoodleNet.AP.CommunityAspect]},
"MoodleNet:Collection" => {~w[Object Actor Group Collection], []}, "MoodleNet:Collection" => {~w[Object Actor Group], [MoodleNet.AP.CollectionAspect]},
# "MoodleNet:EducationalResource" => {~w[Link], []}, "MoodleNet:EducationalResource" => {~w[Object Page WebPage], [MoodleNet.AP.ResourceAspect]}
"MoodleNet:EducationalResource" => {~w[Object Page WebPage], [ResourceAspect]}
} }
def build(value) do def build(value) do
......
defmodule ActivityPub.UrlBuilder do defmodule ActivityPub.UrlBuilder do
defp base_url() do defp base_url() do
MoodleNetWeb.base_url() Application.get_env(:moodle_net, :ap_base_url, MoodleNetWeb.base_url())
end end
def id(local_id) do def id({:page, local_id, params}) do
"#{base_url()}/activity_pub/#{local_id}" id(local_id) <> "/page" <> params_to_query(params)
end end
def id(local_id) when is_integer(local_id),
do: append_bar_if_needed(base_url()) <> to_string(local_id)
def local?(nil), do: false def local?(nil), do: false
def local?(id) when is_binary(id) do def local?(id) when is_binary(id) do
...@@ -21,13 +24,50 @@ defmodule ActivityPub.UrlBuilder do ...@@ -21,13 +24,50 @@ defmodule ActivityPub.UrlBuilder do
uri_id = URI.parse(id) uri_id = URI.parse(id)
uri_base = URI.parse(base_url()) uri_base = URI.parse(base_url())
with true <- uri_id.scheme == uri_base.scheme and uri_id.host == uri_base.host and with true <- same_base_url?(uri_base, uri_id),
uri_id.port == uri_base.port, {:ok, id_string} <- truncate_base_path(uri_base.path, uri_id.path),
"/activity_pub/" <> local_id <- uri_id.path, {id, rest} <- Integer.parse(id_string) do
local_id = String.to_integer(local_id) do virtual_id(id, rest, uri_id.query)
{:ok, local_id}
else else
_ -> :error _ -> :error
end end
end end
defp same_base_url?(uri_base, uri_id) do
uri_id.scheme == uri_base.scheme and uri_id.host == uri_base.host and
uri_id.port == uri_base.port
end
defp truncate_base_path(nil, uri_id_path), do: {:ok, uri_id_path