File size: 1,840 Bytes
3e21b19 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | defmodule Plausible.Auth.UserSession do
@moduledoc """
Schema for storing user session data.
"""
use Ecto.Schema
use Plausible
import Ecto.Changeset
alias Plausible.Auth
@type t() :: %__MODULE__{}
@rand_size 32
@timeout Duration.new!(day: 14)
schema "user_sessions" do
field :token, :binary
field :device, :string
field :last_used_at, :naive_datetime
field :timeout_at, :naive_datetime
belongs_to :user, Plausible.Auth.User
timestamps(updated_at: false)
end
@spec timeout_duration() :: Duration.t()
def timeout_duration(), do: @timeout
@spec new_session(Auth.User.t(), String.t(), Keyword.t()) :: Ecto.Changeset.t()
def new_session(user, device, opts \\ []) do
now = Keyword.get(opts, :now, NaiveDateTime.utc_now(:second))
timeout_at = Keyword.get(opts, :timeout_at, NaiveDateTime.shift(now, @timeout))
%__MODULE__{}
|> cast(%{device: device}, [:device])
|> generate_token()
|> put_assoc(:user, user)
|> put_change(:timeout_at, timeout_at)
|> touch_session(now)
end
@spec touch_session(t() | Ecto.Changeset.t(), NaiveDateTime.t()) :: Ecto.Changeset.t()
def touch_session(session, now \\ NaiveDateTime.utc_now(:second)) do
changeset = change(session)
on_ee do
case get_field(changeset, :user) do
%{type: :sso} ->
put_change(changeset, :last_used_at, now)
_ ->
changeset
|> put_change(:last_used_at, now)
|> put_change(:timeout_at, NaiveDateTime.shift(now, @timeout))
end
else
changeset
|> put_change(:last_used_at, now)
|> put_change(:timeout_at, NaiveDateTime.shift(now, @timeout))
end
end
defp generate_token(changeset) do
token = :crypto.strong_rand_bytes(@rand_size)
put_change(changeset, :token, token)
end
end
|