logo

pleroma

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

token.ex (2730B)


  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.MFA.Token do
  5. use Ecto.Schema
  6. import Ecto.Query
  7. import Ecto.Changeset
  8. alias Pleroma.Repo
  9. alias Pleroma.User
  10. alias Pleroma.Web.OAuth.Authorization
  11. @expires 300
  12. @type t() :: %__MODULE__{}
  13. schema "mfa_tokens" do
  14. field(:token, :string)
  15. field(:valid_until, :naive_datetime_usec)
  16. belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
  17. belongs_to(:authorization, Authorization)
  18. timestamps()
  19. end
  20. @spec get_by_token(String.t()) :: {:ok, t()} | {:error, :not_found}
  21. def get_by_token(token) do
  22. from(
  23. t in __MODULE__,
  24. where: t.token == ^token,
  25. preload: [:user, :authorization]
  26. )
  27. |> Repo.find_resource()
  28. end
  29. @spec validate(String.t()) :: {:ok, t()} | {:error, :not_found} | {:error, :expired_token}
  30. def validate(token_str) do
  31. with {:ok, token} <- get_by_token(token_str),
  32. false <- expired?(token) do
  33. {:ok, token}
  34. end
  35. end
  36. defp expired?(%__MODULE__{valid_until: valid_until}) do
  37. with true <- NaiveDateTime.diff(NaiveDateTime.utc_now(), valid_until) > 0 do
  38. {:error, :expired_token}
  39. end
  40. end
  41. @spec create(User.t(), Authorization.t() | nil) :: {:ok, t()} | {:error, Ecto.Changeset.t()}
  42. def create(user, authorization \\ nil) do
  43. with {:ok, token} <- do_create(user, authorization) do
  44. Pleroma.Workers.PurgeExpiredToken.enqueue(%{
  45. token_id: token.id,
  46. valid_until: DateTime.from_naive!(token.valid_until, "Etc/UTC"),
  47. mod: __MODULE__
  48. })
  49. {:ok, token}
  50. end
  51. end
  52. defp do_create(user, authorization) do
  53. %__MODULE__{}
  54. |> change()
  55. |> assign_user(user)
  56. |> maybe_assign_authorization(authorization)
  57. |> put_token()
  58. |> put_valid_until()
  59. |> Repo.insert()
  60. end
  61. defp assign_user(changeset, user) do
  62. changeset
  63. |> put_assoc(:user, user)
  64. |> validate_required([:user])
  65. end
  66. defp maybe_assign_authorization(changeset, %Authorization{} = authorization) do
  67. changeset
  68. |> put_assoc(:authorization, authorization)
  69. |> validate_required([:authorization])
  70. end
  71. defp maybe_assign_authorization(changeset, _), do: changeset
  72. defp put_token(changeset) do
  73. token = Pleroma.Web.OAuth.Token.Utils.generate_token()
  74. changeset
  75. |> change(%{token: token})
  76. |> validate_required([:token])
  77. |> unique_constraint(:token)
  78. end
  79. defp put_valid_until(changeset) do
  80. expires_in = NaiveDateTime.add(NaiveDateTime.utc_now(), @expires)
  81. changeset
  82. |> change(%{valid_until: expires_in})
  83. |> validate_required([:valid_until])
  84. end
  85. end