logo

pleroma

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

two_factor_authentication_controller.ex (3720B)


  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.PleromaAPI.TwoFactorAuthenticationController do
  5. @moduledoc "The module represents actions to manage MFA"
  6. use Pleroma.Web, :controller
  7. import Pleroma.Web.ControllerHelper, only: [json_response: 3]
  8. alias Pleroma.MFA
  9. alias Pleroma.MFA.TOTP
  10. alias Pleroma.Web.CommonAPI.Utils
  11. alias Pleroma.Web.Plugs.OAuthScopesPlug
  12. plug(OAuthScopesPlug, %{scopes: ["read:security"]} when action in [:settings])
  13. plug(
  14. OAuthScopesPlug,
  15. %{scopes: ["write:security"]} when action in [:setup, :confirm, :disable, :backup_codes]
  16. )
  17. @doc """
  18. Gets user multi factor authentication settings
  19. ## Endpoint
  20. GET /api/pleroma/accounts/mfa
  21. """
  22. def settings(%{assigns: %{user: user}} = conn, _params) do
  23. json(conn, %{settings: MFA.mfa_settings(user)})
  24. end
  25. @doc """
  26. Prepare setup mfa method
  27. ## Endpoint
  28. GET /api/pleroma/accounts/mfa/setup/[:method]
  29. """
  30. def setup(%{assigns: %{user: user}} = conn, %{"method" => "totp"} = _params) do
  31. with {:ok, user} <- MFA.setup_totp(user),
  32. %{secret: secret} = _ <- user.multi_factor_authentication_settings.totp do
  33. provisioning_uri = TOTP.provisioning_uri(secret, "#{user.email}")
  34. json(conn, %{provisioning_uri: provisioning_uri, key: secret})
  35. else
  36. {:error, message} ->
  37. json_response(conn, :unprocessable_entity, %{error: message})
  38. end
  39. end
  40. def setup(conn, _params) do
  41. json_response(conn, :bad_request, %{error: "undefined method"})
  42. end
  43. @doc """
  44. Confirms setup and enable mfa method
  45. ## Endpoint
  46. POST /api/pleroma/accounts/mfa/confirm/:method
  47. - params:
  48. `code` - confirmation code
  49. `password` - current password
  50. """
  51. def confirm(
  52. %{assigns: %{user: user}} = conn,
  53. %{"method" => "totp", "password" => _, "code" => _} = params
  54. ) do
  55. with {:ok, _user} <- Utils.confirm_current_password(user, params["password"]),
  56. {:ok, _user} <- MFA.confirm_totp(user, params) do
  57. json(conn, %{})
  58. else
  59. {:error, message} ->
  60. json_response(conn, :unprocessable_entity, %{error: message})
  61. end
  62. end
  63. def confirm(conn, _) do
  64. json_response(conn, :bad_request, %{error: "undefined mfa method"})
  65. end
  66. @doc """
  67. Disable mfa method and disable mfa if need.
  68. """
  69. def disable(%{assigns: %{user: user}} = conn, %{"method" => "totp"} = params) do
  70. with {:ok, user} <- Utils.confirm_current_password(user, params["password"]),
  71. {:ok, _user} <- MFA.disable_totp(user) do
  72. json(conn, %{})
  73. else
  74. {:error, message} ->
  75. json_response(conn, :unprocessable_entity, %{error: message})
  76. end
  77. end
  78. def disable(%{assigns: %{user: user}} = conn, %{"method" => "mfa"} = params) do
  79. with {:ok, user} <- Utils.confirm_current_password(user, params["password"]),
  80. {:ok, _user} <- MFA.disable(user) do
  81. json(conn, %{})
  82. else
  83. {:error, message} ->
  84. json_response(conn, :unprocessable_entity, %{error: message})
  85. end
  86. end
  87. def disable(conn, _) do
  88. json_response(conn, :bad_request, %{error: "undefined mfa method"})
  89. end
  90. @doc """
  91. Generates backup codes.
  92. ## Endpoint
  93. GET /api/pleroma/accounts/mfa/backup_codes
  94. ## Response
  95. ### Success
  96. `{codes: [codes]}`
  97. ### Error
  98. `{error: [error_message]}`
  99. """
  100. def backup_codes(%{assigns: %{user: user}} = conn, _params) do
  101. with {:ok, codes} <- MFA.generate_backup_codes(user) do
  102. json(conn, %{codes: codes})
  103. else
  104. {:error, message} ->
  105. json_response(conn, :unprocessable_entity, %{error: message})
  106. end
  107. end
  108. end