logo

pleroma

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

token.ex (2772B)


  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.new(
  45. %{
  46. token_id: token.id,
  47. mod: __MODULE__
  48. },
  49. scheduled_at: DateTime.from_naive!(token.valid_until, "Etc/UTC")
  50. )
  51. |> Oban.insert()
  52. {:ok, token}
  53. end
  54. end
  55. defp do_create(user, authorization) do
  56. %__MODULE__{}
  57. |> change()
  58. |> assign_user(user)
  59. |> maybe_assign_authorization(authorization)
  60. |> put_token()
  61. |> put_valid_until()
  62. |> Repo.insert()
  63. end
  64. defp assign_user(changeset, user) do
  65. changeset
  66. |> put_assoc(:user, user)
  67. |> validate_required([:user])
  68. end
  69. defp maybe_assign_authorization(changeset, %Authorization{} = authorization) do
  70. changeset
  71. |> put_assoc(:authorization, authorization)
  72. |> validate_required([:authorization])
  73. end
  74. defp maybe_assign_authorization(changeset, _), do: changeset
  75. defp put_token(changeset) do
  76. token = Pleroma.Web.OAuth.Token.Utils.generate_token()
  77. changeset
  78. |> change(%{token: token})
  79. |> validate_required([:token])
  80. |> unique_constraint(:token)
  81. end
  82. defp put_valid_until(changeset) do
  83. expires_in = NaiveDateTime.add(NaiveDateTime.utc_now(), @expires)
  84. changeset
  85. |> change(%{valid_until: expires_in})
  86. |> validate_required([:valid_until])
  87. end
  88. end