Skip to content

Commit 90497ee

Browse files
committed
Cherry-pick IVLE changes from PR #73
1 parent 614fa62 commit 90497ee

File tree

4 files changed

+131
-8
lines changed

4 files changed

+131
-8
lines changed

lib/cadet/accounts/ivle.ex

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ defmodule Cadet.Accounts.IVLE do
88
[this link](http://ivle.nus.edu.sg/LAPI/default.aspx).
99
"""
1010

11-
@api_url "https://ivle.nus.edu.sg/api/Lapi.svc"
11+
@api_url "https://ivle.nus.edu.sg/api/Lapi.svc/"
1212
@api_key Dotenv.load().values["IVLE_KEY"]
1313

1414
@doc """
@@ -30,7 +30,7 @@ defmodule Cadet.Accounts.IVLE do
3030
{:ok, "e012345"}
3131
3232
"""
33-
def fetch_nusnet_id(token), do: api_fetch("UserID_Get", token)
33+
def fetch_nusnet_id(token), do: api_fetch("UserID_Get", Token: token)
3434

3535
@doc """
3636
Get the full name of the user corresponding to this token.
@@ -51,10 +51,51 @@ defmodule Cadet.Accounts.IVLE do
5151
{:ok, "LEE NING YUAN"}
5252
5353
"""
54-
def fetch_name(token), do: api_fetch("UserName_Get", token)
54+
def fetch_name(token), do: api_fetch("UserName_Get", Token: token)
5555

56-
defp api_fetch(path, token) do
57-
case HTTPoison.get(api_url(path, token)) do
56+
@doc """
57+
Get the role of the user corresponding to this token.
58+
59+
returns...
60+
61+
- {:ok, :student} - valid token, permission "S"
62+
- {:ok, :admin} - valid token, permission "O"
63+
- {:ok, :staff} - valid token, permissions "F", "M", "R"
64+
- {:error, :bad_request} - invalid token, or not taking the module
65+
66+
This function assumes that inactive modules have an ID of
67+
`"00000000-0000-0000-0000-000000000000"`, and that there is only one active
68+
module with the course code `"CS1101S"`. (So far, these assumptions have been
69+
true).
70+
"""
71+
def fetch_role(token) do
72+
{:ok, modules} = api_fetch("Modules", AuthToken: token, CourseID: "CS1101S")
73+
74+
cs1101s =
75+
modules["Results"]
76+
|> Enum.filter(fn module ->
77+
module["CourseCode"] == "CS1101S" and
78+
module["ID"] != "00000000-0000-0000-0000-000000000000"
79+
end)
80+
|> List.first()
81+
82+
case cs1101s do
83+
%{"Permission" => "S"} ->
84+
{:ok, :student}
85+
86+
%{"Permission" => "O"} ->
87+
{:ok, :admin}
88+
89+
%{"Permission" => _} ->
90+
{:ok, :staff}
91+
92+
_ ->
93+
{:error, :bad_request}
94+
end
95+
end
96+
97+
defp api_fetch(method, queries) do
98+
case HTTPoison.get(api_url(method, queries)) do
5899
{:ok, %{body: body, status_code: 200}} when body != ~s("") ->
59100
{:ok, Poison.decode!(body)}
60101

@@ -68,8 +109,17 @@ defmodule Cadet.Accounts.IVLE do
68109
end
69110
end
70111

71-
defp api_url(path, token) do
72-
# construct a valid URL with the module attributes, and given params
73-
"#{@api_url}/#{path}?APIKey=#{@api_key}&Token=#{token}"
112+
# Construct a valid URL with the module attributes, and given params
113+
# token_param_key is specified as some api calls use ...&Token={token},
114+
# but other calls use ...&AuthToken={token}
115+
defp api_url(method, queries) do
116+
queries = [APIKey: @api_key] ++ queries
117+
118+
url =
119+
@api_url
120+
|> URI.merge(method)
121+
|> (&"#{&1}?#{URI.encode_query(queries)}").()
122+
123+
url
74124
end
75125
end

test/cadet/accounts/ivle_test.exs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,19 @@ defmodule Cadet.Accounts.IVLETest do
5757
end
5858
end
5959
end
60+
61+
describe "Fetch a role" do
62+
test "Using a valid token" do
63+
use_cassette "ivle/fetch_role#1" do
64+
assert {:ok, role} = IVLE.fetch_role(@token)
65+
assert Enum.member?([:student, :staff, :admin], role)
66+
end
67+
end
68+
69+
test "Using an invalid token" do
70+
use_cassette "ivle/fetch_role#2" do
71+
assert {:error, :bad_request} = IVLE.fetch_role(@token <> "Z")
72+
end
73+
end
74+
end
6075
end
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[
2+
{
3+
"request": {
4+
"body": "",
5+
"headers": [],
6+
"method": "get",
7+
"options": [],
8+
"request_body": "",
9+
"url": "https://ivle.nus.edu.sg/api/Lapi.svc/Modules"
10+
},
11+
"response": {
12+
"binary": false,
13+
"body": "{\"Results\":[{\"Announcements\":[],\"Forums\":[],\"Workbins\":[],\"Webcasts\":[],\"Gradebooks\":[],\"Polls\":[],\"Multimedia\":[],\"LessonPlan\":[],\"ID\":\"a6579f36-4d7d-41fb-b394-92a00b78148b\",\"CourseLevel\":\"1\",\"CourseCode\":\"CS1101S\",\"CourseName\":\"PROGRAMMING METHODOLOGY\",\"CourseDepartment\":\"\",\"CourseSemester\":\"Semester 1\",\"CourseAcadYear\":\"2018/2019\",\"CourseOpenDate\":\"\\/Date(1526486400000+0800)\\/\",\"CourseOpenDate_js\":\"2018-05-17T00:00:00\",\"CourseCloseDate\":\"\\/Date(1545494340000+0800)\\/\",\"CourseCloseDate_js\":\"2018-12-22T23:59:00\",\"CourseMC\":\"0\",\"isActive\":\"Y\",\"Permission\":\"S\",\"Creator\":{\"UserID\":\"dcsmjh\",\"Name\":\"Martin Henz\",\"Email\":null,\"Title\":null,\"UserGuid\":\"4dce39fc-432c-4e4c-aef1-8bb187fcbcc0\",\"AccountType\":null,\"Photo\":null},\"hasGradebookItems\":false,\"hasTimetableItems\":false,\"hasGroupsItems\":false,\"hasClassGroupsForSignUp\":false,\"hasGuestRosterItems\":false,\"hasClassRosterItems\":false,\"hasWeblinkItems\":false,\"hasLecturerItems\":false,\"hasDescriptionItems\":false,\"hasReadingItems\":false,\"hasAnnouncementItems\":false,\"hasProjectGroupItems\":false,\"hasProjectGroupsForSignUp\":false,\"hasConsultationItems\":false,\"hasConsultationSlotsForSignUp\":false,\"hasLessonPlanItems\":false,\"Badge\":3,\"BadgeAnnouncement\":3,\"WebLinks\":[],\"Lecturers\":[],\"Descriptions\":[],\"ReadingFormatted\":[],\"ReadingUnformatted\":[]}],\"Comments\":\"Valid login!\",\"LastUpdate\":\"\\/Date(1529925360661+0800)\\/\",\"LastUpdate_js\":\"2018-06-25T19:16:00.6613434+08:00\"}",
14+
"headers": {
15+
"Cache-Control": "private",
16+
"Content-Type": "application/json",
17+
"Server": "Microsoft-IIS/8.5",
18+
"Request-Context": "appId=cid-v1:9bebd252-0be2-48b7-a1db-8e2b70524944",
19+
"Set-Cookie": "ASP.NET_SessionId=45zj2hcegu2tf01cjxe2tljv; path=/; HttpOnly",
20+
"X-AspNet-Version": "4.0.30319",
21+
"X-Powered-By": "ASP.NET",
22+
"Date": "Mon, 25 Jun 2018 11:16:00 GMT",
23+
"Content-Length": "1423"
24+
},
25+
"status_code": 200,
26+
"type": "ok"
27+
}
28+
}
29+
]
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[
2+
{
3+
"request": {
4+
"body": "",
5+
"headers": [],
6+
"method": "get",
7+
"options": [],
8+
"request_body": "",
9+
"url": "https://ivle.nus.edu.sg/api/Lapi.svc/Modules"
10+
},
11+
"response": {
12+
"binary": false,
13+
"body": "{\"Results\":[],\"Comments\":\"Invalid login!\",\"LastUpdate\":\"\\/Date(1529925361303+0800)\\/\",\"LastUpdate_js\":\"2018-06-25T19:16:01.3037465+08:00\"}",
14+
"headers": {
15+
"Cache-Control": "private",
16+
"Content-Type": "application/json",
17+
"Server": "Microsoft-IIS/8.5",
18+
"Request-Context": "appId=cid-v1:9bebd252-0be2-48b7-a1db-8e2b70524944",
19+
"Set-Cookie": "ASP.NET_SessionId=lrv1epzits2rh4hhkxg1uv2w; path=/; HttpOnly",
20+
"X-AspNet-Version": "4.0.30319",
21+
"X-Powered-By": "ASP.NET",
22+
"Date": "Mon, 25 Jun 2018 11:16:00 GMT",
23+
"Content-Length": "138"
24+
},
25+
"status_code": 200,
26+
"type": "ok"
27+
}
28+
}
29+
]

0 commit comments

Comments
 (0)