webportal class
WebPortal in src/wrapper.js is the object you construct. It stores one WebPortalSession and talks to StudentPortalAPI through __hit.
Related:
- Authentication and session management
- Attendance methods
- Registration and subject methods
- Exam and schedule methods
- Academic records methods
- Feedback and account methods
- Error handling
- Data models
Shape#
constructor() {
this.session = null;
}
No constructor options in 0.0.22. No proxy fields.
classDiagram
class WebPortal {
session
student_login()
__hit()
get_attendance_meta()
get_grade_card()
fill_feedback_form()
}
class WebPortalSession {
token
expiry
instituteid
memberid
get_headers()
}
WebPortal --> WebPortalSession : sessionSession#
sequenceDiagram participant App participant WP as WebPortal participant API as StudentPortalAPI App->>WP: new WebPortal Note over WP: session = null App->>WP: student_login WP->>API: pret token then generate-token1 API-->>WP: response.regdata WP->>WP: this.session = new WebPortalSession WP-->>App: session
WebPortalSession fields from login regdata:
| Property | Source |
|---|---|
raw_response |
full constructor arg |
regdata |
resp.regdata |
institute |
institutelist[0].label |
instituteid |
institutelist[0].value |
memberid |
regdata.memberid |
userid |
regdata.userid |
token |
regdata.token |
expiry |
JWT payload exp × 1000 |
clientid |
regdata.clientid |
membertype |
regdata.membertype |
name |
regdata.name |
enrollmentno |
regdata.enrollmentno |
First institute in institutelist wins. Multi-institute accounts are not selectable.
__hit#
async __hit(method, url, options = {})
| Option | Meaning |
|---|---|
headers |
merged after LocalName / Bearer |
json |
JSON.stringify into the body |
body |
raw body if json is absent |
authenticated |
use session.get_headers() |
exception |
error class, default APIError |
flowchart TD
start[__hit] --> exc{options.exception?}
exc -->|yes| useCustom[use that class]
exc -->|no| useAPI[APIError]
useCustom --> auth{authenticated?}
useAPI --> auth
auth -->|yes| hdr[session.get_headers]
auth -->|no| local[generate_local_name]
hdr --> fetchN[fetch]
local --> fetchN
fetchN --> s513{status 513?}
s513 -->|yes| throw513[unavailable]
s513 -->|no| s401{status 401?}
s401 -->|yes| throw401[SessionExpired]
s401 -->|no| json[response.json]
json --> ok{responseStatus Success?}
ok -->|no| throwSt[exception with status JSON]
ok -->|yes| ret[return resp]
fetchN --> cors{TypeError CORS?}
cors -->|yes| throwCors[unavailable]flowchart LR jsonOpt[options.json] --> stringify[JSON.stringify] bodyOpt[options.body] --> raw[raw string] stringify --> fetchBody[fetch body] raw --> fetchBody
GET with no body still sets fetchOptions.body to undefined because the json / body branch always assigns body. download_marks skips __hit and calls fetch itself.
Content-Type: application/json is always set.
Login#
async student_login(username, password, captcha = DEFCAPTCHA)
Throws LoginError. Payload is serialize_payload then __hit with options.body (already a string). See Authentication and session management.
Authenticated methods#
After login, methods on WebPortal (not on the session object) hit portal routes. Each group has its own page.
authenticated(method) wraps the prototype:
if (this.session == null) throw new NotLoggedIn();
return method.apply(this, args);
flowchart TD call[portal.get_attendance_meta] --> wrap[authenticated wrapper] wrap -->|session null| nl[NotLoggedIn] wrap -->|session set| impl[original method]
fill_feedback_form is not wrapped. download_marks is wrapped but talks to fetch directly.
Constants on the same module#
export const API = "https://webportal.jiit.ac.in:6011/StudentPortalAPI";
export const DEFCAPTCHA = { captcha: "phw5n", hidden: "gmBctEffdSg=" };
Every URL is API + ENDPOINT.
Payload encryption vs plain JSON#
Encrypted with serialize_payload then usually passed as options.json (so the encrypted string is JSON-stringified again): attendance detail, daily attendance, registration lists, exam lists, marks semester list, grade card, SGPA, fines, subject choices, parts of feedback.
Plain JSON objects: personal info, bank info, change password, attendance meta, fee summary, hostel, feedback event list.
Login uses options.body with the encrypted string, not json.
flowchart LR login[student_login] --> body[options.body encrypted string] att[get_attendance] --> jsonEnc[options.json encrypted string] info[get_personal_info] --> jsonPlain[options.json object]
download_marks oddity#
const localname = await generate_local_name();
let _headers = await this.session.get_headers(localname);
get_headers takes no parameters, so localname is unused. Headers still get a fresh LocalName from inside get_headers.
Logging#
__hit prints console.log(options) and console.log("fetching", url, "with options", fetchOptions). That includes request headers. Expect noise in the browser console.