ActivityPub helpers and object route
This commit is contained in:
parent
3818e713cd
commit
70370fb824
|
@ -25,6 +25,10 @@ config :logger, :console,
|
||||||
# Use Jason for JSON parsing in Phoenix
|
# Use Jason for JSON parsing in Phoenix
|
||||||
config :phoenix, :json_library, Jason
|
config :phoenix, :json_library, Jason
|
||||||
|
|
||||||
|
config :mime, :types, %{
|
||||||
|
"application/activity+json" => ["activity+json"]
|
||||||
|
}
|
||||||
|
|
||||||
# Import environment specific config. This must remain at the bottom
|
# Import environment specific config. This must remain at the bottom
|
||||||
# of this file so it overrides the configuration defined above.
|
# of this file so it overrides the configuration defined above.
|
||||||
import_config "#{Mix.env()}.exs"
|
import_config "#{Mix.env()}.exs"
|
||||||
|
|
|
@ -16,6 +16,7 @@ config :clacks, Clacks.Repo,
|
||||||
# watchers to your application. For example, we use it
|
# watchers to your application. For example, we use it
|
||||||
# with webpack to recompile .js and .css sources.
|
# with webpack to recompile .js and .css sources.
|
||||||
config :clacks, ClacksWeb.Endpoint,
|
config :clacks, ClacksWeb.Endpoint,
|
||||||
|
url: [scheme: "http", port: 4000],
|
||||||
http: [port: 4000],
|
http: [port: 4000],
|
||||||
debug_errors: true,
|
debug_errors: true,
|
||||||
code_reloader: true,
|
code_reloader: true,
|
||||||
|
|
|
@ -10,7 +10,7 @@ use Mix.Config
|
||||||
# which you should run after static files are built and
|
# which you should run after static files are built and
|
||||||
# before starting your production server.
|
# before starting your production server.
|
||||||
config :clacks, ClacksWeb.Endpoint,
|
config :clacks, ClacksWeb.Endpoint,
|
||||||
url: [host: "example.com", port: 80],
|
url: [scheme: "http", host: "example.com", port: 80],
|
||||||
cache_static_manifest: "priv/static/cache_manifest.json"
|
cache_static_manifest: "priv/static/cache_manifest.json"
|
||||||
|
|
||||||
# Do not print debug messages in production
|
# Do not print debug messages in production
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
defmodule Clacks.Activity do
|
defmodule Clacks.Activity do
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
|
||||||
@type t() :: %__MODULE__{}
|
@type t() :: %__MODULE__{}
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
defmodule Clacks.ActivityPub do
|
||||||
|
@context ["https://www.w3.org/ns/activitystreams"]
|
||||||
|
@public "https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
|
||||||
|
@spec note(
|
||||||
|
actor :: String.t(),
|
||||||
|
html :: String.t(),
|
||||||
|
context :: String.t(),
|
||||||
|
id :: String.t() | nil,
|
||||||
|
published :: DateTime.t(),
|
||||||
|
to :: [String.t()],
|
||||||
|
cc :: [String.t()]
|
||||||
|
) :: map()
|
||||||
|
def note(
|
||||||
|
actor,
|
||||||
|
html,
|
||||||
|
context,
|
||||||
|
id \\ nil,
|
||||||
|
published \\ DateTime.utc_now(),
|
||||||
|
to \\ [@public],
|
||||||
|
cc \\ []
|
||||||
|
) do
|
||||||
|
id = id || object_id(Ecto.UUID.generate())
|
||||||
|
|
||||||
|
%{
|
||||||
|
"@context" => @context,
|
||||||
|
"id" => id,
|
||||||
|
"url" => id,
|
||||||
|
"type" => "Note",
|
||||||
|
"actor" => actor,
|
||||||
|
"attributedTo" => actor,
|
||||||
|
"to" => to,
|
||||||
|
"cc" => cc,
|
||||||
|
"content" => html,
|
||||||
|
"conversation" => context,
|
||||||
|
"context" => context,
|
||||||
|
"published" => published |> DateTime.to_iso8601()
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec create(
|
||||||
|
object :: map(),
|
||||||
|
id :: String.t() | nil,
|
||||||
|
actor :: String.t() | nil,
|
||||||
|
to :: [String.t()] | nil,
|
||||||
|
cc :: [String.t()] | nil
|
||||||
|
) :: map()
|
||||||
|
def create(object, id \\ nil, actor \\ nil, to \\ nil, cc \\ nil) do
|
||||||
|
%{
|
||||||
|
"@context" => @context,
|
||||||
|
"id" => id || activity_id(Ecto.UUID.generate()),
|
||||||
|
"actor" => actor || object["actor"],
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => object,
|
||||||
|
"to" => to || object["to"],
|
||||||
|
"cc" => cc || object["cc"]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec object_id(id :: String.t()) :: String.t()
|
||||||
|
def object_id(id) do
|
||||||
|
url = Application.get_env(:clacks, ClacksWeb.Endpoint)[:url]
|
||||||
|
|
||||||
|
%URI{
|
||||||
|
scheme: url[:scheme],
|
||||||
|
host: url[:host],
|
||||||
|
port: url[:port],
|
||||||
|
path: Path.join("/objects", id)
|
||||||
|
}
|
||||||
|
|> URI.to_string()
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec activity_id(id :: String.t()) :: String.t()
|
||||||
|
def activity_id(id) do
|
||||||
|
url = Application.get_env(:clacks, ClacksWeb.Endpoint)[:url]
|
||||||
|
|
||||||
|
%URI{
|
||||||
|
scheme: url[:scheme],
|
||||||
|
host: url[:host],
|
||||||
|
port: url[:port],
|
||||||
|
path: Path.join("/activities", id)
|
||||||
|
}
|
||||||
|
|> URI.to_string()
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,5 +1,6 @@
|
||||||
defmodule Clacks.Object do
|
defmodule Clacks.Object do
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
@type t() :: %__MODULE__{}
|
@type t() :: %__MODULE__{}
|
||||||
|
|
||||||
|
@ -8,4 +9,10 @@ defmodule Clacks.Object do
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def changeset(%__MODULE__{} = schema, attrs) do
|
||||||
|
schema
|
||||||
|
|> cast(attrs, [:data])
|
||||||
|
|> validate_required([:data])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
defmodule ClacksWeb.ObjectsController do
|
||||||
|
use ClacksWeb, :controller
|
||||||
|
alias Clacks.{Repo, Object, ActivityPub}
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
def get(conn, %{"id" => id}) do
|
||||||
|
object_id = current_url(conn)
|
||||||
|
query = from(o in Object, where: fragment("?->>'id'", o.data) == ^object_id)
|
||||||
|
|
||||||
|
case Repo.one(query) do
|
||||||
|
nil ->
|
||||||
|
conn
|
||||||
|
|> put_status(404)
|
||||||
|
|
||||||
|
object ->
|
||||||
|
conn
|
||||||
|
|> put_resp_header("content-type", "application/activity+json")
|
||||||
|
|> json(object.data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -9,8 +9,8 @@ defmodule ClacksWeb.Router do
|
||||||
plug :put_secure_browser_headers
|
plug :put_secure_browser_headers
|
||||||
end
|
end
|
||||||
|
|
||||||
pipeline :api do
|
pipeline :activitypub do
|
||||||
plug :accepts, ["json"]
|
plug :accepts, ["activity+json", "html"]
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/", ClacksWeb do
|
scope "/", ClacksWeb do
|
||||||
|
@ -19,6 +19,12 @@ defmodule ClacksWeb.Router do
|
||||||
get "/", PageController, :index
|
get "/", PageController, :index
|
||||||
end
|
end
|
||||||
|
|
||||||
|
scope "/", ClacksWeb do
|
||||||
|
pipe_through :activitypub
|
||||||
|
|
||||||
|
get "/objects/:id", ObjectsController, :get
|
||||||
|
end
|
||||||
|
|
||||||
# Other scopes may use custom stacks.
|
# Other scopes may use custom stacks.
|
||||||
# scope "/api", ClacksWeb do
|
# scope "/api", ClacksWeb do
|
||||||
# pipe_through :api
|
# pipe_through :api
|
||||||
|
|
Loading…
Reference in New Issue