Introduce support for 3rd-party auth (OAuth2 & LDAP)
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -40,14 +40,18 @@ defmodule Mobilizon.Users.User do
|
||||
:confirmation_token,
|
||||
:reset_password_sent_at,
|
||||
:reset_password_token,
|
||||
:default_actor_id,
|
||||
:locale,
|
||||
:unconfirmed_email,
|
||||
:disabled
|
||||
:disabled,
|
||||
:provider
|
||||
]
|
||||
@attrs @required_attrs ++ @optional_attrs
|
||||
|
||||
@registration_required_attrs @required_attrs ++ [:password]
|
||||
|
||||
@auth_provider_required_attrs @required_attrs ++ [:provider]
|
||||
|
||||
@password_change_required_attrs [:password]
|
||||
@password_reset_required_attrs @password_change_required_attrs ++
|
||||
[:reset_password_token, :reset_password_sent_at]
|
||||
@@ -67,6 +71,7 @@ defmodule Mobilizon.Users.User do
|
||||
field(:unconfirmed_email, :string)
|
||||
field(:locale, :string, default: "en")
|
||||
field(:disabled, :boolean, default: false)
|
||||
field(:provider, :string)
|
||||
|
||||
belongs_to(:default_actor, Actor)
|
||||
has_many(:actors, Actor)
|
||||
@@ -116,6 +121,16 @@ defmodule Mobilizon.Users.User do
|
||||
)
|
||||
end
|
||||
|
||||
@doc false
|
||||
@spec auth_provider_changeset(t, map) :: Ecto.Changeset.t()
|
||||
def auth_provider_changeset(%__MODULE__{} = user, attrs) do
|
||||
user
|
||||
|> changeset(attrs)
|
||||
|> cast_assoc(:default_actor)
|
||||
|> put_change(:confirmed_at, DateTime.utc_now() |> DateTime.truncate(:second))
|
||||
|> validate_required(@auth_provider_required_attrs)
|
||||
end
|
||||
|
||||
@doc false
|
||||
@spec send_password_reset_changeset(t, map) :: Ecto.Changeset.t()
|
||||
def send_password_reset_changeset(%__MODULE__{} = user, attrs) do
|
||||
|
||||
@@ -15,13 +15,6 @@ defmodule Mobilizon.Users do
|
||||
alias Mobilizon.Storage.{Page, Repo}
|
||||
alias Mobilizon.Users.{Setting, User}
|
||||
|
||||
alias Mobilizon.Web.Auth
|
||||
|
||||
@type tokens :: %{
|
||||
required(:access_token) => String.t(),
|
||||
required(:refresh_token) => String.t()
|
||||
}
|
||||
|
||||
defenum(UserRole, :user_role, [:administrator, :moderator, :user])
|
||||
|
||||
defenum(NotificationPendingNotificationDelay, none: 0, direct: 1, one_hour: 5, one_day: 10)
|
||||
@@ -41,6 +34,18 @@ defmodule Mobilizon.Users do
|
||||
end
|
||||
end
|
||||
|
||||
@spec create_external(String.t(), String.t()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
|
||||
def create_external(email, provider) do
|
||||
with {:ok, %User{} = user} <-
|
||||
%User{}
|
||||
|> User.auth_provider_changeset(%{email: email, provider: provider})
|
||||
|> Repo.insert() do
|
||||
Events.create_feed_token(%{user_id: user.id})
|
||||
|
||||
{:ok, user}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single user.
|
||||
Raises `Ecto.NoResultsError` if the user does not exist.
|
||||
@@ -75,6 +80,16 @@ defmodule Mobilizon.Users do
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets an user by its email.
|
||||
"""
|
||||
@spec get_user_by_email!(String.t(), boolean | nil) :: User.t()
|
||||
def get_user_by_email!(email, activated \\ nil) do
|
||||
email
|
||||
|> user_by_email_query(activated)
|
||||
|> Repo.one!()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Get an user by its activation token.
|
||||
"""
|
||||
@@ -267,52 +282,6 @@ defmodule Mobilizon.Users do
|
||||
@spec count_users :: integer
|
||||
def count_users, do: Repo.one(from(u in User, select: count(u.id)))
|
||||
|
||||
@doc """
|
||||
Authenticate an user.
|
||||
"""
|
||||
@spec authenticate(User.t()) :: {:ok, tokens} | {:error, :unauthorized}
|
||||
def authenticate(%{user: %User{password_hash: password_hash} = user, password: password}) do
|
||||
# Does password match the one stored in the database?
|
||||
if Argon2.verify_pass(password, password_hash) do
|
||||
{:ok, _tokens} = generate_tokens(user)
|
||||
else
|
||||
{:error, :unauthorized}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generates access token and refresh token for an user.
|
||||
"""
|
||||
@spec generate_tokens(User.t()) :: {:ok, tokens}
|
||||
def generate_tokens(user) do
|
||||
with {:ok, access_token} <- generate_access_token(user),
|
||||
{:ok, refresh_token} <- generate_refresh_token(user) do
|
||||
{:ok, %{access_token: access_token, refresh_token: refresh_token}}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generates access token for an user.
|
||||
"""
|
||||
@spec generate_access_token(User.t()) :: {:ok, String.t()}
|
||||
def generate_access_token(user) do
|
||||
with {:ok, access_token, _claims} <-
|
||||
Auth.Guardian.encode_and_sign(user, %{}, token_type: "access") do
|
||||
{:ok, access_token}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generates refresh token for an user.
|
||||
"""
|
||||
@spec generate_refresh_token(User.t()) :: {:ok, String.t()}
|
||||
def generate_refresh_token(user) do
|
||||
with {:ok, refresh_token, _claims} <-
|
||||
Auth.Guardian.encode_and_sign(user, %{}, token_type: "refresh") do
|
||||
{:ok, refresh_token}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a settings for an user.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user