Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Check token claim for CGU #179

Merged
merged 17 commits into from
Apr 5, 2022
21 changes: 21 additions & 0 deletions apps/lenra/lib/lenra/guardian/guardian.ex
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,25 @@ defmodule Lenra.Guardian do
{:ok, claims}
end
end

def verify_claims(claims, _options) do
with {:ok, user} <- resource_from_claims(claims) do
cgus = Lenra.Repo.preload(user, :cgus).cgus
jonas-martinez marked this conversation as resolved.
Show resolved Hide resolved

case Enum.count(cgus) do
0 ->
{:error, :did_not_accept_cgu}

_ ->
{:ok, latest_cgu} = Lenra.CguService.get_latest_cgu()
{:ok, latest_accepted_cgu} = Lenra.CguService.get_latest_cgu_from_list(cgus)
jonas-martinez marked this conversation as resolved.
Show resolved Hide resolved

with {:ok, 0} <- Lenra.CguService.compare_versions(latest_cgu, latest_accepted_cgu) do
{:ok, claims}
else
_ -> {:error, :did_not_accept_cgu}
end
end
end
end
end
51 changes: 51 additions & 0 deletions apps/lenra/lib/lenra/services/cgu_services.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,55 @@ defmodule Lenra.CguService do
cgu -> {:ok, cgu}
end
end

@doc """
Compares two CGU versions.

Returns a tuple with the following values:
- {:ok, 0}, if the versions are equal
- {:ok, -1} if the first version is older than the second
- {:ok, 1} if the first version is newer than the second
- {:error, error} if an error occurred
"""
def compare_versions(cgu1, cgu2) do
cond do
cgu1.inserted_at == cgu2.inserted_at ->
{:ok, 0}

cgu1.inserted_at < cgu2.inserted_at ->
{:ok, -1}

cgu1.inserted_at > cgu2.inserted_at ->
{:ok, 1}

true ->
{:error, "Cannot compare versions"}
end
end

@doc """
Returns the latest CGU from a list.

Returns a tuple with the following values:
- {:ok, cgu}, with cgu being the latest CGU
- {:error, error} if an error occurred
"""
def get_latest_cgu_from_list(list) do
jonas-martinez marked this conversation as resolved.
Show resolved Hide resolved
cond do
Enum.count(list) == 0 ->
{:error, "Cannot get latest CGU from an empty list"}

Enum.count(list) == 1 ->
{:ok, Enum.at(list, 0)}

true ->
latest_cgu = Enum.at(list, 0)
Enum.each(list, fn cgu ->
with {:ok, 1} <- compare_versions(cgu, latest_cgu) do
^latest_cgu = cgu
end
end)
{:ok, latest_cgu}
end
end
end
3 changes: 3 additions & 0 deletions apps/lenra_web/lib/lenra_web/guardian/error_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ defmodule Lenra.Guardian.ErrorHandler do

:unauthenticated ->
"You are not authenticated"

:did_not_accept_cgu ->
"You did not accept the latest CGU"
jonas-martinez marked this conversation as resolved.
Show resolved Hide resolved
end

conn
Expand Down
11 changes: 7 additions & 4 deletions apps/lenra_web/lib/lenra_web/guardian/token_helper.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ defmodule LenraWeb.TokenHelper do
conn = create_refresh_and_store_cookie(conn, user)

with {:ok, refresh_token} <- get_cookie_from_resp(conn),
access_token <- create_access_token(refresh_token) do
{:ok, access_token} <- create_access_token(refresh_token) do
assign_access_token(conn, access_token)
else
error ->
Expand All @@ -34,9 +34,12 @@ defmodule LenraWeb.TokenHelper do
end

def create_access_token(refresh_token) do
{:ok, _old, {access_token, _new_claims}} = Lenra.Guardian.exchange(refresh_token, "refresh", "access")

access_token
with {:ok, _old, {access_token, _new_claims}} <- Lenra.Guardian.exchange(refresh_token, "refresh", "access") do
{:ok, access_token}
else
{:error, :did_not_accept_cgu} -> {:did_not_accept_cgu, :did_not_accept_cgu}
jonas-martinez marked this conversation as resolved.
Show resolved Hide resolved
error -> error
end
end

def revoke_current_refresh(conn) do
Expand Down