Allow user to register with custom language
[akkoma] / lib / pleroma / web / twitter_api / twitter_api.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
6 import Pleroma.Web.Gettext
7
8 alias Pleroma.Emails.Mailer
9 alias Pleroma.Emails.UserEmail
10 alias Pleroma.Repo
11 alias Pleroma.User
12 alias Pleroma.UserInviteToken
13
14 def register_user(params, opts \\ []) do
15 fallback_language = Gettext.get_locale()
16
17 params =
18 params
19 |> Map.take([:email, :token, :password])
20 |> Map.put(:bio, params |> Map.get(:bio, "") |> User.parse_bio())
21 |> Map.put(:nickname, params[:username])
22 |> Map.put(:name, Map.get(params, :fullname, params[:username]))
23 |> Map.put(:password_confirmation, params[:password])
24 |> Map.put(:registration_reason, params[:reason])
25 |> Map.put(
26 :language,
27 Pleroma.Web.Gettext.normalize_locale(params[:language]) || fallback_language
28 )
29
30 if Pleroma.Config.get([:instance, :registrations_open]) do
31 create_user(params, opts)
32 else
33 create_user_with_invite(params, opts)
34 end
35 end
36
37 defp create_user_with_invite(params, opts) do
38 with %{token: token} when is_binary(token) <- params,
39 %UserInviteToken{} = invite <- Repo.get_by(UserInviteToken, %{token: token}),
40 true <- UserInviteToken.valid_invite?(invite) do
41 UserInviteToken.update_usage!(invite)
42 create_user(params, opts)
43 else
44 nil -> {:error, "Invalid token"}
45 _ -> {:error, "Expired token"}
46 end
47 end
48
49 defp create_user(params, opts) do
50 changeset = User.register_changeset(%User{}, params, opts)
51
52 case User.register(changeset) do
53 {:ok, user} ->
54 {:ok, user}
55
56 {:error, changeset} ->
57 errors =
58 changeset
59 |> Ecto.Changeset.traverse_errors(fn {msg, _opts} -> msg end)
60 |> Jason.encode!()
61
62 {:error, errors}
63 end
64 end
65
66 def password_reset(nickname_or_email) do
67 with true <- is_binary(nickname_or_email),
68 %User{local: true, email: email, is_active: true} = user when is_binary(email) <-
69 User.get_by_nickname_or_email(nickname_or_email),
70 {:ok, token_record} <- Pleroma.PasswordResetToken.create_token(user) do
71 user
72 |> UserEmail.password_reset_email(token_record.token)
73 |> Mailer.deliver_async()
74
75 {:ok, :enqueued}
76 else
77 _ ->
78 {:ok, :noop}
79 end
80 end
81
82 def validate_captcha(app, params) do
83 if app.trusted || not Pleroma.Captcha.enabled?() do
84 :ok
85 else
86 do_validate_captcha(params)
87 end
88 end
89
90 defp do_validate_captcha(params) do
91 with :ok <- validate_captcha_presence(params),
92 :ok <-
93 Pleroma.Captcha.validate(
94 params[:captcha_token],
95 params[:captcha_solution],
96 params[:captcha_answer_data]
97 ) do
98 :ok
99 else
100 {:error, :captcha_error} ->
101 captcha_error(dgettext("errors", "CAPTCHA Error"))
102
103 {:error, :invalid} ->
104 captcha_error(dgettext("errors", "Invalid CAPTCHA"))
105
106 {:error, :kocaptcha_service_unavailable} ->
107 captcha_error(dgettext("errors", "Kocaptcha service unavailable"))
108
109 {:error, :expired} ->
110 captcha_error(dgettext("errors", "CAPTCHA expired"))
111
112 {:error, :already_used} ->
113 captcha_error(dgettext("errors", "CAPTCHA already used"))
114
115 {:error, :invalid_answer_data} ->
116 captcha_error(dgettext("errors", "Invalid answer data"))
117
118 {:error, error} ->
119 captcha_error(error)
120 end
121 end
122
123 defp validate_captcha_presence(params) do
124 [:captcha_solution, :captcha_token, :captcha_answer_data]
125 |> Enum.find_value(:ok, fn key ->
126 unless is_binary(params[key]) do
127 error = dgettext("errors", "Invalid CAPTCHA (Missing parameter: %{name})", name: key)
128 {:error, error}
129 end
130 end)
131 end
132
133 # For some reason FE expects error message to be a serialized JSON
134 defp captcha_error(error), do: {:error, Jason.encode!(%{captcha: [error]})}
135 end