Skip to content

Commit 56fac01

Browse files
committed
Minor improvements
1 parent f0bdd94 commit 56fac01

2 files changed

Lines changed: 66 additions & 10 deletions

File tree

apps/codebattle/lib/codebattle/group_task/context.ex

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,17 +120,44 @@ defmodule Codebattle.GroupTask.Context do
120120
{:error, :invalid_token}
121121

122122
group_task_token ->
123+
create_solution(group_task_token, attrs)
124+
end
125+
end
126+
127+
defp create_solution(group_task_token, attrs) do
128+
params = %{
129+
user_id: group_task_token.user_id,
130+
group_task_id: group_task_token.group_task_id,
131+
lang: Map.get(attrs, "lang") || Map.get(attrs, :lang)
132+
}
133+
134+
case decode_solution(Map.get(attrs, "solution") || Map.get(attrs, :solution)) do
135+
{:ok, decoded_solution} ->
123136
%GroupTaskSolution{}
124-
|> GroupTaskSolution.changeset(%{
125-
user_id: group_task_token.user_id,
126-
group_task_id: group_task_token.group_task_id,
127-
solution: Map.get(attrs, "solution") || Map.get(attrs, :solution),
128-
lang: Map.get(attrs, "lang") || Map.get(attrs, :lang)
129-
})
137+
|> GroupTaskSolution.changeset(Map.put(params, :solution, decoded_solution))
130138
|> Repo.insert()
139+
140+
:error ->
141+
{:error, invalid_solution_encoding_changeset(params)}
131142
end
132143
end
133144

145+
defp decode_solution(solution) when is_binary(solution) do
146+
case Base.decode64(String.trim(solution)) do
147+
{:ok, decoded_solution} -> {:ok, decoded_solution}
148+
:error -> :error
149+
end
150+
end
151+
152+
defp decode_solution(_solution), do: :error
153+
154+
defp invalid_solution_encoding_changeset(params) do
155+
%GroupTaskSolution{}
156+
|> GroupTaskSolution.changeset(Map.put(params, :solution, "placeholder"))
157+
|> Ecto.Changeset.delete_change(:solution)
158+
|> Ecto.Changeset.add_error(:solution, "is invalid base64")
159+
end
160+
134161
defp generate_token do
135162
32
136163
|> :crypto.strong_rand_bytes()

apps/codebattle/test/codebattle_web/controllers/api/v1/group_task_solution_controller_test.exs

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ defmodule CodebattleWeb.Api.V1.GroupTaskSolutionControllerTest do
1818
response =
1919
conn
2020
|> put_req_header("authorization", "Bearer some-token")
21-
|> post("/api/v1/group_task_solutions", %{"solution" => "print(1)", "lang" => "python"})
21+
|> post("/api/v1/group_task_solutions", %{
22+
"solution" => Base.encode64("print(1)"),
23+
"lang" => "python"
24+
})
2225
|> json_response(403)
2326

2427
assert response["error"] == "group_tasks_api_disabled"
@@ -30,7 +33,10 @@ defmodule CodebattleWeb.Api.V1.GroupTaskSolutionControllerTest do
3033
response =
3134
conn
3235
|> put_req_header("authorization", "Bearer missing-token")
33-
|> post("/api/v1/group_task_solutions", %{"solution" => "print(1)", "lang" => "python"})
36+
|> post("/api/v1/group_task_solutions", %{
37+
"solution" => Base.encode64("print(1)"),
38+
"lang" => "python"
39+
})
3440
|> json_response(401)
3541

3642
assert response["error"] == "unauthorized"
@@ -47,7 +53,7 @@ defmodule CodebattleWeb.Api.V1.GroupTaskSolutionControllerTest do
4753
conn
4854
|> put_req_header("authorization", "Bearer #{token.token}")
4955
|> post("/api/v1/group_task_solutions", %{
50-
"solution" => "def solution():\n return 42\n",
56+
"solution" => Base.encode64("def solution():\n return 42\n"),
5157
"lang" => "Python"
5258
})
5359
|> json_response(201)
@@ -71,11 +77,34 @@ defmodule CodebattleWeb.Api.V1.GroupTaskSolutionControllerTest do
7177
response =
7278
conn
7379
|> put_req_header("authorization", "Bearer #{token.token}")
74-
|> post("/api/v1/group_task_solutions", %{"solution" => " ", "lang" => ""})
80+
|> post("/api/v1/group_task_solutions", %{
81+
"solution" => Base.encode64(" "),
82+
"lang" => ""
83+
})
7584
|> json_response(422)
7685

7786
assert response["errors"]["solution"] == ["can't be blank"]
7887
assert response["errors"]["lang"] == ["can't be blank"]
7988
assert Repo.aggregate(Codebattle.GroupTaskSolution, :count, :id) == 0
8089
end
90+
91+
test "returns validation error for malformed solution base64", %{conn: conn} do
92+
FunWithFlags.enable(:group_tasks_api)
93+
94+
user = insert(:user)
95+
group_task = insert(:group_task)
96+
{:ok, token} = Context.create_or_rotate_token(group_task, user.id)
97+
98+
response =
99+
conn
100+
|> put_req_header("authorization", "Bearer #{token.token}")
101+
|> post("/api/v1/group_task_solutions", %{
102+
"solution" => "***not-base64***",
103+
"lang" => "python"
104+
})
105+
|> json_response(422)
106+
107+
assert response["errors"]["solution"] == ["is invalid base64"]
108+
assert Repo.aggregate(Codebattle.GroupTaskSolution, :count, :id) == 0
109+
end
81110
end

0 commit comments

Comments
 (0)