@@ -335,9 +335,9 @@ defmodule Eventos.Actors do
|
||||
Register user
|
||||
"""
|
||||
def register(%{email: email, password: password, username: username}) do
|
||||
key = :public_key.generate_key({:rsa, 2048, 65537})
|
||||
key = :public_key.generate_key({:rsa, 2048, 65_537})
|
||||
entry = :public_key.pem_entry_encode(:RSAPrivateKey, key)
|
||||
pem = :public_key.pem_encode([entry]) |> String.trim_trailing()
|
||||
pem = [entry] |> :public_key.pem_encode() |> String.trim_trailing()
|
||||
|
||||
import Exgravatar
|
||||
|
||||
@@ -375,9 +375,9 @@ defmodule Eventos.Actors do
|
||||
end
|
||||
|
||||
def register_bot_account(%{name: name, summary: summary}) do
|
||||
key = :public_key.generate_key({:rsa, 2048, 65537})
|
||||
key = :public_key.generate_key({:rsa, 2048, 65_537})
|
||||
entry = :public_key.pem_entry_encode(:RSAPrivateKey, key)
|
||||
pem = :public_key.pem_encode([entry]) |> String.trim_trailing()
|
||||
pem = [entry] |> :public_key.pem_encode() |> String.trim_trailing()
|
||||
|
||||
actor = Eventos.Actors.Actor.registration_changeset(%Eventos.Actors.Actor{}, %{
|
||||
preferred_username: name,
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
defmodule Eventos.Events.Comment do
|
||||
@moduledoc """
|
||||
An actor comment (for instance on an event or on a group)
|
||||
"""
|
||||
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
|
||||
@@ -83,13 +83,13 @@ defmodule EventosWeb.ActivityPubController do
|
||||
def inbox(conn, params) do
|
||||
headers = Enum.into(conn.req_headers, %{})
|
||||
|
||||
if !String.contains?(headers["signature"] || "", params["actor"]) do
|
||||
Logger.info("Signature not from author, relayed message, fetching from source")
|
||||
ActivityPub.fetch_event_from_url(params["object"]["id"])
|
||||
else
|
||||
if String.contains?(headers["signature"] || "", params["actor"]) do
|
||||
Logger.info("Signature error")
|
||||
Logger.info("Could not validate #{params["actor"]}")
|
||||
Logger.info(inspect(conn.req_headers))
|
||||
else
|
||||
Logger.info("Signature not from author, relayed message, fetching from source")
|
||||
ActivityPub.fetch_event_from_url(params["object"]["id"])
|
||||
end
|
||||
|
||||
json(conn, "ok")
|
||||
|
||||
@@ -60,7 +60,7 @@ defmodule EventosWeb.EventController do
|
||||
end
|
||||
|
||||
def export_to_ics(conn, %{"uuid" => uuid}) do
|
||||
event = Events.get_event_full_by_uuid(uuid) |> ICalendar.export_event()
|
||||
event = uuid |> Events.get_event_full_by_uuid() |> ICalendar.export_event()
|
||||
send_resp(conn, 200, event)
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
defmodule EventosWeb.HTTPSignaturePlug do
|
||||
@moduledoc """
|
||||
# HTTPSignaturePlug
|
||||
|
||||
Plug to check HTTP Signatures on every incoming request
|
||||
"""
|
||||
|
||||
alias Eventos.Service.HTTPSignatures
|
||||
import Plug.Conn
|
||||
require Logger
|
||||
@@ -13,7 +19,9 @@ defmodule EventosWeb.HTTPSignaturePlug do
|
||||
|
||||
def call(conn, _opts) do
|
||||
user = conn.params["actor"]
|
||||
Logger.debug("Checking sig for #{user}")
|
||||
Logger.debug fn ->
|
||||
"Checking sig for #{user}"
|
||||
end
|
||||
with [signature | _] <- get_req_header(conn, "signature") do
|
||||
cond do
|
||||
signature && String.contains?(signature, user) ->
|
||||
|
||||
@@ -49,9 +49,9 @@ defmodule EventosWeb.ActivityPub.ActorView do
|
||||
end
|
||||
|
||||
def render("following.json", %{actor: actor, page: page}) do
|
||||
following = Actor.get_followings(actor)
|
||||
|
||||
collection(following, actor.following_url, page)
|
||||
actor
|
||||
|> Actor.get_followings()
|
||||
|> collection(actor.following_url, page)
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
end
|
||||
|
||||
@@ -68,9 +68,9 @@ defmodule EventosWeb.ActivityPub.ActorView do
|
||||
end
|
||||
|
||||
def render("followers.json", %{actor: actor, page: page}) do
|
||||
followers = Actor.get_followers(actor)
|
||||
|
||||
collection(followers, actor.followers_url, page)
|
||||
actor
|
||||
|> Actor.get_followers()
|
||||
|> collection(actor.followers_url, page)
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
defmodule Mix.Tasks.CreateBot do
|
||||
@moduledoc """
|
||||
Creates a bot from a source
|
||||
"""
|
||||
|
||||
use Mix.Task
|
||||
alias Eventos.Actors
|
||||
alias Eventos.Actors.Bot
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
defmodule Eventos.Service.ActivityPub do
|
||||
@moduledoc """
|
||||
# ActivityPub
|
||||
|
||||
Every ActivityPub method
|
||||
"""
|
||||
|
||||
alias Eventos.Events
|
||||
alias Eventos.Events.{Event, Category}
|
||||
alias Eventos.Service.ActivityPub.Transmogrifier
|
||||
@@ -49,8 +55,8 @@ defmodule Eventos.Service.ActivityPub do
|
||||
url,
|
||||
[Accept: "application/activity+json"],
|
||||
follow_redirect: true,
|
||||
timeout: 10000,
|
||||
recv_timeout: 20000
|
||||
timeout: 10_000,
|
||||
recv_timeout: 20_000
|
||||
),
|
||||
{:ok, data} <- Jason.decode(body),
|
||||
nil <- Events.get_event_by_url!(data["id"]),
|
||||
@@ -285,9 +291,7 @@ defmodule Eventos.Service.ActivityPub do
|
||||
case bot.type do
|
||||
"ics" ->
|
||||
{:ok, %HTTPoison.Response{body: body} = _resp} = HTTPoison.get(bot.source)
|
||||
ical_events = body
|
||||
|> ExIcal.parse()
|
||||
|> ExIcal.by_range(DateTime.utc_now(), DateTime.utc_now() |> Timex.shift(years: 1))
|
||||
ical_events = body |> ExIcal.parse() |> ExIcal.by_range(DateTime.utc_now(), DateTime.utc_now() |> Timex.shift(years: 1))
|
||||
activities = ical_events
|
||||
|> Enum.chunk_every(limit)
|
||||
|> Enum.at(page - 1)
|
||||
|
||||
@@ -201,10 +201,10 @@ defmodule Eventos.Service.ActivityPub.Transmogrifier do
|
||||
if object = Object.get_by_ap_id(id), do: {:ok, object}, else: nil
|
||||
end
|
||||
|
||||
def set_reply_to_uri(%{"inReplyTo" => inReplyTo} = object) do
|
||||
with false <- String.starts_with?(inReplyTo, "http"),
|
||||
{:ok, %{data: replied_to_object}} <- get_obj_helper(inReplyTo) do
|
||||
Map.put(object, "inReplyTo", replied_to_object["external_url"] || inReplyTo)
|
||||
def set_reply_to_uri(%{"inReplyTo" => in_reply_to} = object) do
|
||||
with false <- String.starts_with?(in_reply_to, "http"),
|
||||
{:ok, %{data: replied_to_object}} <- get_obj_helper(in_reply_to) do
|
||||
Map.put(object, "inReplyTo", replied_to_object["external_url"] || in_reply_to)
|
||||
else
|
||||
_e -> object
|
||||
end
|
||||
@@ -332,10 +332,9 @@ defmodule Eventos.Service.ActivityPub.Transmogrifier do
|
||||
# end
|
||||
#
|
||||
def add_attributed_to(object) do
|
||||
attributedTo = object["attributedTo"] || object["actor"]
|
||||
attributed_to = object["attributedTo"] || object["actor"]
|
||||
|
||||
object
|
||||
|> Map.put("attributedTo", attributedTo)
|
||||
object |> Map.put("attributedTo", attributed_to)
|
||||
end
|
||||
#
|
||||
# def prepare_attachments(object) do
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
defmodule Eventos.Service.ActivityPub.Utils do
|
||||
@moduledoc """
|
||||
# Utils
|
||||
|
||||
Various utils
|
||||
"""
|
||||
|
||||
alias Eventos.Repo
|
||||
alias Eventos.Actors
|
||||
alias Eventos.Actors.Actor
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
defmodule Eventos.Service.Federator do
|
||||
@moduledoc """
|
||||
Handle federated activities
|
||||
"""
|
||||
|
||||
use GenServer
|
||||
alias Eventos.Actors
|
||||
alias Eventos.Activity
|
||||
@@ -16,7 +20,7 @@ defmodule Eventos.Service.Federator do
|
||||
|
||||
spawn(fn ->
|
||||
# 1 minute
|
||||
Process.sleep(1000 * 60 * 1)
|
||||
Process.sleep(1000 * 60)
|
||||
end)
|
||||
|
||||
GenServer.start_link(
|
||||
@@ -101,7 +105,9 @@ defmodule Eventos.Service.Federator do
|
||||
end
|
||||
|
||||
def handle_cast(m, state) do
|
||||
IO.inspect("Unknown: #{inspect(m)}, #{inspect(state)}")
|
||||
Logger.error fn ->
|
||||
"Unknown: #{inspect(m)}, #{inspect(state)}"
|
||||
end
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
# https://tools.ietf.org/html/draft-cavage-http-signatures-08
|
||||
defmodule Eventos.Service.HTTPSignatures do
|
||||
@moduledoc """
|
||||
# HTTP Signatures
|
||||
|
||||
Generates and checks HTTP Signatures
|
||||
"""
|
||||
|
||||
alias Eventos.Actors.Actor
|
||||
alias Eventos.Service.ActivityPub
|
||||
require Logger
|
||||
import Logger
|
||||
|
||||
def split_signature(sig) do
|
||||
default = %{"headers" => "date"}
|
||||
@@ -22,8 +28,12 @@ defmodule Eventos.Service.HTTPSignatures do
|
||||
|
||||
def validate(headers, signature, public_key) do
|
||||
sigstring = build_signing_string(headers, signature["headers"])
|
||||
Logger.debug("Signature: #{signature["signature"]}")
|
||||
Logger.debug("Sigstring: #{sigstring}")
|
||||
Logger.debug fn ->
|
||||
"Signature: #{signature["signature"]}"
|
||||
end
|
||||
Logger.debug fn ->
|
||||
"Sigstring: #{sigstring}"
|
||||
end
|
||||
{:ok, sig} = Base.decode64(signature["signature"])
|
||||
:public_key.verify(sigstring, :sha256, sig, public_key)
|
||||
end
|
||||
@@ -74,14 +84,12 @@ defmodule Eventos.Service.HTTPSignatures do
|
||||
with private_key = Actor.get_keys_for_actor(actor) do
|
||||
sigstring = build_signing_string(headers, Map.keys(headers))
|
||||
|
||||
signature =
|
||||
:public_key.sign(sigstring, :sha256, private_key)
|
||||
|> Base.encode64()
|
||||
signature = sigstring |> :public_key.sign(:sha256, private_key) |> Base.encode64()
|
||||
|
||||
[
|
||||
keyId: actor.url <> "#main-key",
|
||||
algorithm: "rsa-sha256",
|
||||
headers: Map.keys(headers) |> Enum.join(" "),
|
||||
headers: headers |> Map.keys() |> Enum.join(" "),
|
||||
signature: signature
|
||||
]
|
||||
|> Enum.map(fn {k, v} -> "#{k}=\"#{v}\"" end)
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
defmodule Eventos.Service.Streamer do
|
||||
@moduledoc """
|
||||
# Streamer
|
||||
|
||||
Handles streaming activities
|
||||
"""
|
||||
|
||||
use GenServer
|
||||
require Logger
|
||||
alias Eventos.Accounts.Actor
|
||||
@@ -30,7 +36,8 @@ defmodule Eventos.Service.Streamer do
|
||||
end
|
||||
|
||||
def handle_cast(%{action: :ping}, topics) do
|
||||
Map.values(topics)
|
||||
topics
|
||||
|> Map.values()
|
||||
|> List.flatten()
|
||||
|> Enum.each(fn socket ->
|
||||
Logger.debug("Sending keepalive ping")
|
||||
@@ -51,7 +58,9 @@ defmodule Eventos.Service.Streamer do
|
||||
sockets_for_topic = sockets[topic] || []
|
||||
sockets_for_topic = Enum.uniq([socket | sockets_for_topic])
|
||||
sockets = Map.put(sockets, topic, sockets_for_topic)
|
||||
Logger.debug("Got new conn for #{topic}")
|
||||
Logger.debug fn ->
|
||||
"Got new conn for #{topic}"
|
||||
end
|
||||
{:noreply, sockets}
|
||||
end
|
||||
|
||||
@@ -60,7 +69,9 @@ defmodule Eventos.Service.Streamer do
|
||||
sockets_for_topic = sockets[topic] || []
|
||||
sockets_for_topic = List.delete(sockets_for_topic, socket)
|
||||
sockets = Map.put(sockets, topic, sockets_for_topic)
|
||||
Logger.debug("Removed conn for #{topic}")
|
||||
Logger.debug fn ->
|
||||
"Removed conn for #{topic}"
|
||||
end
|
||||
{:noreply, sockets}
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
defmodule Eventos.Service.WebFinger do
|
||||
@moduledoc """
|
||||
# WebFinger
|
||||
|
||||
Performs the WebFinger requests and responses (json only)
|
||||
"""
|
||||
|
||||
alias Eventos.Actors
|
||||
alias Eventos.Service.XmlBuilder
|
||||
@@ -59,7 +64,9 @@ defmodule Eventos.Service.WebFinger do
|
||||
{"application/activity+json", "self"} ->
|
||||
Map.put(data, "url", link["href"])
|
||||
_ ->
|
||||
Logger.debug("Unhandled type: #{inspect(link["type"])}")
|
||||
Logger.debug fn ->
|
||||
"Unhandled type: #{inspect(link["type"])}"
|
||||
end
|
||||
data
|
||||
end
|
||||
end)
|
||||
@@ -81,7 +88,7 @@ defmodule Eventos.Service.WebFinger do
|
||||
address = "http://#{domain}/.well-known/webfinger?resource=acct:#{actor}"
|
||||
|
||||
Logger.debug(inspect address)
|
||||
with {:ok, %HTTPoison.Response{} = response} <- HTTPoison.get(address, [Accept: "application/json, application/activity+json, application/jrd+json"],follow_redirect: true),
|
||||
with {:ok, %HTTPoison.Response{} = response} <- HTTPoison.get(address, [Accept: "application/json, application/activity+json, application/jrd+json"], follow_redirect: true),
|
||||
%{status_code: status_code, body: body} when status_code in 200..299 <- response do
|
||||
{:ok, doc} = Jason.decode(body)
|
||||
webfinger_from_json(doc)
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
defmodule Eventos.Service.XmlBuilder do
|
||||
@moduledoc """
|
||||
XML Builder.
|
||||
|
||||
Do we still need this ? Only for xrd ?
|
||||
"""
|
||||
|
||||
def to_xml({tag, attributes, content}) do
|
||||
open_tag = make_open_tag(tag, attributes)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user