Skip to content

Commit

Permalink
Add ability to delete all redbird sessions
Browse files Browse the repository at this point in the history
* Prepends all session keys with "redbird_sessions" so that it will be
easy to identify which keys in the users redis database were set through
Redbird

* Adds the ExRedis `keys` option to find all keys that start with the
redbird session

* Adds `delete_all_sessions` to delete all matching keys
  • Loading branch information
aellispierce committed Feb 2, 2017
1 parent 2c5f3c6 commit 3ba4922
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 5 deletions.
22 changes: 22 additions & 0 deletions lib/mix/tasks/redbird/delete_all_sessions.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
defmodule Mix.Tasks.Redbird.DeleteAllSessions do
use Mix.Task

@shortdoc "Deletes all redbird sessions"

@moduledoc """
Deletes all redbird sessions.
mix redbird.delete_all_sessions my_app
The first argument is the app specific key_namespace you set in your plug
session config. If no argument is given, it will delete all redbird sessions.
"""
def run(_args) do
Redbird.start(nil, nil)
Plug.Session.REDIS.namespace
|> delete_all_sessions
end

def delete_all_sessions(namespace) do
Redbird.Redis.keys("#{namespace}*")
|> Redbird.Redis.del
end
end
27 changes: 22 additions & 5 deletions lib/redbird/plug/session/redis.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,43 @@ defmodule Plug.Session.REDIS do
opts
end

def get(_conn, redis_key, _init_options) do
case get(redis_key) do
def get(_conn, namespaced_key, _init_options) do
case get(namespaced_key) do
:undefined -> {nil, %{}}
value -> {redis_key, value |> :erlang.binary_to_term}
value -> {namespaced_key, value |> :erlang.binary_to_term}
end
end

def put(conn, nil, data, init_options) do
put(conn, generate_random_key(), data, init_options)
end
def put(_conn, redis_key, data, init_options) do
setex(%{key: redis_key, value: data, seconds: session_expiration(init_options)})
redis_key
key = add_namespace(redis_key)
setex(%{
key: key,
value: data,
seconds: session_expiration(init_options)
})
key
end

def delete(_conn, redis_key, _kinit_options) do
del(redis_key)
:ok
end

defp add_namespace(key) do
namespace <> key
end

def namespace do
Application.get_env(:redbird, :key_namespace, redbird_namespace)
end

def redbird_namespace do
"redbird_session_"
end

defp generate_random_key do
:crypto.strong_rand_bytes(96) |> Base.encode64
end
Expand Down
4 changes: 4 additions & 0 deletions lib/redis.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ defmodule Redbird.Redis do
Exredis.Api.del(pid(), key)
end

def keys(pattern) do
Exredis.Api.keys(pattern)
end

def pid do
:redbird_phoenix_session
end
Expand Down
31 changes: 31 additions & 0 deletions test/mix/tasks/redbird/delete_all_sessions_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
defmodule Mix.Tasks.Redbird.DeleteAllSessionsTest do
use ExUnit.Case
alias Plug.Session.REDIS

setup do
on_exit fn ->
Mix.Tasks.Redbird.DeleteAllSessions.run([])
end
end

test "deletes all redbird session keys" do
key = "redis_session"
conn = %{}
options = []
REDIS.put(conn, key, %{foo: :bar}, options)

assert {nil, %{}} = REDIS.get(conn, key, options)
end

test "deletes user defined namespaced session keys" do
Application.put_env(:redbird, :key_namespace, "test_")
conn = %{}
key = "redis_session"
options = []
REDIS.put(conn, key, %{foo: :bar}, options)

Mix.Tasks.Redbird.DeleteAllSessions.run([])

assert {nil, %{}} = REDIS.get(conn, "test_" <> key, options)
end
end
28 changes: 28 additions & 0 deletions test/redbird_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ defmodule RedbirdTest do
:ok = Application.start(:redbird)
end

setup do
on_exit fn ->
Redbird.Redis.keys(Plug.Session.REDIS.namespace <> "*")
|> Redbird.Redis.del
end
end

describe "get" do
test "when there is value stored it is retrieved" do
conn = conn(:get, "/")
Expand Down Expand Up @@ -90,4 +97,25 @@ defmodule RedbirdTest do
assert {nil, %{}} = REDIS.get(conn, key, options)
end
end

test "redbird_session is appended to key names by default" do
conn = %{}
key = "redis_session"
options = []
REDIS.put(conn, key, %{foo: :bar}, options)

assert {"redbird_session_redis_session", %{foo: :bar}} = REDIS.get(conn, "redbird_session_" <> key, options)
end

test "user can set their own key namespace" do
Application.put_env(:redbird, :key_namespace, "test_")
Redbird.Redis.keys("test_*")
|> Redbird.Redis.del
conn = %{}
key = "redis_session"
options = []
REDIS.put(conn, key, %{foo: :bar}, options)

assert {"test_redis_session", %{foo: :bar}} = REDIS.get(conn, "test_" <> key, options)
end
end

0 comments on commit 3ba4922

Please sign in to comment.