Skip to content
This repository has been archived by the owner on Mar 23, 2021. It is now read-only.

Commit

Permalink
Sign datetime for token
Browse files Browse the repository at this point in the history
Merge pull request #56 from l-vincent-l/no_db_token
  • Loading branch information
Mauko Quiroga committed Apr 8, 2020
2 parents 8f99677 + 978c49e commit 89a5805
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 28 deletions.
4 changes: 2 additions & 2 deletions lib/covid19_questionnaire/data/store.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ defmodule Covid19Questionnaire.Data.Store do
@tick_interval 1000
@chunk_size 100

def write({date, token}, questionnaire = %{metadata: metadata}) do
duration = DateTime.diff(date, token.date)
def write({date, %{date: token_date} = token}, questionnaire = %{metadata: metadata}) do
duration = DateTime.diff(date, token_date)
metadata = %{metadata | date: date, duration: duration}
questionnaire = %{questionnaire | token: token, metadata: metadata}
data = %{data: questionnaire}
Expand Down
34 changes: 22 additions & 12 deletions lib/covid19_questionnaire/data/token.ex
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
defmodule Covid19Questionnaire.Data.Token do
@moduledoc false
@endpoint Covid19QuestionnaireWeb.Endpoint
@max_age 3600

use Ecto.Schema
alias Covid19Questionnaire.Data.Repo
def create do
now = DateTime.utc_now()
dt = DateTime.to_unix(now, :microsecond)

@derive {Jason.Encoder, except: [:__meta__, :__struct__]}
@primary_key {:uuid, :binary_id, autogenerate: true}

schema "token" do
field(:date, :utc_datetime_usec)
{:ok,
%{
uuid: Phoenix.Token.encrypt(@endpoint, secret(), dt),
date: now
}}
end

def create, do: Repo.insert(%__MODULE__{date: DateTime.utc_now()})
def decrypt(token) do
case Phoenix.Token.decrypt(@endpoint, secret(), token, max_age: @max_age) do
{:ok, dt} ->
DateTime.from_unix(dt, :microsecond)

def find(uuid) do
case Ecto.UUID.cast(uuid) do
:error -> nil
_ -> Repo.get(__MODULE__, uuid)
{:error, error} ->
{:error, error}
end
end

defp secret do
:covid19_questionnaire
|> Application.get_env(@endpoint)
|> Keyword.get(:secret_key_base)
end
end
15 changes: 8 additions & 7 deletions lib/covid19_questionnaire_web/plugs/authenticate.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ defmodule Covid19QuestionnaireWeb.Plugs.Authenticate do
alias Covid19Questionnaire.Data.Token

rule "authenticate", conn do
conn
|> get_req_header("x-token")
|> hd
|> Token.find()
|> case do
nil -> block(true)
token -> allow(token)
token =
conn
|> get_req_header("x-token")
|> hd

case Token.decrypt(token) do
{:ok, start_datetime} -> allow(%{date: start_datetime, uuid: token})
_ -> block(true)
end
end

Expand Down
10 changes: 5 additions & 5 deletions test/covid19_questionnaire/data/store_test.exs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
defmodule Covid19Questionnaire.Data.StoreTest do
use ExUnit.Case, async: true
alias Covid19Questionnaire.Data.{Journal, Store}
alias Covid19Questionnaire.Data.{Journal, Store, Token}
alias Covid19QuestionnaireWeb.Schemas.{Metadata, Questionnaire}

test "stores data" do
questionnaire = %Questionnaire{
metadata: %Metadata{}
}

date_tokn = DateTime.utc_now()
date_quiz = date_tokn |> DateTime.add(3600, :second)
uuid = "faketoken"
{:ok, data} = Store.write({date_quiz, %{uuid: uuid, date: date_tokn}}, questionnaire)
{:ok, %{date: token_date} = token} = Token.create()
date_quiz = DateTime.add(token_date, 3600, :second)

{:ok, data} = Store.write({date_quiz, token}, questionnaire)

data =
data
Expand Down
10 changes: 8 additions & 2 deletions test/covid19_questionnaire/data/token_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@ defmodule Covid19Questionnaire.Data.TokenTest do
alias Covid19Questionnaire.Data.Token

test "stores & retrieves tokens" do
{:ok, token = %{uuid: uuid}} = Token.create()
{:ok, %{uuid: token, date: date}} = Token.create()

assert token == Token.find(uuid)
{:ok, start_datetime} = Token.decrypt(token)

assert_in_delta(
DateTime.to_unix(date, :microsecond),
DateTime.to_unix(start_datetime, :microsecond),
1000
)
end
end

0 comments on commit 89a5805

Please sign in to comment.