From d94ee5cd50005a947c3c3a734b086fd5cd266c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20K=C3=BChl?= Date: Tue, 18 Sep 2018 11:56:46 +0200 Subject: [PATCH] Mastodon API: Support push subscription CRUD --- .../mastodon_api/mastodon_api_controller.ex | 27 ++++++++ .../views/push_subscription_view.ex | 14 ++++ lib/pleroma/web/push/subscription.ex | 66 +++++++++++++++++++ lib/pleroma/web/router.ex | 5 ++ ...180918182427_create_push_subscriptions.exs | 18 +++++ 5 files changed, 130 insertions(+) create mode 100644 lib/pleroma/web/mastodon_api/views/push_subscription_view.ex create mode 100644 lib/pleroma/web/push/subscription.ex create mode 100644 priv/repo/migrations/20180918182427_create_push_subscriptions.exs diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 391a79885..7f06ee607 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -1138,6 +1138,33 @@ def delete_filter(%{assigns: %{user: user}} = conn, %{"id" => filter_id}) do json(conn, %{}) end + def create_push_subscription(%{assigns: %{user: user, token: token}} = conn, params) do + Pleroma.Web.Push.Subscription.delete_if_exists(user, token) + {:ok, subscription} = Pleroma.Web.Push.Subscription.create(user, token, params) + view = PushSubscriptionView.render("push_subscription.json", subscription: subscription) + json(conn, view) + end + + def get_push_subscription(%{assigns: %{user: user, token: token}} = conn, params) do + subscription = Pleroma.Web.Push.Subscription.get(user, token) + view = PushSubscriptionView.render("push_subscription.json", subscription: subscription) + json(conn, view) + end + + def update_push_subscription( + %{assigns: %{user: user, token: token}} = conn, + params + ) do + {:ok, subscription} = Pleroma.Web.Push.Subscription.update(user, token, params) + view = PushSubscriptionView.render("push_subscription.json", subscription: subscription) + json(conn, view) + end + + def delete_push_subscription(%{assigns: %{user: user, token: token}} = conn, params) do + {:ok, _response} = Pleroma.Web.Push.Subscription.delete(user, token) + json(conn, %{}) + end + def errors(conn, _) do conn |> put_status(500) diff --git a/lib/pleroma/web/mastodon_api/views/push_subscription_view.ex b/lib/pleroma/web/mastodon_api/views/push_subscription_view.ex new file mode 100644 index 000000000..a910bb43e --- /dev/null +++ b/lib/pleroma/web/mastodon_api/views/push_subscription_view.ex @@ -0,0 +1,14 @@ +defmodule Pleroma.Web.MastodonAPI.PushSubscriptionView do + use Pleroma.Web, :view + alias Pleroma.Web.MastodonAPI.PushSubscriptionView + + def render("push_subscription.json", %{subscription: subscription}) do + %{ + id: to_string(subscription.id), + endpoint: subscription.endpoint, + alerts: Map.get(subscription.data, "alerts"), + # TODO: generate VAPID server key + server_key: "N/A" + } + end +end diff --git a/lib/pleroma/web/push/subscription.ex b/lib/pleroma/web/push/subscription.ex new file mode 100644 index 000000000..dc8fe9f33 --- /dev/null +++ b/lib/pleroma/web/push/subscription.ex @@ -0,0 +1,66 @@ +defmodule Pleroma.Web.Push.Subscription do + use Ecto.Schema + import Ecto.{Changeset, Query} + alias Pleroma.{Repo, User} + alias Pleroma.Web.OAuth.Token + alias Pleroma.Web.Push.Subscription + + schema "push_subscriptions" do + belongs_to(:user, User) + belongs_to(:token, Token) + field(:endpoint, :string) + field(:key_p256dh, :string) + field(:key_auth, :string) + field(:data, :map, default: %{}) + + timestamps() + end + + @supported_alert_types ~w[follow favourite mention reblog] + + defp alerts(%{"data" => %{"alerts" => alerts}}) do + alerts = Map.take(alerts, @supported_alert_types) + %{"alerts" => alerts} + end + + def create( + %User{} = user, + %Token{} = token, + %{ + "subscription" => %{ + "endpoint" => endpoint, + "keys" => %{"auth" => key_auth, "p256dh" => key_p256dh} + } + } = params + ) do + Repo.insert(%Subscription{ + user_id: user.id, + token_id: token.id, + endpoint: endpoint, + key_auth: key_auth, + key_p256dh: key_p256dh, + data: alerts(params) + }) + end + + def get(%User{id: user_id}, %Token{id: token_id}) do + Repo.get_by(Subscription, user_id: user_id, token_id: token_id) + end + + def update(user, token, params) do + get(user, token) + |> change(data: alerts(params)) + |> Repo.update() + end + + def delete(user, token) do + Repo.delete(get(user, token)) + end + + def delete_if_exists(user, token) do + case get(user, token) do + nil -> {:ok, nil} + sub -> Repo.delete(sub) + end + end +end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index ddfaa8c42..04dc80444 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -171,6 +171,11 @@ defmodule Pleroma.Web.Router do put("/filters/:id", MastodonAPIController, :update_filter) delete("/filters/:id", MastodonAPIController, :delete_filter) + post("/push/subscription", MastodonAPIController, :create_push_subscription) + get("/push/subscription", MastodonAPIController, :get_push_subscription) + put("/push/subscription", MastodonAPIController, :update_push_subscription) + delete("/push/subscription", MastodonAPIController, :delete_push_subscription) + get("/suggestions", MastodonAPIController, :suggestions) get("/endorsements", MastodonAPIController, :empty_array) diff --git a/priv/repo/migrations/20180918182427_create_push_subscriptions.exs b/priv/repo/migrations/20180918182427_create_push_subscriptions.exs new file mode 100644 index 000000000..0cc7afa54 --- /dev/null +++ b/priv/repo/migrations/20180918182427_create_push_subscriptions.exs @@ -0,0 +1,18 @@ +defmodule Pleroma.Repo.Migrations.CreatePushSubscriptions do + use Ecto.Migration + + def change do + create table("push_subscriptions") do + add :user_id, references("users", on_delete: :delete_all) + add :token_id, references("oauth_tokens", on_delete: :delete_all) + add :endpoint, :string + add :key_p256dh, :string + add :key_auth, :string + add :data, :map + + timestamps() + end + + create index("push_subscriptions", [:user_id, :token_id], unique: true) + end +end