Skip to content

Commit 917bb86

Browse files
tteerawatbegedin
authored andcommitted
Implement SetTimberUserContext plug (#1101)
* Created and applied a SetTimberUserContext plug * Implemented User.full_name/1 function * Added `SetTimberUserContext` to `groups_for_modules` in "Web – Plugs" list.
1 parent 082cb3b commit 917bb86

File tree

7 files changed

+125
-31
lines changed

7 files changed

+125
-31
lines changed

lib/code_corps/guardian.ex

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,6 @@ defmodule CodeCorps.Guardian do
1717
def resource_from_claims(_), do: {:error, :missing_subject}
1818

1919
defp resource_from_subject("Project:" <> id), do: {:ok, Repo.get(Project, id)}
20-
defp resource_from_subject("User:" <> id) do
21-
user = Repo.get(User, id)
22-
23-
if user do
24-
name = full_name(user)
25-
%Timber.Contexts.UserContext{id: user.id, email: user.email, name: name}
26-
|> Timber.add_context()
27-
end
28-
29-
{:ok, user}
30-
end
20+
defp resource_from_subject("User:" <> id), do: {:ok, Repo.get(User, id)}
3121
defp resource_from_subject(_), do: {:error, :unknown_resource_type}
32-
33-
defp full_name(%User{first_name: nil, last_name: nil}), do: ""
34-
defp full_name(%User{first_name: first_name, last_name: nil}), do: first_name
35-
defp full_name(%User{first_name: nil, last_name: last_name}), do: last_name
36-
defp full_name(%User{first_name: first_name, last_name: last_name}) do
37-
first_name <> " " <> last_name
38-
end
39-
defp full_name(_), do: ""
4022
end

lib/code_corps/model/user.ex

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ defmodule CodeCorps.User do
6868
timestamps()
6969
end
7070

71+
@doc """
72+
Returns full name of the given user.
73+
"""
74+
def full_name(%__MODULE__{first_name: first_name, last_name: last_name}) do
75+
[first_name, last_name]
76+
|> Enum.map_join(" ", &to_string/1)
77+
|> String.trim()
78+
end
79+
7180
@doc """
7281
Builds a changeset based on the `struct` and `params`.
7382
"""
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
defmodule CodeCorpsWeb.Plug.SetTimberUserContext do
2+
@moduledoc """
3+
Captures user context.
4+
"""
5+
6+
@behaviour Plug
7+
8+
alias CodeCorps.User
9+
10+
@impl true
11+
def init(opts), do: opts
12+
13+
@impl true
14+
def call(%{assigns: %{current_user: user}} = conn, _), do: add_context(conn, user)
15+
def call(conn, _), do: conn
16+
17+
@impl false
18+
def add_context(conn, %User{} = user) do
19+
%Timber.Contexts.UserContext{id: user.id, email: user.email, name: User.full_name(user)}
20+
|> Timber.add_context()
21+
22+
conn
23+
end
24+
def add_context(conn, _), do: conn
25+
end

lib/code_corps_web/router.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ defmodule CodeCorpsWeb.Router do
2626

2727
pipeline :current_user do
2828
plug CodeCorpsWeb.Plug.CurrentUser
29+
plug CodeCorpsWeb.Plug.SetTimberUserContext
2930
plug CodeCorpsWeb.Plug.SetSentryUserContext
3031
plug CodeCorpsWeb.Plug.AnalyticsIdentify
3132
end

mix.exs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,8 @@ defmodule CodeCorps.Mixfile do
232232
CodeCorpsWeb.Plug.DataToAttributes,
233233
CodeCorpsWeb.Plug.IdsToIntegers,
234234
CodeCorpsWeb.Plug.Segment,
235-
CodeCorpsWeb.Plug.SetSentryUserContext
235+
CodeCorpsWeb.Plug.SetSentryUserContext,
236+
CodeCorpsWeb.Plug.SetTimberUserContext
236237
],
237238

238239
"Miscellaneous": [

test/lib/code_corps/model/user_test.exs

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,39 @@ defmodule CodeCorps.UserTest do
66
@valid_attrs %{email: "test@user.com", password: "somepassword", username: "testuser"}
77
@invalid_attrs %{}
88

9-
test "changeset with valid attributes" do
10-
changeset = User.changeset(%User{}, @valid_attrs)
11-
assert changeset.valid?
9+
describe "full_name/1" do
10+
test "returns full name correctly" do
11+
names = [
12+
{"Josh", "Smith", "Josh Smith"},
13+
{"Josh", nil, "Josh"},
14+
{nil, "Smith", "Smith"},
15+
{nil, nil, ""},
16+
{"", "", ""}
17+
]
18+
Enum.each names, fn({first_name, last_name, expected_full_name}) ->
19+
user = build(:user, first_name: first_name, last_name: last_name)
20+
21+
assert User.full_name(user) == expected_full_name
22+
end
23+
end
1224
end
1325

14-
test "changeset with invalid attributes" do
15-
changeset = User.changeset(%User{}, @invalid_attrs)
16-
refute changeset.valid?
17-
end
26+
describe "changeset/2" do
27+
test "changeset with valid attributes" do
28+
changeset = User.changeset(%User{}, @valid_attrs)
29+
assert changeset.valid?
30+
end
1831

19-
test "changeset with invalid email" do
20-
attrs = Map.put(@valid_attrs, :email, "notanemail")
21-
changeset = User.changeset(%User{}, attrs)
22-
assert_error_message(changeset, :email, "has invalid format")
32+
test "changeset with invalid attributes" do
33+
changeset = User.changeset(%User{}, @invalid_attrs)
34+
refute changeset.valid?
35+
end
36+
37+
test "changeset with invalid email" do
38+
attrs = Map.put(@valid_attrs, :email, "notanemail")
39+
changeset = User.changeset(%User{}, attrs)
40+
assert_error_message(changeset, :email, "has invalid format")
41+
end
2342
end
2443

2544
describe "registration_changeset" do
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
defmodule CodeCorpsWeb.Plug.SetTimberUserContextTest do
2+
use CodeCorpsWeb.ConnCase
3+
4+
alias CodeCorpsWeb.Plug.SetTimberUserContext
5+
6+
@opts SetTimberUserContext.init([])
7+
8+
describe "init/1" do
9+
test "returns the given options" do
10+
assert SetTimberUserContext.init([]) == []
11+
end
12+
end
13+
14+
describe "call/2" do
15+
test "adds user context when current_user is set" do
16+
user = insert(:user, first_name: "Josh", last_name: "Smith")
17+
conn = build_conn() |> assign(:current_user, user)
18+
19+
result = SetTimberUserContext.call(conn, @opts)
20+
21+
assert result == conn
22+
assert Timber.CurrentContext.load() ==
23+
%{user: %{id: to_string(user.id), name: "Josh Smith", email: user.email}}
24+
end
25+
26+
test "adds nothing when current_user is not set" do
27+
conn = build_conn()
28+
29+
result = SetTimberUserContext.call(conn, @opts)
30+
31+
assert result == conn
32+
assert Timber.CurrentContext.load() == %{}
33+
end
34+
end
35+
36+
describe "add_context/2" do
37+
test "adds user context correctly when given user is valid" do
38+
user = insert(:user, first_name: "Josh", last_name: nil)
39+
conn = build_conn()
40+
41+
result = SetTimberUserContext.add_context(conn, user)
42+
43+
assert result == conn
44+
assert Timber.CurrentContext.load() ==
45+
%{user: %{id: to_string(user.id), name: "Josh", email: user.email}}
46+
end
47+
48+
test "adds nothing when given user is invalid" do
49+
conn = build_conn()
50+
51+
result = SetTimberUserContext.add_context(conn, nil)
52+
53+
assert result == conn
54+
assert Timber.CurrentContext.load() == %{}
55+
end
56+
end
57+
end

0 commit comments

Comments
 (0)