-
Notifications
You must be signed in to change notification settings - Fork 86
/
ets_adapter.ex
90 lines (71 loc) · 1.99 KB
/
ets_adapter.ex
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
defmodule Guardian.DB.ETSAdapter do
@moduledoc """
Implement the Guardian.DB.Adapter for ETS
"""
@behaviour Guardian.DB.Adapter
@impl true
def one(claims, opts) do
jti = Map.get(claims, "jti")
aud = Map.get(claims, "aud")
match =
opts
|> Keyword.fetch!(:table)
|> :ets.match({jti, aud, :_, :_, :"$1"})
case match do
[[token]] -> token
_ -> nil
end
end
@impl true
def insert(%{valid?: true} = changeset, opts) do
table = Keyword.fetch!(opts, :table)
token = Map.merge(changeset.data, changeset.changes)
unless :ets.insert(table, {token.jti, token.aud, token.sub, token.exp, token}) do
raise """
An error occurred trying to insert a new record into the ETS table #{table}.
Please ensure you've created the table before attempting to insert records.
"""
end
{:ok, token}
end
def insert(changeset, _opts) do
{:error, changeset}
end
@impl true
def delete(%{jti: jti} = token, opts) do
table = Keyword.fetch!(opts, :table)
unless :ets.delete(table, jti) do
raise """
An error occurred trying to delete a record from the ETS table #{table}.
Please ensure you've created the table before attempting to delete records.
"""
end
{:ok, token}
end
@impl true
def delete_by_sub(sub, opts) do
table = Keyword.fetch!(opts, :table)
table
|> :ets.match({:"$1", :_, sub, :_, :"$2"})
|> delete_many(table)
end
@impl true
def purge_expired_tokens(exp, opts) do
table = Keyword.fetch!(opts, :table)
matcher = [{{:"$1", :"$2", :"$3", :"$4", :"$5"}, [{:<, :"$4", exp}], [[:"$1", :"$5"]]}]
table
|> :ets.select(matcher)
|> delete_many(table)
end
defp delete_many(tokens, table) do
deleted_tokens =
Enum.reduce(tokens, [], fn [jti, token], acc ->
if :ets.delete(table, jti) do
[token | acc]
else
acc
end
end)
{length(deleted_tokens), deleted_tokens}
end
end