Skip to content

Commit 43e1833

Browse files
authored
Merge pull request #674 from code-corps/667-user-tasks
UserTask model, policies and endpoints
2 parents 575134d + aff42e5 commit 43e1833

File tree

13 files changed

+575
-1
lines changed

13 files changed

+575
-1
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
defmodule CodeCorps.Repo.Migrations.CreateUserTask do
2+
@moduledoc false
3+
4+
use Ecto.Migration
5+
6+
def change do
7+
create table(:user_tasks) do
8+
add :task_id, references(:tasks), null: false
9+
add :user_id, references(:users), null: false
10+
11+
timestamps()
12+
end
13+
14+
create index :user_tasks, [:user_id, :task_id], unique: true
15+
end
16+
end

priv/repo/structure.sql

Lines changed: 141 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,38 @@ CREATE SEQUENCE task_lists_id_seq
10621062
ALTER SEQUENCE task_lists_id_seq OWNED BY task_lists.id;
10631063

10641064

1065+
--
1066+
-- Name: task_skills; Type: TABLE; Schema: public; Owner: -
1067+
--
1068+
1069+
CREATE TABLE task_skills (
1070+
id integer NOT NULL,
1071+
skill_id integer NOT NULL,
1072+
task_id integer NOT NULL,
1073+
inserted_at timestamp without time zone NOT NULL,
1074+
updated_at timestamp without time zone NOT NULL
1075+
);
1076+
1077+
1078+
--
1079+
-- Name: task_skills_id_seq; Type: SEQUENCE; Schema: public; Owner: -
1080+
--
1081+
1082+
CREATE SEQUENCE task_skills_id_seq
1083+
START WITH 1
1084+
INCREMENT BY 1
1085+
NO MINVALUE
1086+
NO MAXVALUE
1087+
CACHE 1;
1088+
1089+
1090+
--
1091+
-- Name: task_skills_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
1092+
--
1093+
1094+
ALTER SEQUENCE task_skills_id_seq OWNED BY task_skills.id;
1095+
1096+
10651097
--
10661098
-- Name: tasks; Type: TABLE; Schema: public; Owner: -
10671099
--
@@ -1199,6 +1231,38 @@ CREATE SEQUENCE user_skills_id_seq
11991231
ALTER SEQUENCE user_skills_id_seq OWNED BY user_skills.id;
12001232

12011233

1234+
--
1235+
-- Name: user_tasks; Type: TABLE; Schema: public; Owner: -
1236+
--
1237+
1238+
CREATE TABLE user_tasks (
1239+
id integer NOT NULL,
1240+
task_id integer NOT NULL,
1241+
user_id integer NOT NULL,
1242+
inserted_at timestamp without time zone NOT NULL,
1243+
updated_at timestamp without time zone NOT NULL
1244+
);
1245+
1246+
1247+
--
1248+
-- Name: user_tasks_id_seq; Type: SEQUENCE; Schema: public; Owner: -
1249+
--
1250+
1251+
CREATE SEQUENCE user_tasks_id_seq
1252+
START WITH 1
1253+
INCREMENT BY 1
1254+
NO MINVALUE
1255+
NO MAXVALUE
1256+
CACHE 1;
1257+
1258+
1259+
--
1260+
-- Name: user_tasks_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
1261+
--
1262+
1263+
ALTER SEQUENCE user_tasks_id_seq OWNED BY user_tasks.id;
1264+
1265+
12021266
--
12031267
-- Name: users; Type: TABLE; Schema: public; Owner: -
12041268
--
@@ -1422,6 +1486,13 @@ ALTER TABLE ONLY stripe_platform_customers ALTER COLUMN id SET DEFAULT nextval('
14221486
ALTER TABLE ONLY task_lists ALTER COLUMN id SET DEFAULT nextval('task_lists_id_seq'::regclass);
14231487

14241488

1489+
--
1490+
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
1491+
--
1492+
1493+
ALTER TABLE ONLY task_skills ALTER COLUMN id SET DEFAULT nextval('task_skills_id_seq'::regclass);
1494+
1495+
14251496
--
14261497
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
14271498
--
@@ -1450,6 +1521,13 @@ ALTER TABLE ONLY user_roles ALTER COLUMN id SET DEFAULT nextval('user_roles_id_s
14501521
ALTER TABLE ONLY user_skills ALTER COLUMN id SET DEFAULT nextval('user_skills_id_seq'::regclass);
14511522

14521523

1524+
--
1525+
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
1526+
--
1527+
1528+
ALTER TABLE ONLY user_tasks ALTER COLUMN id SET DEFAULT nextval('user_tasks_id_seq'::regclass);
1529+
1530+
14531531
--
14541532
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
14551533
--
@@ -1633,6 +1711,14 @@ ALTER TABLE ONLY task_lists
16331711
ADD CONSTRAINT task_lists_pkey PRIMARY KEY (id);
16341712

16351713

1714+
--
1715+
-- Name: task_skills_pkey; Type: CONSTRAINT; Schema: public; Owner: -
1716+
--
1717+
1718+
ALTER TABLE ONLY task_skills
1719+
ADD CONSTRAINT task_skills_pkey PRIMARY KEY (id);
1720+
1721+
16361722
--
16371723
-- Name: user_categories_pkey; Type: CONSTRAINT; Schema: public; Owner: -
16381724
--
@@ -1657,6 +1743,14 @@ ALTER TABLE ONLY user_skills
16571743
ADD CONSTRAINT user_skills_pkey PRIMARY KEY (id);
16581744

16591745

1746+
--
1747+
-- Name: user_tasks_pkey; Type: CONSTRAINT; Schema: public; Owner: -
1748+
--
1749+
1750+
ALTER TABLE ONLY user_tasks
1751+
ADD CONSTRAINT user_tasks_pkey PRIMARY KEY (id);
1752+
1753+
16601754
--
16611755
-- Name: users_pkey; Type: CONSTRAINT; Schema: public; Owner: -
16621756
--
@@ -1966,6 +2060,13 @@ CREATE UNIQUE INDEX stripe_platform_customers_user_id_index ON stripe_platform_c
19662060
CREATE INDEX task_lists_project_id_index ON task_lists USING btree (project_id);
19672061

19682062

2063+
--
2064+
-- Name: task_skills_task_id_skill_id_index; Type: INDEX; Schema: public; Owner: -
2065+
--
2066+
2067+
CREATE UNIQUE INDEX task_skills_task_id_skill_id_index ON task_skills USING btree (task_id, skill_id);
2068+
2069+
19692070
--
19702071
-- Name: tasks_number_project_id_index; Type: INDEX; Schema: public; Owner: -
19712072
--
@@ -2008,6 +2109,13 @@ CREATE UNIQUE INDEX user_categories_user_id_category_id_index ON user_categories
20082109
CREATE UNIQUE INDEX user_roles_user_id_role_id_index ON user_roles USING btree (user_id, role_id);
20092110

20102111

2112+
--
2113+
-- Name: user_tasks_user_id_task_id_index; Type: INDEX; Schema: public; Owner: -
2114+
--
2115+
2116+
CREATE UNIQUE INDEX user_tasks_user_id_task_id_index ON user_tasks USING btree (user_id, task_id);
2117+
2118+
20112119
--
20122120
-- Name: users_email_index; Type: INDEX; Schema: public; Owner: -
20132121
--
@@ -2301,6 +2409,22 @@ ALTER TABLE ONLY task_lists
23012409
ADD CONSTRAINT task_lists_project_id_fkey FOREIGN KEY (project_id) REFERENCES projects(id);
23022410

23032411

2412+
--
2413+
-- Name: task_skills_skill_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
2414+
--
2415+
2416+
ALTER TABLE ONLY task_skills
2417+
ADD CONSTRAINT task_skills_skill_id_fkey FOREIGN KEY (skill_id) REFERENCES skills(id);
2418+
2419+
2420+
--
2421+
-- Name: task_skills_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
2422+
--
2423+
2424+
ALTER TABLE ONLY task_skills
2425+
ADD CONSTRAINT task_skills_task_id_fkey FOREIGN KEY (task_id) REFERENCES tasks(id);
2426+
2427+
23042428
--
23052429
-- Name: tasks_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
23062430
--
@@ -2373,9 +2497,25 @@ ALTER TABLE ONLY user_skills
23732497
ADD CONSTRAINT user_skills_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);
23742498

23752499

2500+
--
2501+
-- Name: user_tasks_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
2502+
--
2503+
2504+
ALTER TABLE ONLY user_tasks
2505+
ADD CONSTRAINT user_tasks_task_id_fkey FOREIGN KEY (task_id) REFERENCES tasks(id);
2506+
2507+
2508+
--
2509+
-- Name: user_tasks_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
2510+
--
2511+
2512+
ALTER TABLE ONLY user_tasks
2513+
ADD CONSTRAINT user_tasks_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);
2514+
2515+
23762516
--
23772517
-- PostgreSQL database dump complete
23782518
--
23792519

2380-
INSERT INTO "schema_migrations" (version) VALUES (20160723215749), (20160804000000), (20160804001111), (20160805132301), (20160805203929), (20160808143454), (20160809214736), (20160810124357), (20160815125009), (20160815143002), (20160816020347), (20160816034021), (20160817220118), (20160818000944), (20160818132546), (20160820113856), (20160820164905), (20160822002438), (20160822004056), (20160822011624), (20160822020401), (20160822044612), (20160830081224), (20160830224802), (20160911233738), (20160912002705), (20160912145957), (20160918003206), (20160928232404), (20161003185918), (20161019090945), (20161019110737), (20161020144622), (20161021131026), (20161031001615), (20161121005339), (20161121014050), (20161121043941), (20161121045709), (20161122015942), (20161123081114), (20161123150943), (20161124085742), (20161125200620), (20161126045705), (20161127054559), (20161205024856), (20161207112519), (20161209192504), (20161212005641), (20161214005935), (20161215052051), (20161216051447), (20161218005913), (20161219160401), (20161219163909), (20161220141753), (20161221085759), (20161226213600), (20161231063614), (20170102130055), (20170102181053), (20170104113708), (20170104212623), (20170104235423), (20170106013143), (20170115035159), (20170115230549), (20170121014100);
2520+
INSERT INTO "schema_migrations" (version) VALUES (20160723215749), (20160804000000), (20160804001111), (20160805132301), (20160805203929), (20160808143454), (20160809214736), (20160810124357), (20160815125009), (20160815143002), (20160816020347), (20160816034021), (20160817220118), (20160818000944), (20160818132546), (20160820113856), (20160820164905), (20160822002438), (20160822004056), (20160822011624), (20160822020401), (20160822044612), (20160830081224), (20160830224802), (20160911233738), (20160912002705), (20160912145957), (20160918003206), (20160928232404), (20161003185918), (20161019090945), (20161019110737), (20161020144622), (20161021131026), (20161031001615), (20161121005339), (20161121014050), (20161121043941), (20161121045709), (20161122015942), (20161123081114), (20161123150943), (20161124085742), (20161125200620), (20161126045705), (20161127054559), (20161205024856), (20161207112519), (20161209192504), (20161212005641), (20161214005935), (20161215052051), (20161216051447), (20161218005913), (20161219160401), (20161219163909), (20161220141753), (20161221085759), (20161226213600), (20161231063614), (20170102130055), (20170102181053), (20170104113708), (20170104212623), (20170104235423), (20170106013143), (20170115035159), (20170115230549), (20170121014100), (20170131234029), (20170201035458);
23812521

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
defmodule CodeCorps.UserTaskControllerTest do
2+
@moduledoc false
3+
4+
use CodeCorps.ApiCase, resource_name: :user_task
5+
6+
describe "index" do
7+
test "lists all entries on index", %{conn: conn} do
8+
[user_task_1, user_task_2] = insert_pair(:user_task)
9+
10+
conn
11+
|> request_index
12+
|> json_response(200)
13+
|> assert_ids_from_response([user_task_1.id, user_task_2.id])
14+
end
15+
16+
test "filters resources on index", %{conn: conn} do
17+
[user_task_1, user_task_2 | _] = insert_list(3, :user_task)
18+
19+
path = "user-tasks/?filter[id]=#{user_task_1.id},#{user_task_2.id}"
20+
21+
conn
22+
|> get(path)
23+
|> json_response(200)
24+
|> assert_ids_from_response([user_task_1.id, user_task_2.id])
25+
end
26+
end
27+
28+
describe "show" do
29+
test "shows chosen resource", %{conn: conn} do
30+
user = insert(:user)
31+
task = insert(:task)
32+
user_task = insert(:user_task, task: task, user: user)
33+
34+
conn
35+
|> request_show(user_task)
36+
|> json_response(200)
37+
|> Map.get("data")
38+
|> assert_result_id(user_task.id)
39+
end
40+
41+
test "renders 404 error when id is nonexistent", %{conn: conn} do
42+
assert conn |> request_show(:not_found) |> json_response(404)
43+
end
44+
end
45+
46+
describe "create" do
47+
@tag :authenticated
48+
test "creates and renders resource when data is valid", %{conn: conn, current_user: current_user} do
49+
task = insert(:task, user: current_user)
50+
user = insert(:user)
51+
52+
attrs = %{task: task, user: user}
53+
assert conn |> request_create(attrs) |> json_response(201)
54+
end
55+
56+
@tag :authenticated
57+
test "renders 422 error when data is invalid", %{conn: conn, current_user: current_user} do
58+
task = insert(:task, user: current_user)
59+
60+
invalid_attrs = %{task: task, user: nil}
61+
assert conn |> request_create(invalid_attrs) |> json_response(422)
62+
end
63+
64+
test "renders 401 when unauthenticated", %{conn: conn} do
65+
assert conn |> request_create |> json_response(401)
66+
end
67+
68+
@tag :authenticated
69+
test "renders 403 when not authorized", %{conn: conn} do
70+
task = insert(:task)
71+
user = insert(:user)
72+
attrs = %{task: task, user: user}
73+
74+
assert conn |> request_create(attrs) |> json_response(403)
75+
end
76+
end
77+
78+
describe "delete" do
79+
@tag :authenticated
80+
test "deletes chosen resource", %{conn: conn, current_user: current_user} do
81+
task = insert(:task, user: current_user)
82+
user_task = insert(:user_task, task: task)
83+
84+
assert conn |> request_delete(user_task) |> response(204)
85+
end
86+
87+
test "renders 401 when unauthenticated", %{conn: conn} do
88+
assert conn |> request_delete |> json_response(401)
89+
end
90+
91+
@tag :authenticated
92+
test "renders 403 when not authorized", %{conn: conn} do
93+
assert conn |> request_delete |> json_response(403)
94+
end
95+
96+
@tag :authenticated
97+
test "renders 404 when id is nonexistent on delete", %{conn: conn} do
98+
assert conn |> request_delete(:not_found) |> json_response(404)
99+
end
100+
end
101+
end

test/models/user_task_test.exs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
defmodule CodeCorps.UserTaskTest do
2+
@moduledoc false
3+
4+
use CodeCorps.ModelCase
5+
6+
alias CodeCorps.UserTask
7+
8+
describe "create_changeset/2" do
9+
@required_attrs ~w(task_id user_id)
10+
11+
test "requires #{@required_attrs}" do
12+
changeset = UserTask.create_changeset(%UserTask{}, %{})
13+
14+
assert_validation_triggered(changeset, :task_id, :required)
15+
assert_validation_triggered(changeset, :user_id, :required)
16+
end
17+
18+
test "ensures associated Task record exists" do
19+
user = insert(:user)
20+
changeset = UserTask.create_changeset(%UserTask{}, %{task_id: -1, user_id: user.id})
21+
22+
{:error, response_changeset} = Repo.insert(changeset)
23+
assert_error_message(response_changeset, :task, "does not exist")
24+
end
25+
26+
test "ensures associated User record exists" do
27+
task = insert(:task)
28+
changeset = UserTask.create_changeset(%UserTask{}, %{task_id: task.id, user_id: -1})
29+
30+
{:error, response_changeset} = Repo.insert(changeset)
31+
assert_error_message(response_changeset, :user, "does not exist")
32+
end
33+
34+
test "ensures uniqueness of User/Task combination" do
35+
user_task = insert(:user_task)
36+
37+
changeset = UserTask.create_changeset(%UserTask{}, %{task_id: user_task.task_id, user_id: user_task.user_id})
38+
39+
{:error, response_changeset} = Repo.insert(changeset)
40+
assert_error_message(response_changeset, :user, "has already been taken")
41+
end
42+
end
43+
end

0 commit comments

Comments
 (0)