aboutsummaryrefslogtreecommitdiff
path: root/lib/pleroma/web
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pleroma/web')
-rw-r--r--lib/pleroma/web/admin_api/admin_api_controller.ex2
-rw-r--r--lib/pleroma/web/auth/pleroma_authenticator.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex57
-rw-r--r--lib/pleroma/web/oauth/app.ex1
-rw-r--r--lib/pleroma/web/oauth/authorization.ex39
-rw-r--r--lib/pleroma/web/oauth/oauth_controller.ex22
-rw-r--r--lib/pleroma/web/oauth/token.ex11
-rw-r--r--lib/pleroma/web/router.ex2
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api.ex29
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api_controller.ex2
10 files changed, 139 insertions, 28 deletions
diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex
index b553d96a8..e00b33aba 100644
--- a/lib/pleroma/web/admin_api/admin_api_controller.ex
+++ b/lib/pleroma/web/admin_api/admin_api_controller.ex
@@ -59,7 +59,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
bio: "."
}
- changeset = User.register_changeset(%User{}, user_data, confirmed: true)
+ changeset = User.register_changeset(%User{}, user_data, need_confirmation: false)
{:ok, user} = User.register(changeset)
conn
diff --git a/lib/pleroma/web/auth/pleroma_authenticator.ex b/lib/pleroma/web/auth/pleroma_authenticator.ex
index dd79cdcf7..c4a6fce08 100644
--- a/lib/pleroma/web/auth/pleroma_authenticator.ex
+++ b/lib/pleroma/web/auth/pleroma_authenticator.ex
@@ -74,7 +74,7 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do
password_confirmation: random_password
},
external: true,
- confirmed: true
+ need_confirmation: false
)
|> Repo.insert(),
{:ok, _} <-
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index fd595031d..defd88a44 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -39,12 +39,22 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
alias Pleroma.Web.OAuth.Authorization
alias Pleroma.Web.OAuth.Scopes
alias Pleroma.Web.OAuth.Token
+ alias Pleroma.Web.TwitterAPI.TwitterAPI
alias Pleroma.Web.ControllerHelper
import Ecto.Query
require Logger
+ plug(
+ Pleroma.Plugs.RateLimitPlug,
+ %{
+ max_requests: Config.get([:app_account_creation, :max_requests]),
+ interval: Config.get([:app_account_creation, :interval])
+ }
+ when action in [:account_register]
+ )
+
@httpoison Application.get_env(:pleroma, :httpoison)
@local_mastodon_name "Mastodon-Local"
@@ -1693,6 +1703,53 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
end
+ def account_register(
+ %{assigns: %{app: app}} = conn,
+ %{"username" => nickname, "email" => _, "password" => _, "agreement" => true} = params
+ ) do
+ params =
+ params
+ |> Map.take([
+ "email",
+ "captcha_solution",
+ "captcha_token",
+ "captcha_answer_data",
+ "token",
+ "password"
+ ])
+ |> Map.put("nickname", nickname)
+ |> Map.put("fullname", params["fullname"] || nickname)
+ |> Map.put("bio", params["bio"] || "")
+ |> Map.put("confirm", params["password"])
+
+ with {:ok, user} <- TwitterAPI.register_user(params, need_confirmation: true),
+ {:ok, token} <- Token.create_token(app, user, %{scopes: app.scopes}) do
+ json(conn, %{
+ token_type: "Bearer",
+ access_token: token.token,
+ scope: app.scopes,
+ created_at: Token.Utils.format_created_at(token)
+ })
+ else
+ {:error, errors} ->
+ conn
+ |> put_status(400)
+ |> json(Jason.encode!(errors))
+ end
+ end
+
+ def account_register(%{assigns: %{app: _app}} = conn, _params) do
+ conn
+ |> put_status(400)
+ |> json(%{error: "Missing parameters"})
+ end
+
+ def account_register(conn, _) do
+ conn
+ |> put_status(403)
+ |> json(%{error: "Invalid credentials"})
+ end
+
def conversations(%{assigns: %{user: user}} = conn, params) do
participations = Participation.for_user_with_last_activity_id(user, params)
diff --git a/lib/pleroma/web/oauth/app.ex b/lib/pleroma/web/oauth/app.ex
index bccc2ac96..ddcdb1871 100644
--- a/lib/pleroma/web/oauth/app.ex
+++ b/lib/pleroma/web/oauth/app.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.OAuth.App do
import Ecto.Changeset
@type t :: %__MODULE__{}
+
schema "apps" do
field(:client_name, :string)
field(:redirect_uris, :string)
diff --git a/lib/pleroma/web/oauth/authorization.ex b/lib/pleroma/web/oauth/authorization.ex
index ca3901cc4..b47688de1 100644
--- a/lib/pleroma/web/oauth/authorization.ex
+++ b/lib/pleroma/web/oauth/authorization.ex
@@ -14,6 +14,7 @@ defmodule Pleroma.Web.OAuth.Authorization do
import Ecto.Query
@type t :: %__MODULE__{}
+
schema "oauth_authorizations" do
field(:token, :string)
field(:scopes, {:array, :string}, default: [])
@@ -25,28 +26,45 @@ defmodule Pleroma.Web.OAuth.Authorization do
timestamps()
end
+ @spec create_authorization(App.t(), User.t() | %{}, [String.t()] | nil) ::
+ {:ok, Authorization.t()} | {:error, Changeset.t()}
def create_authorization(%App{} = app, %User{} = user, scopes \\ nil) do
- scopes = scopes || app.scopes
- token = :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false)
-
- authorization = %Authorization{
- token: token,
- used: false,
+ %{
+ scopes: scopes || app.scopes,
user_id: user.id,
- app_id: app.id,
- scopes: scopes,
- valid_until: NaiveDateTime.add(NaiveDateTime.utc_now(), 60 * 10)
+ app_id: app.id
}
+ |> create_changeset()
+ |> Repo.insert()
+ end
+
+ @spec create_changeset(map()) :: Changeset.t()
+ def create_changeset(attrs \\ %{}) do
+ %Authorization{}
+ |> cast(attrs, [:user_id, :app_id, :scopes, :valid_until])
+ |> validate_required([:app_id, :scopes])
+ |> add_token()
+ |> add_lifetime()
+ end
+
+ defp add_token(changeset) do
+ token = :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false)
+ put_change(changeset, :token, token)
+ end
- Repo.insert(authorization)
+ defp add_lifetime(changeset) do
+ put_change(changeset, :valid_until, NaiveDateTime.add(NaiveDateTime.utc_now(), 60 * 10))
end
+ @spec use_changeset(Authtorizatiton.t(), map()) :: Changeset.t()
def use_changeset(%Authorization{} = auth, params) do
auth
|> cast(params, [:used])
|> validate_required([:used])
end
+ @spec use_token(Authorization.t()) ::
+ {:ok, Authorization.t()} | {:error, Changeset.t()} | {:error, String.t()}
def use_token(%Authorization{used: false, valid_until: valid_until} = auth) do
if NaiveDateTime.diff(NaiveDateTime.utc_now(), valid_until) < 0 do
Repo.update(use_changeset(auth, %{used: true}))
@@ -57,6 +75,7 @@ defmodule Pleroma.Web.OAuth.Authorization do
def use_token(%Authorization{used: true}), do: {:error, "already used"}
+ @spec delete_user_authorizations(User.t()) :: {integer(), any()}
def delete_user_authorizations(%User{id: user_id}) do
from(
a in Pleroma.Web.OAuth.Authorization,
diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex
index 8ee0da667..862b8f8c9 100644
--- a/lib/pleroma/web/oauth/oauth_controller.ex
+++ b/lib/pleroma/web/oauth/oauth_controller.ex
@@ -218,6 +218,28 @@ defmodule Pleroma.Web.OAuth.OAuthController do
token_exchange(conn, params)
end
+ def token_exchange(conn, %{"grant_type" => "client_credentials"} = params) do
+ with %App{} = app <- get_app_from_request(conn, params),
+ {:ok, auth} <- Authorization.create_authorization(app, %User{}),
+ {:ok, token} <- Token.exchange_token(app, auth),
+ {:ok, inserted_at} <- DateTime.from_naive(token.inserted_at, "Etc/UTC") do
+ response = %{
+ token_type: "Bearer",
+ access_token: token.token,
+ refresh_token: token.refresh_token,
+ created_at: DateTime.to_unix(inserted_at),
+ expires_in: 60 * 10,
+ scope: Enum.join(token.scopes, " ")
+ }
+
+ json(conn, response)
+ else
+ _error ->
+ put_status(conn, 400)
+ |> json(%{error: "Invalid credentials"})
+ end
+ end
+
# Bad request
def token_exchange(conn, params), do: bad_request(conn, params)
diff --git a/lib/pleroma/web/oauth/token.ex b/lib/pleroma/web/oauth/token.ex
index 4e5d1d118..ef047d565 100644
--- a/lib/pleroma/web/oauth/token.ex
+++ b/lib/pleroma/web/oauth/token.ex
@@ -45,12 +45,16 @@ defmodule Pleroma.Web.OAuth.Token do
|> Repo.find_resource()
end
+ @spec exchange_token(App.t(), Authorization.t()) ::
+ {:ok, Token.t()} | {:error, Changeset.t()}
def exchange_token(app, auth) do
with {:ok, auth} <- Authorization.use_token(auth),
true <- auth.app_id == app.id do
+ user = if auth.user_id, do: User.get_cached_by_id(auth.user_id), else: %User{}
+
create_token(
app,
- User.get_cached_by_id(auth.user_id),
+ user,
%{scopes: auth.scopes}
)
end
@@ -81,12 +85,13 @@ defmodule Pleroma.Web.OAuth.Token do
|> validate_required([:valid_until])
end
+ @spec create_token(App.t(), User.t(), map()) :: {:ok, Token} | {:error, Changeset.t()}
def create_token(%App{} = app, %User{} = user, attrs \\ %{}) do
%__MODULE__{user_id: user.id, app_id: app.id}
|> cast(%{scopes: attrs[:scopes] || app.scopes}, [:scopes])
- |> validate_required([:scopes, :user_id, :app_id])
+ |> validate_required([:scopes, :app_id])
|> put_valid_until(attrs)
- |> put_token
+ |> put_token()
|> put_refresh_token(attrs)
|> Repo.insert()
end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 8b84fbbad..51146d010 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -385,6 +385,8 @@ defmodule Pleroma.Web.Router do
scope "/api/v1", Pleroma.Web.MastodonAPI do
pipe_through(:api)
+ post("/accounts", MastodonAPIController, :account_register)
+
get("/instance", MastodonAPIController, :masto_instance)
get("/instance/peers", MastodonAPIController, :peers)
post("/apps", MastodonAPIController, :create_app)
diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex
index 3a7774647..1362ef57c 100644
--- a/lib/pleroma/web/twitter_api/twitter_api.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api.ex
@@ -128,7 +128,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
end
end
- def register_user(params) do
+ def register_user(params, opts \\ []) do
token = params["token"]
params = %{
@@ -162,13 +162,22 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
# I have no idea how this error handling works
{:error, %{error: Jason.encode!(%{captcha: [error]})}}
else
- registrations_open = Pleroma.Config.get([:instance, :registrations_open])
- registration_process(registrations_open, params, token)
+ registration_process(
+ params,
+ %{
+ registrations_open: Pleroma.Config.get([:instance, :registrations_open]),
+ token: token
+ },
+ opts
+ )
end
end
- defp registration_process(registration_open, params, token)
- when registration_open == false or is_nil(registration_open) do
+ defp registration_process(params, %{registrations_open: true}, opts) do
+ create_user(params, opts)
+ end
+
+ defp registration_process(params, %{token: token}, opts) do
invite =
unless is_nil(token) do
Repo.get_by(UserInviteToken, %{token: token})
@@ -182,19 +191,15 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
invite when valid_invite? ->
UserInviteToken.update_usage!(invite)
- create_user(params)
+ create_user(params, opts)
_ ->
{:error, "Expired token"}
end
end
- defp registration_process(true, params, _token) do
- create_user(params)
- end
-
- defp create_user(params) do
- changeset = User.register_changeset(%User{}, params)
+ defp create_user(params, opts) do
+ changeset = User.register_changeset(%User{}, params, opts)
case User.register(changeset) do
{:ok, user} ->
diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
index 21e6c555a..3c5a70be9 100644
--- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
@@ -440,7 +440,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
true <- user.local,
true <- user.info.confirmation_pending,
true <- user.info.confirmation_token == token,
- info_change <- User.Info.confirmation_changeset(user.info, :confirmed),
+ info_change <- User.Info.confirmation_changeset(user.info, need_confirmation: false),
changeset <- Changeset.change(user) |> Changeset.put_embed(:info, info_change),
{:ok, _} <- User.update_and_set_cache(changeset) do
conn