• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

source-academy / backend / f68ac11c84c493d4ecbbc3e74b32351c08202176-PR-1210

13 Nov 2024 04:11PM UTC coverage: 93.605% (-0.2%) from 93.78%
f68ac11c84c493d4ecbbc3e74b32351c08202176-PR-1210

Pull #1210

github

josh1248
Formatting (again)
Pull Request #1210: Create endpoint for retrieval of all assessment submissions

9 of 11 new or added lines in 2 files covered. (81.82%)

4 existing lines in 2 files now uncovered.

3103 of 3315 relevant lines covered (93.6%)

1064.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.33
/lib/cadet_web/router.ex
1
defmodule CadetWeb.Router do
2
  use CadetWeb, :router
3

4
  pipeline :api do
871✔
5
    plug(:accepts, ["json"])
6
    plug(:fetch_session)
7
    plug(:put_secure_browser_headers)
8
  end
9

10
  pipeline :auth do
871✔
11
    plug(Cadet.Auth.Pipeline)
12
    plug(CadetWeb.Plug.AssignCurrentUser)
13
  end
14

15
  pipeline :ensure_auth do
852✔
16
    plug(Guardian.Plug.EnsureAuthenticated)
17
  end
18

19
  pipeline :rate_limit do
4✔
20
    plug(CadetWeb.Plugs.RateLimiter)
21
  end
22

23
  pipeline :course do
773✔
24
    plug(:assign_course)
25
  end
26

27
  pipeline :ensure_staff do
119✔
28
    plug(:ensure_role, [:staff, :admin])
29
  end
30

31
  pipeline :ensure_admin do
80✔
32
    plug(:ensure_role, [:admin])
33
  end
34

35
  scope "/", CadetWeb do
36
    get("/.well-known/jwks.json", JWKSController, :index)
4✔
37
  end
38

39
  scope "/sso" do
40
    forward("/", Samly.Router)
×
41
  end
42

43
  # V2 API
44

45
  # Public Pages
46
  scope "/v2", CadetWeb do
47
    pipe_through([:api, :auth])
48

49
    # get("/sourcecast", SourcecastController, :index)
50
    post("/auth/refresh", AuthController, :refresh)
5✔
51
    post("/auth/login", AuthController, :create)
6✔
52
    post("/auth/logout", AuthController, :logout)
3✔
53
    get("/auth/saml_redirect", AuthController, :saml_redirect)
5✔
54
  end
55

56
  scope "/v2", CadetWeb do
57
    # no sessions or anything here
58

59
    get("/devices/:secret/cert", DevicesController, :get_cert)
3✔
60
    get("/devices/:secret/key", DevicesController, :get_key)
3✔
61
    get("/devices/:secret/client_id", DevicesController, :get_client_id)
2✔
62
    get("/devices/:secret/mqtt_endpoint", DevicesController, :get_mqtt_endpoint)
1✔
63
  end
64

65
  # Authenticated Pages without course
66
  scope "/v2", CadetWeb do
67
    pipe_through([:api, :auth, :ensure_auth])
68

69
    get("/user", UserController, :index)
3✔
70
    get("/user/latest_viewed_course", UserController, :get_latest_viewed)
3✔
71
    put("/user/latest_viewed_course", UserController, :update_latest_viewed)
2✔
72

73
    post("/config/create", CoursesController, :create)
5✔
74

75
    get("/devices", DevicesController, :index)
2✔
76
    post("/devices", DevicesController, :register)
4✔
77
    post("/devices/:id", DevicesController, :edit)
4✔
78
    delete("/devices/:id", DevicesController, :deregister)
3✔
79
    get("/devices/:id/ws_endpoint", DevicesController, :get_ws_endpoint)
4✔
80
  end
81

82
  # LLM-related endpoints
83
  scope "/v2/chats", CadetWeb do
84
    pipe_through([:api, :auth, :ensure_auth, :rate_limit])
85

86
    post("", ChatController, :init_chat)
2✔
87
    post("/:conversationId/message", ChatController, :chat)
3✔
88
  end
89

90
  # Authenticated Pages with course
91
  scope "/v2/courses/:course_id", CadetWeb do
92
    pipe_through([:api, :auth, :ensure_auth, :course])
93

94
    get("/sourcecast", SourcecastController, :index)
2✔
95

96
    get("/assessments", AssessmentsController, :index)
17✔
97
    get("/assessments/:assessmentid", AssessmentsController, :show)
93✔
98
    post("/assessments/:assessmentid/unlock", AssessmentsController, :unlock)
9✔
99
    post("/assessments/:assessmentid/submit", AssessmentsController, :submit)
365✔
100
    post("/assessments/question/:questionid/answer", AnswerController, :submit)
60✔
101

102
    post(
4✔
103
      "/assessments/question/:questionid/answerLastModified",
104
      AnswerController,
105
      :check_last_modified
106
    )
107

108
    get("/achievements", IncentivesController, :index_achievements)
2✔
109
    get("/self/goals", IncentivesController, :index_goals)
3✔
110
    post("/self/goals/:uuid/progress", IncentivesController, :update_progress)
2✔
111

112
    get("/stories", StoriesController, :index)
4✔
113

114
    get("/notifications", NotificationsController, :index)
3✔
115
    post("/notifications/acknowledge", NotificationsController, :acknowledge)
3✔
116

117
    get("/user/total_xp", UserController, :combined_total_xp)
1✔
118
    put("/user/game_states", UserController, :update_game_states)
2✔
119
    put("/user/research_agreement", UserController, :update_research_agreement)
2✔
120

121
    get("/config", CoursesController, :index)
3✔
122

123
    get("/team/:assessmentid", TeamController, :index)
2✔
124
  end
125

126
  # Admin pages (Access: Course administrators only - these routes can cause substantial damage)
127
  @doc """
128
    NOTE: This scope must come before the routes for all staff below.
129

130
    This is due to the all-staff route "/grading/:submissionid/:questionid", which would pattern match
131
    and overshadow "/grading/:assessmentid/publish_all_grades".
132

133
    If an admin route will overshadow an all-staff route as well, a suggested better solution would be a
134
    per-route permission level check.
135
  """
136
  scope "/v2/courses/:course_id/admin", CadetWeb do
137
    pipe_through([:api, :auth, :ensure_auth, :course, :ensure_admin])
138

139
    get("/assets/:foldername", AdminAssetsController, :index)
6✔
140
    post("/assets/:foldername/*filename", AdminAssetsController, :upload)
9✔
141
    delete("/assets/:foldername/*filename", AdminAssetsController, :delete)
8✔
142

143
    post("/assessments", AdminAssessmentsController, :create)
5✔
144
    post("/assessments/:assessmentid", AdminAssessmentsController, :update)
15✔
145
    delete("/assessments/:assessmentid", AdminAssessmentsController, :delete)
5✔
146

NEW
147
    get("/grading/all_submissions", AdminGradingController, :index_all_submissions)
×
148

149
    post(
2✔
150
      "/grading/:assessmentid/publish_all_grades",
151
      AdminGradingController,
152
      :publish_all_grades
153
    )
154

155
    post(
2✔
156
      "/grading/:assessmentid/unpublish_all_grades",
157
      AdminGradingController,
158
      :unpublish_all_grades
159
    )
160

161
    put("/users/:course_reg_id/role", AdminUserController, :update_role)
7✔
162
    delete("/users/:course_reg_id", AdminUserController, :delete_user)
7✔
163

164
    put("/config", AdminCoursesController, :update_course_config)
8✔
165
    # TODO: Missing corresponding Swagger path entry
166
    get("/config/assessment_configs", AdminCoursesController, :get_assessment_configs)
3✔
167
    put("/config/assessment_configs", AdminCoursesController, :update_assessment_configs)
8✔
168
    # TODO: Missing corresponding Swagger path entry
169
    delete(
5✔
170
      "/config/assessment_config/:assessment_config_id",
171
      AdminCoursesController,
172
      :delete_assessment_config
173
    )
174
  end
175

176
  # Admin pages (Access: All staff)
177
  scope "/v2/courses/:course_id/admin", CadetWeb do
178
    pipe_through([:api, :auth, :ensure_auth, :course, :ensure_staff])
179

180
    resources("/sourcecast", AdminSourcecastController, only: [:create, :delete])
181

182
    get(
5✔
183
      "/assessments/:assessmentid/popularVoteLeaderboard",
184
      AdminAssessmentsController,
185
      :get_popular_leaderboard
186
    )
187

188
    get(
1✔
189
      "/assessments/:assessmentid/scoreLeaderboard",
190
      AdminAssessmentsController,
191
      :get_score_leaderboard
192
    )
193

194
    get("/grading", AdminGradingController, :index)
8✔
195
    get("/grading/summary", AdminGradingController, :grading_summary)
2✔
196

197
    get("/grading/:submissionid", AdminGradingController, :show)
6✔
198
    post("/grading/:submissionid/unsubmit", AdminGradingController, :unsubmit)
10✔
199
    post("/grading/:submissionid/unpublish_grades", AdminGradingController, :unpublish_grades)
3✔
200
    post("/grading/:submissionid/publish_grades", AdminGradingController, :publish_grades)
4✔
201
    post("/grading/:submissionid/autograde", AdminGradingController, :autograde_submission)
3✔
202
    post("/grading/:submissionid/:questionid", AdminGradingController, :update)
9✔
203

204
    post(
3✔
205
      "/grading/:submissionid/:questionid/autograde",
206
      AdminGradingController,
207
      :autograde_answer
208
    )
209

210
    get("/users", AdminUserController, :index)
5✔
211
    get("/users/teamformation", AdminUserController, :get_students)
×
212
    put("/users", AdminUserController, :upsert_users_and_groups)
10✔
213
    get("/users/:course_reg_id/assessments", AdminAssessmentsController, :index)
4✔
214

215
    # The admin route for getting assessment information for a specifc user
216
    # TODO: Missing Swagger path
217
    get(
×
218
      "/users/:course_reg_id/assessments/:assessmentid",
219
      AdminAssessmentsController,
220
      :get_assessment
221
    )
222

223
    # The admin route for getting total xp of a specific user
224
    get("/users/:course_reg_id/total_xp", AdminUserController, :combined_total_xp)
1✔
225
    get("/users/:course_reg_id/goals", AdminGoalsController, :index_goals_with_progress)
1✔
226
    post("/users/:course_reg_id/goals/:uuid/progress", AdminGoalsController, :update_progress)
3✔
227

228
    put("/achievements", AdminAchievementsController, :bulk_update)
4✔
229
    put("/achievements/:uuid", AdminAchievementsController, :update)
3✔
230
    delete("/achievements/:uuid", AdminAchievementsController, :delete)
3✔
231

232
    get("/goals", AdminGoalsController, :index)
5✔
233
    put("/goals", AdminGoalsController, :bulk_update)
3✔
234
    put("/goals/:uuid", AdminGoalsController, :update)
3✔
235
    delete("/goals/:uuid", AdminGoalsController, :delete)
3✔
236

237
    post("/stories", AdminStoriesController, :create)
4✔
238
    delete("/stories/:storyid", AdminStoriesController, :delete)
4✔
239
    post("/stories/:storyid", AdminStoriesController, :update)
4✔
240

241
    get("/teams", AdminTeamsController, :index)
6✔
242
    post("/teams", AdminTeamsController, :create)
7✔
243
    delete("/teams/:teamid", AdminTeamsController, :delete)
5✔
244
    put("/teams/:teamid", AdminTeamsController, :update)
4✔
245
    post("/teams/upload", AdminTeamsController, :bulk_upload)
×
246
  end
247

248
  # Other scopes may use custom stacks.
249
  # scope "/api", CadetWeb do
250
  #   pipe_through :api
251
  # end
252

253
  def swagger_info do
254
    %{
1✔
255
      info: %{
256
        version: "2.0",
257
        title: "cadet"
258
      },
259
      basePath: "/v2",
260
      securityDefinitions: %{
261
        JWT: %{
262
          type: "apiKey",
263
          in: "header",
264
          name: "Authorization"
265
        }
266
      }
267
    }
268
  end
269

270
  scope "/swagger" do
271
    forward("/", PhoenixSwagger.Plug.SwaggerUI, otp_app: :cadet, swagger_file: "swagger.json")
1✔
272
  end
273

274
  scope "/", CadetWeb do
275
    get("/", DefaultController, :index)
1✔
276
  end
277

278
  if Mix.env() == :dev do
279
    forward("/sent_emails", Bamboo.SentEmailViewerPlug)
280
  end
281

282
  defp assign_course(conn, _opts) do
283
    course_id = conn.path_params["course_id"]
773✔
284

285
    course_reg =
773✔
286
      Cadet.Accounts.CourseRegistrations.get_user_record(conn.assigns.current_user.id, course_id)
773✔
287

288
    case course_reg do
773✔
289
      nil -> conn |> send_resp(403, "Forbidden") |> halt()
10✔
290
      cr -> assign(conn, :course_reg, cr)
763✔
291
    end
292
  end
293

294
  defp ensure_role(conn, opts) do
295
    if not is_nil(conn.assigns.current_user) and conn.assigns.course_reg.role in opts do
199✔
296
      conn
146✔
297
    else
298
      conn
299
      |> send_resp(403, "Forbidden")
300
      |> halt()
53✔
301
    end
302
  end
303
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc