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

source-academy / backend / 18dc689a4df4836fc6967bf0f74dc252964bd175-PR-1180

08 Sep 2024 06:14PM UTC coverage: 79.088% (-15.3%) from 94.372%
18dc689a4df4836fc6967bf0f74dc252964bd175-PR-1180

Pull #1180

github

josh1248
Change appropriate routes into admin scope
Pull Request #1180: Transfer groundControl (and admin panel) from staff to admin route

7 of 12 new or added lines in 1 file covered. (58.33%)

499 existing lines in 25 files now uncovered.

2602 of 3290 relevant lines covered (79.09%)

1023.2 hits per line

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

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

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

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

15
  pipeline :ensure_auth do
663✔
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
613✔
24
    plug(:assign_course)
25
  end
26

27
  pipeline :ensure_admin do
45✔
28
    plug(:ensure_role, [:admin])
29
  end
30

UNCOV
31
  pipeline :ensure_staff do
×
32
    plug(:ensure_role, [:staff, :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)
1✔
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
  # Staff pages
127
  scope "/v2/courses/:course_id/staff", CadetWeb do
128
    pipe_through([:api, :auth, :ensure_auth, :course, :ensure_staff])
129

130
    resources("/sourcecast", AdminSourcecastController, only: [:create, :delete])
131

UNCOV
132
    get("/assets/:foldername", AdminAssetsController, :index)
×
UNCOV
133
    post("/assets/:foldername/*filename", AdminAssetsController, :upload)
×
UNCOV
134
    delete("/assets/:foldername/*filename", AdminAssetsController, :delete)
×
135

UNCOV
136
    get(
×
137
      "/assessments/:assessmentid/popularVoteLeaderboard",
138
      AdminAssessmentsController,
139
      :get_popular_leaderboard
140
    )
141

UNCOV
142
    get(
×
143
      "/assessments/:assessmentid/scoreLeaderboard",
144
      AdminAssessmentsController,
145
      :get_score_leaderboard
146
    )
147

UNCOV
148
    get("/grading", AdminGradingController, :index)
×
UNCOV
149
    get("/grading/summary", AdminGradingController, :grading_summary)
×
150

UNCOV
151
    post("/grading/:assessmentid/publish_all_grades", AdminGradingController, :publish_all_grades)
×
152

UNCOV
153
    post(
×
154
      "/grading/:assessmentid/unpublish_all_grades",
155
      AdminGradingController,
156
      :unpublish_all_grades
157
    )
158

UNCOV
159
    get("/grading/:submissionid", AdminGradingController, :show)
×
UNCOV
160
    post("/grading/:submissionid/unsubmit", AdminGradingController, :unsubmit)
×
UNCOV
161
    post("/grading/:submissionid/unpublish_grades", AdminGradingController, :unpublish_grades)
×
UNCOV
162
    post("/grading/:submissionid/publish_grades", AdminGradingController, :publish_grades)
×
UNCOV
163
    post("/grading/:submissionid/autograde", AdminGradingController, :autograde_submission)
×
UNCOV
164
    post("/grading/:submissionid/:questionid", AdminGradingController, :update)
×
165

UNCOV
166
    post(
×
167
      "/grading/:submissionid/:questionid/autograde",
168
      AdminGradingController,
169
      :autograde_answer
170
    )
171

UNCOV
172
    get("/users", AdminUserController, :index)
×
173
    get("/users/teamformation", AdminUserController, :get_students)
×
UNCOV
174
    put("/users", AdminUserController, :upsert_users_and_groups)
×
UNCOV
175
    get("/users/:course_reg_id/assessments", AdminAssessmentsController, :index)
×
176

177
    # The admin route for getting assessment information for a specifc user
178
    # TODO: Missing Swagger path
179
    get(
×
180
      "/users/:course_reg_id/assessments/:assessmentid",
181
      AdminAssessmentsController,
182
      :get_assessment
183
    )
184

185
    # The admin route for getting total xp of a specific user
UNCOV
186
    get("/users/:course_reg_id/total_xp", AdminUserController, :combined_total_xp)
×
UNCOV
187
    put("/users/:course_reg_id/role", AdminUserController, :update_role)
×
UNCOV
188
    get("/users/:course_reg_id/goals", AdminGoalsController, :index_goals_with_progress)
×
UNCOV
189
    post("/users/:course_reg_id/goals/:uuid/progress", AdminGoalsController, :update_progress)
×
190

UNCOV
191
    put("/achievements", AdminAchievementsController, :bulk_update)
×
UNCOV
192
    put("/achievements/:uuid", AdminAchievementsController, :update)
×
UNCOV
193
    delete("/achievements/:uuid", AdminAchievementsController, :delete)
×
194

UNCOV
195
    get("/goals", AdminGoalsController, :index)
×
UNCOV
196
    put("/goals", AdminGoalsController, :bulk_update)
×
UNCOV
197
    put("/goals/:uuid", AdminGoalsController, :update)
×
UNCOV
198
    delete("/goals/:uuid", AdminGoalsController, :delete)
×
199

UNCOV
200
    post("/stories", AdminStoriesController, :create)
×
UNCOV
201
    delete("/stories/:storyid", AdminStoriesController, :delete)
×
UNCOV
202
    post("/stories/:storyid", AdminStoriesController, :update)
×
203

NEW
204
    get("/teams", AdminTeamsController, :index)
×
NEW
205
    post("/teams", AdminTeamsController, :create)
×
NEW
206
    delete("/teams/:teamid", AdminTeamsController, :delete)
×
NEW
207
    put("/teams/:teamid", AdminTeamsController, :update)
×
NEW
208
    post("/teams/upload", AdminTeamsController, :bulk_upload)
×
209
  end
210

211
  # Admin pages
212
  scope "/v2/courses/:course_id/admin", CadetWeb do
213
    pipe_through([:api, :auth, :ensure_auth, :course, :ensure_admin])
214

215
    post("/assessments", AdminAssessmentsController, :create)
4✔
216
    post("/assessments/:assessmentid", AdminAssessmentsController, :update)
13✔
217
    delete("/assessments/:assessmentid", AdminAssessmentsController, :delete)
4✔
218

219
    put("/config", AdminCoursesController, :update_course_config)
7✔
220
    # TODO: Missing corresponding Swagger path entry
221
    get("/config/assessment_configs", AdminCoursesController, :get_assessment_configs)
2✔
222
    put("/config/assessment_configs", AdminCoursesController, :update_assessment_configs)
7✔
223
    # TODO: Missing corresponding Swagger path entry
224
    delete(
4✔
225
      "/config/assessment_config/:assessment_config_id",
226
      AdminCoursesController,
227
      :delete_assessment_config
228
    )
229

230
    post("/grading/:assessmentid/publish_all_grades", AdminGradingController, :publish_all_grades)
2✔
231

232
    post(
2✔
233
      "/grading/:assessmentid/unpublish_all_grades",
234
      AdminGradingController,
235
      :unpublish_all_grades
236
    )
237

238
    delete("/users/:course_reg_id", AdminUserController, :delete_user)
7✔
239
  end
240

241
  # Other scopes may use custom stacks.
242
  # scope "/api", CadetWeb do
243
  #   pipe_through :api
244
  # end
245

246
  def swagger_info do
247
    %{
1✔
248
      info: %{
249
        version: "2.0",
250
        title: "cadet"
251
      },
252
      basePath: "/v2",
253
      securityDefinitions: %{
254
        JWT: %{
255
          type: "apiKey",
256
          in: "header",
257
          name: "Authorization"
258
        }
259
      }
260
    }
261
  end
262

263
  scope "/swagger" do
264
    forward("/", PhoenixSwagger.Plug.SwaggerUI, otp_app: :cadet, swagger_file: "swagger.json")
1✔
265
  end
266

267
  scope "/", CadetWeb do
268
    get("/", DefaultController, :index)
1✔
269
  end
270

271
  if Mix.env() == :dev do
272
    forward("/sent_emails", Bamboo.SentEmailViewerPlug)
273
  end
274

275
  defp assign_course(conn, _opts) do
276
    course_id = conn.path_params["course_id"]
613✔
277

278
    course_reg =
613✔
279
      Cadet.Accounts.CourseRegistrations.get_user_record(conn.assigns.current_user.id, course_id)
613✔
280

281
    case course_reg do
613✔
282
      nil -> conn |> send_resp(403, "Forbidden") |> halt()
5✔
283
      cr -> assign(conn, :course_reg, cr)
608✔
284
    end
285
  end
286

287
  defp ensure_role(conn, opts) do
288
    if not is_nil(conn.assigns.current_user) and conn.assigns.course_reg.role in opts do
45✔
289
      conn
14✔
290
    else
291
      conn
292
      |> send_resp(403, "Forbidden")
293
      |> halt()
31✔
294
    end
295
  end
296
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