Skip to content

Commit 3dcb004

Browse files
committed
Add UserTaskPolicy and tests
1 parent 539e785 commit 3dcb004

File tree

2 files changed

+165
-0
lines changed

2 files changed

+165
-0
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
defmodule CodeCorps.UserTaskPolicyTest do
2+
@moduledoc false
3+
4+
use CodeCorps.PolicyCase
5+
6+
import CodeCorps.UserTaskPolicy, only: [create?: 2, delete?: 2]
7+
import CodeCorps.UserTask, only: [create_changeset: 2]
8+
9+
alias CodeCorps.UserTask
10+
11+
defp generate_data_for(role) do
12+
{user, project} = insert_user_and_project(role)
13+
14+
task = case role do
15+
"author" -> insert(:task, project: project, user: user)
16+
_ -> insert(:task, project: project)
17+
end
18+
19+
{user, task}
20+
end
21+
22+
defp insert_user_and_project(role) do
23+
user = insert(:user)
24+
organization = insert(:organization)
25+
project = insert(:project, organization: organization)
26+
27+
insert_membership(user, organization, role)
28+
29+
{user, project}
30+
end
31+
32+
defp insert_membership(_, _, role) when role in ~w(non-member author), do: nil
33+
defp insert_membership(user, organization, role) do
34+
insert(:organization_membership, organization: organization, member: user, role: role)
35+
end
36+
37+
describe "create?" do
38+
test "returns false when user is not member of organization" do
39+
{user, task} = generate_data_for("non-member")
40+
41+
changeset = %UserTask{} |> create_changeset(%{task_id: task.id})
42+
refute create?(user, changeset)
43+
end
44+
45+
test "returns false when user is pending member of organization" do
46+
{user, task} = generate_data_for("pending")
47+
48+
changeset = %UserTask{} |> create_changeset(%{task_id: task.id})
49+
refute create?(user, changeset)
50+
end
51+
52+
test "returns true when user is contributor of organization" do
53+
{user, task} = generate_data_for("contributor")
54+
55+
changeset = %UserTask{} |> create_changeset(%{task_id: task.id})
56+
assert create?(user, changeset)
57+
end
58+
59+
test "returns true when user is admin of organization" do
60+
{user, task} = generate_data_for("admin")
61+
62+
changeset = %UserTask{} |> create_changeset(%{task_id: task.id})
63+
assert create?(user, changeset)
64+
end
65+
66+
test "returns true when user is owner of organization" do
67+
{user, task} = generate_data_for("owner")
68+
69+
changeset = %UserTask{} |> create_changeset(%{task_id: task.id})
70+
assert create?(user, changeset)
71+
end
72+
73+
test "returns true when user is author of task" do
74+
{user, task} = generate_data_for("author")
75+
76+
changeset = %UserTask{} |> create_changeset(%{task_id: task.id})
77+
78+
assert create?(user, changeset)
79+
end
80+
end
81+
82+
describe "delete?" do
83+
test "returns false when user is not member of organization" do
84+
{user, task} = generate_data_for("non-member")
85+
86+
user_task = insert(:user_task, task: task)
87+
88+
refute delete?(user, user_task)
89+
end
90+
91+
test "returns false when user is pending member of organization" do
92+
{user, task} = generate_data_for("pending")
93+
94+
user_task = insert(:user_task, task: task)
95+
96+
refute delete?(user, user_task)
97+
end
98+
99+
test "returns true when user is contributor of organization" do
100+
{user, task} = generate_data_for("contributor")
101+
102+
user_task = insert(:user_task, task: task)
103+
104+
assert delete?(user, user_task)
105+
end
106+
107+
test "returns true when user is admin of organization" do
108+
{user, task} = generate_data_for("admin")
109+
110+
user_task = insert(:user_task, task: task)
111+
112+
assert delete?(user, user_task)
113+
end
114+
115+
test "returns true when user is owner of organization" do
116+
{user, task} = generate_data_for("owner")
117+
118+
user_task = insert(:user_task, task: task)
119+
120+
assert delete?(user, user_task)
121+
end
122+
123+
test "returns true when user is author of task" do
124+
{user, task} = generate_data_for("author")
125+
126+
user_task = insert(:user_task, task: task)
127+
128+
assert delete?(user, user_task)
129+
end
130+
end
131+
end

web/policies/user_task_policy.ex

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
defmodule CodeCorps.UserTaskPolicy do
2+
@moduledoc """
3+
Represents an authorization policy for performing actions on UserTask records.
4+
Used to authorize a controller action.
5+
"""
6+
import CodeCorps.Helpers.Policy,
7+
only: [get_project: 1, get_membership: 2, get_role: 1, contributor_or_higher?: 1]
8+
9+
alias CodeCorps.{Repo, Task, UserTask, User}
10+
alias Ecto.Changeset
11+
12+
@spec create?(User.t, Changeset.t) :: boolean
13+
def create?(%User{} = user, %Changeset{} = changeset) do
14+
cond do
15+
changeset |> get_task |> get_project |> get_membership(user) |> get_role |> contributor_or_higher? -> true
16+
changeset |> get_task |> authored_by?(user) -> true
17+
true -> false
18+
end
19+
end
20+
21+
@spec delete?(User.t, UserTask.t) :: boolean
22+
def delete?(%User{} = user, %UserTask{} = user_task) do
23+
cond do
24+
user_task |> get_task |> get_project |> get_membership(user) |> get_role |> contributor_or_higher? -> true
25+
user_task |> get_task |> authored_by?(user) -> true
26+
true -> false
27+
end
28+
end
29+
30+
defp get_task(%UserTask{task_id: task_id}), do: Repo.get(Task, task_id)
31+
defp get_task(%Changeset{changes: %{task_id: task_id}}), do: Repo.get(Task, task_id)
32+
33+
defp authored_by?(%Task{user_id: author_id}, %User{id: user_id}), do: user_id == author_id
34+
end

0 commit comments

Comments
 (0)