Add login information to user
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
37d5b9ea45
commit
45fa3e8ad0
|
@ -60,13 +60,17 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||||
@doc """
|
@doc """
|
||||||
Login an user. Returns a token and the user
|
Login an user. Returns a token and the user
|
||||||
"""
|
"""
|
||||||
def login_user(_parent, %{email: email, password: password}, _resolution) do
|
def login_user(_parent, %{email: email, password: password}, %{context: context}) do
|
||||||
case Authenticator.authenticate(email, password) do
|
with {:ok,
|
||||||
{:ok,
|
%{
|
||||||
%{access_token: _access_token, refresh_token: _refresh_token, user: _user} =
|
access_token: _access_token,
|
||||||
user_and_tokens} ->
|
refresh_token: _refresh_token,
|
||||||
{:ok, user_and_tokens}
|
user: %User{} = user
|
||||||
|
} = user_and_tokens} <- Authenticator.authenticate(email, password),
|
||||||
|
{:ok, %User{} = user} <- update_user_login_information(user, context),
|
||||||
|
user_and_tokens <- Map.put(user_and_tokens, :user, user) do
|
||||||
|
{:ok, user_and_tokens}
|
||||||
|
else
|
||||||
{:error, :user_not_found} ->
|
{:error, :user_not_found} ->
|
||||||
{:error, "No user with this email was found"}
|
{:error, "No user with this email was found"}
|
||||||
|
|
||||||
|
@ -81,11 +85,12 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||||
@doc """
|
@doc """
|
||||||
Refresh a token
|
Refresh a token
|
||||||
"""
|
"""
|
||||||
def refresh_token(_parent, %{refresh_token: refresh_token}, _context) do
|
def refresh_token(_parent, %{refresh_token: refresh_token}, context) do
|
||||||
with {:ok, user, _claims} <- Auth.Guardian.resource_from_token(refresh_token),
|
with {:ok, user, _claims} <- Auth.Guardian.resource_from_token(refresh_token),
|
||||||
{:ok, _old, {exchanged_token, _claims}} <-
|
{:ok, _old, {exchanged_token, _claims}} <-
|
||||||
Auth.Guardian.exchange(refresh_token, ["access", "refresh"], "access"),
|
Auth.Guardian.exchange(refresh_token, ["access", "refresh"], "access"),
|
||||||
{:ok, refresh_token} <- Authenticator.generate_refresh_token(user) do
|
{:ok, refresh_token} <- Authenticator.generate_refresh_token(user),
|
||||||
|
{:ok, %User{}} <- update_user_login_information(user, context) do
|
||||||
{:ok, %{access_token: exchanged_token, refresh_token: refresh_token}}
|
{:ok, %{access_token: exchanged_token, refresh_token: refresh_token}}
|
||||||
else
|
else
|
||||||
{:error, message} ->
|
{:error, message} ->
|
||||||
|
@ -513,4 +518,22 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||||
{:ok, user}
|
{:ok, user}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec update_user_login_information(User.t(), map()) ::
|
||||||
|
{:ok, User.t()} | {:error, Ecto.Changeset.t()}
|
||||||
|
defp update_user_login_information(
|
||||||
|
%User{current_sign_in_at: current_sign_in_at, current_sign_in_ip: current_sign_in_ip} =
|
||||||
|
user,
|
||||||
|
context
|
||||||
|
) do
|
||||||
|
with current_ip <- Map.get(context, :ip),
|
||||||
|
now <- DateTime.utc_now() do
|
||||||
|
Users.update_user(user, %{
|
||||||
|
last_sign_in_at: current_sign_in_at || now,
|
||||||
|
last_sign_in_ip: current_sign_in_ip || current_ip,
|
||||||
|
current_sign_in_ip: current_ip,
|
||||||
|
current_sign_in_at: now
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -27,7 +27,11 @@ defmodule Mobilizon.Users.User do
|
||||||
default_actor: Actor.t(),
|
default_actor: Actor.t(),
|
||||||
disabled: boolean(),
|
disabled: boolean(),
|
||||||
actors: [Actor.t()],
|
actors: [Actor.t()],
|
||||||
feed_tokens: [FeedToken.t()]
|
feed_tokens: [FeedToken.t()],
|
||||||
|
last_sign_in_at: DateTime.t(),
|
||||||
|
last_sign_in_ip: String.t(),
|
||||||
|
current_sign_in_ip: String.t(),
|
||||||
|
current_sign_in_at: DateTime.t()
|
||||||
}
|
}
|
||||||
|
|
||||||
@required_attrs [:email]
|
@required_attrs [:email]
|
||||||
|
@ -44,7 +48,11 @@ defmodule Mobilizon.Users.User do
|
||||||
:locale,
|
:locale,
|
||||||
:unconfirmed_email,
|
:unconfirmed_email,
|
||||||
:disabled,
|
:disabled,
|
||||||
:provider
|
:provider,
|
||||||
|
:last_sign_in_at,
|
||||||
|
:last_sign_in_ip,
|
||||||
|
:current_sign_in_ip,
|
||||||
|
:current_sign_in_at
|
||||||
]
|
]
|
||||||
@attrs @required_attrs ++ @optional_attrs
|
@attrs @required_attrs ++ @optional_attrs
|
||||||
|
|
||||||
|
@ -72,6 +80,10 @@ defmodule Mobilizon.Users.User do
|
||||||
field(:locale, :string, default: "en")
|
field(:locale, :string, default: "en")
|
||||||
field(:disabled, :boolean, default: false)
|
field(:disabled, :boolean, default: false)
|
||||||
field(:provider, :string)
|
field(:provider, :string)
|
||||||
|
field(:last_sign_in_at, :utc_datetime)
|
||||||
|
field(:last_sign_in_ip, :string)
|
||||||
|
field(:current_sign_in_ip, :string)
|
||||||
|
field(:current_sign_in_at, :utc_datetime)
|
||||||
|
|
||||||
belongs_to(:default_actor, Actor)
|
belongs_to(:default_actor, Actor)
|
||||||
has_many(:actors, Actor)
|
has_many(:actors, Actor)
|
||||||
|
|
|
@ -15,10 +15,10 @@ defmodule Mobilizon.Web.Auth.Context do
|
||||||
def call(%{assigns: %{ip: _}} = conn, _opts), do: conn
|
def call(%{assigns: %{ip: _}} = conn, _opts), do: conn
|
||||||
|
|
||||||
def call(conn, _opts) do
|
def call(conn, _opts) do
|
||||||
set_user_and_ip_in_context(conn)
|
set_user_information_in_context(conn)
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_user_and_ip_in_context(conn) do
|
def set_user_information_in_context(conn) do
|
||||||
context = %{ip: conn.remote_ip |> :inet.ntoa() |> to_string()}
|
context = %{ip: conn.remote_ip |> :inet.ntoa() |> to_string()}
|
||||||
|
|
||||||
context =
|
context =
|
||||||
|
@ -30,6 +30,15 @@ defmodule Mobilizon.Web.Auth.Context do
|
||||||
context
|
context
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context =
|
||||||
|
case get_req_header(conn, "user-agent") do
|
||||||
|
[user_agent | _] ->
|
||||||
|
Map.put(context, :user_agent, user_agent)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
context
|
||||||
|
end
|
||||||
|
|
||||||
put_private(conn, :absinthe, %{context: context})
|
put_private(conn, :absinthe, %{context: context})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -44,8 +44,6 @@ defmodule Mobilizon.Web.Auth.Guardian do
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_encode_and_sign(resource, claims, token, _options) do
|
def after_encode_and_sign(resource, claims, token, _options) do
|
||||||
Logger.debug(fn -> "after_encode_and_sign #{inspect(claims)}" end)
|
|
||||||
|
|
||||||
with {:ok, _} <- Guardian.DB.after_encode_and_sign(resource, claims["typ"], claims, token) do
|
with {:ok, _} <- Guardian.DB.after_encode_and_sign(resource, claims["typ"], claims, token) do
|
||||||
{:ok, token}
|
{:ok, token}
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
defmodule Mobilizon.Storage.Repo.Migrations.AddLoginInformationToUser do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
alter table(:users) do
|
||||||
|
add(:last_sign_in_at, :utc_datetime, null: true)
|
||||||
|
add(:last_sign_in_ip, :string, null: true)
|
||||||
|
add(:current_sign_in_ip, :string, null: true)
|
||||||
|
add(:current_sign_in_at, :utc_datetime, null: true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue