View Source Charon.SessionStore.Behaviour behaviour (Charon v3.2.0)
Behaviour definition of a persistent session store.
Clients should not use the implementation directly, but should use Charon.SessionStore
.
Implementation guidelines
Implementations are expected to store sessions by ID, user ID and session type.
For the optional callbacks get_all/3
and delete_all/3
, sessions should be retrievable
by user ID and session type only.
Implementations should return the session exactly as it went in (they don't have to take care of struct version upgrades).
Implementations should handle cleanup of expired entries,
but may define additional functions and instructions to take care of such things
(like a cleanup/0
that should run periodically).
Implementations should implement optimistic locking with respect to the :lock_version
field
of the session struct. On an update, the lock version of the updated session should match
the lock version of the existing session. If that is the case, the implementation should increase
:lock_version
and proceed with the update. If not, the implementation should abort the update
and return {:error, :conflict}
.
Summary
Callbacks
Delete session of type type
with id session_id
for user with id user_id
.
Delete all sessions of type type
for the user with id user_id
.
Get session of type type
with id session_id
for user with id user_id
.
Must not return sessions that have expired,
or that can't be refreshed anymore because the refresh token has expired.
Get all sessions of type type
for the user with id user_id
.
Must not return sessions that have expired,
or that can't be refreshed anymore because the refresh token has expired.
Insert or update session
. If the implementation supports optimistic locking, it
will return {:error, :conflict}
on an optimistic locking conflict.
Callbacks
@callback delete( session_id :: binary(), user_id :: binary() | integer(), type :: atom(), config :: Charon.Config.t() ) :: :ok | {:error, binary()}
Delete session of type type
with id session_id
for user with id user_id
.
Implementations may choose to ignore user_id
, since session_id
is unique by itself.
@callback delete_all( user_id :: binary() | integer(), type :: atom(), config :: Charon.Config.t() ) :: :ok | {:error, binary()}
Delete all sessions of type type
for the user with id user_id
.
@callback get( session_id :: binary(), user_id :: binary() | integer(), type :: atom(), config :: Charon.Config.t() ) :: Charon.Models.Session.t() | nil | {:error, binary()}
Get session of type type
with id session_id
for user with id user_id
.
Must not return sessions that have expired,
or that can't be refreshed anymore because the refresh token has expired.
Implementations may choose to ignore user_id
, since session_id
is unique by itself.
@callback get_all( user_id :: binary() | integer(), type :: atom(), config :: Charon.Config.t() ) :: [Charon.Models.Session.t()] | {:error, binary()}
Get all sessions of type type
for the user with id user_id
.
Must not return sessions that have expired,
or that can't be refreshed anymore because the refresh token has expired.
@callback upsert(session :: Charon.Models.Session.t(), config :: Charon.Config.t()) :: :ok | {:error, :conflict | binary()}
Insert or update session
. If the implementation supports optimistic locking, it
will return {:error, :conflict}
on an optimistic locking conflict.
Values session_id
, user_id
and type
are taken from the session
struct.
Implementations may choose to ignore user_id
, since session_id
is unique by itself.
Implementations may assume that Charon.SessionPlugs.upsert_session/3
will ensure that:
:refreshed_at
contains the current unix timestamp:refresh_expires_at
never exceeds:expires_at