logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git

subscription.ex (2901B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.Push.Subscription do
  5. use Ecto.Schema
  6. import Ecto.Changeset
  7. alias Pleroma.Repo
  8. alias Pleroma.User
  9. alias Pleroma.Web.OAuth.Token
  10. alias Pleroma.Web.Push.Subscription
  11. @type t :: %__MODULE__{}
  12. schema "push_subscriptions" do
  13. belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
  14. belongs_to(:token, Token)
  15. field(:endpoint, :string)
  16. field(:key_p256dh, :string)
  17. field(:key_auth, :string)
  18. field(:data, :map, default: %{})
  19. timestamps()
  20. end
  21. # credo:disable-for-next-line Credo.Check.Readability.MaxLineLength
  22. @supported_alert_types ~w[follow favourite mention reblog poll pleroma:chat_mention pleroma:emoji_reaction]a
  23. defp alerts(%{data: %{alerts: alerts}}) do
  24. alerts = Map.take(alerts, @supported_alert_types)
  25. %{"alerts" => alerts}
  26. end
  27. def enabled?(subscription, "follow_request") do
  28. enabled?(subscription, "follow")
  29. end
  30. def enabled?(subscription, alert_type) do
  31. get_in(subscription.data, ["alerts", alert_type])
  32. end
  33. def create(
  34. %User{} = user,
  35. %Token{} = token,
  36. %{
  37. subscription: %{
  38. endpoint: endpoint,
  39. keys: %{auth: key_auth, p256dh: key_p256dh}
  40. }
  41. } = params
  42. ) do
  43. Repo.insert(%Subscription{
  44. user_id: user.id,
  45. token_id: token.id,
  46. endpoint: endpoint,
  47. key_auth: ensure_base64_urlsafe(key_auth),
  48. key_p256dh: ensure_base64_urlsafe(key_p256dh),
  49. data: alerts(params)
  50. })
  51. end
  52. @doc "Gets subsciption by user & token"
  53. @spec get(User.t(), Token.t()) :: {:ok, t()} | {:error, :not_found}
  54. def get(%User{id: user_id}, %Token{id: token_id}) do
  55. case Repo.get_by(Subscription, user_id: user_id, token_id: token_id) do
  56. nil -> {:error, :not_found}
  57. subscription -> {:ok, subscription}
  58. end
  59. end
  60. def update(user, token, params) do
  61. with {:ok, subscription} <- get(user, token) do
  62. subscription
  63. |> change(data: alerts(params))
  64. |> Repo.update()
  65. end
  66. end
  67. def delete(user, token) do
  68. with {:ok, subscription} <- get(user, token),
  69. do: Repo.delete(subscription)
  70. end
  71. def delete_if_exists(user, token) do
  72. case get(user, token) do
  73. {:error, _} -> {:ok, nil}
  74. {:ok, sub} -> Repo.delete(sub)
  75. end
  76. end
  77. # Some webpush clients (e.g. iOS Toot!) use an non urlsafe base64 as an encoding for the key.
  78. # However, the web push rfs specify to use base64 urlsafe, and the `web_push_encryption` library
  79. # we use requires the key to be properly encoded. So we just convert base64 to urlsafe base64.
  80. defp ensure_base64_urlsafe(string) do
  81. string
  82. |> String.replace("+", "-")
  83. |> String.replace("/", "_")
  84. |> String.replace("=", "")
  85. end
  86. end