Home Projects Jsjiit Architecture And Design

Architecture and Design

Purpose and Scope

This document provides a comprehensive technical overview of the jsjiit library's internal architecture, design patterns, and implementation details. It focuses on the structural organization of the codebase, the relationships between core components, and the architectural decisions that enable browser-based interaction with the JIIT WebPortal API.

For practical usage information, see Getting Started. For detailed API method documentation, see API Reference. For information about the build pipeline and artifact generation, see Build and Distribution.


Architectural Overview

The jsjiit library implements a client-server proxy pattern where the library acts as an intermediary between browser applications and the JIIT WebPortal backend. The architecture consists of three primary layers:

  1. API Surface Layer: Unified export interface (src/index.js)
  2. Portal Interaction Layer: Session management and HTTP communication (src/wrapper.js)
  3. Support Infrastructure: Cryptography (src/encryption.js), domain models, utilities, and error handling

System Architecture Diagram

Architecture Diagram


Class Structure and Relationships

The library exposes two primary classes and multiple data model classes. The class hierarchy is intentionally flat, favoring composition over inheritance.

Core Classes

Class Location Responsibility
WebPortal src/wrapper.js75-671 Main API orchestrator; manages session lifecycle and provides all public API methods
WebPortalSession src/wrapper.js25-70 Immutable session container; stores authentication token and user metadata
AttendanceMeta src/attendance.js Container for attendance headers and semester lists
AttendanceHeader src/attendance.js Represents attendance metadata with stynumber
Semester src/attendance.js Represents academic semester with registration data
RegisteredSubject src/registration.js Individual subject registration details
Registrations src/registration.js Collection of registered subjects and faculty
ExamEvent src/exam.js Exam event metadata

Class Relationship Diagram

Architecture Diagram


Module Dependency Graph

The module organization follows a clear dependency hierarchy with no circular dependencies. The index.js module serves as a facade, while wrapper.js is the central orchestrator.

Dependency Flow Diagram

Architecture Diagram

Import Dependency Table

Module Direct Dependencies Purpose
src/index.js All modules Unified export facade
src/wrapper.js exceptions, registration, attendance, exam, encryption Core API implementation
src/encryption.js utils AES-CBC cryptography
src/attendance.js None Data models only
src/registration.js None Data models only
src/exam.js None Data models only
src/exceptions.js None Error definitions only
src/utils.js None Pure utility functions
src/feedback.js None Enum definitions only

Request/Response Lifecycle

Every authenticated API call follows a consistent request/response pattern involving encryption, HTTP communication, and data transformation.

Request Flow Diagram

Architecture Diagram

HTTP Request Construction

The __hit() method at src/wrapper.js97-158 is the central HTTP communication primitive. It handles:

  1. Header injection: Adds Authorization: Bearer {token} and LocalName: {encrypted_name}
  2. Payload serialization: Converts options.json to JSON string or uses options.body directly
  3. Error transformation: Maps HTTP status codes to custom exceptions
  4. Response validation: Checks status.responseStatus === "Success"
// Simplified flow from wrapper.js:97-158
async __hit(method, url, options = {}) {
    // 1. Determine exception type
    let exception = options.exception || APIError;

    // 2. Generate headers (authenticated or anonymous)
    let header = options.authenticated 
        ? await this.session.get_headers()
        : { LocalName: await generate_local_name() };

    // 3. Build fetch options
    let fetchOptions = {
        method: method,
        headers: { "Content-Type": "application/json", ...header },
        body: options.json ? JSON.stringify(options.json) : options.body
    };

    // 4. Execute request and validate response
    const response = await fetch(url, fetchOptions);
    if (response.status === 401) throw new SessionExpired();
    const resp = await response.json();
    if (resp.status.responseStatus !== "Success") throw new exception(...);

    return resp;
}

Authentication Architecture

Authentication is managed through a two-phase login process and enforced via a decorator pattern.

Authentication Flow

Architecture Diagram

Session Token Structure

The WebPortalSession class parses the JWT token to extract metadata:

// From wrapper.js:49-51
this.token = this.regdata["token"];
let expiry_timestamp = JSON.parse(atob(this.token.split(".")[1]))["exp"];
this.expiry = new Date(expiry_timestamp * 1000);

The token is a standard JWT with three base64-encoded sections (header.payload.signature). The library decodes the payload section to extract the exp (expiry) claim.

Authentication Enforcement Decorator

All protected methods are wrapped with the authenticated() decorator at src/wrapper.js679-686:

function authenticated(method) {
  return function (...args) {
    if (this.session == null) {
      throw new NotLoggedIn();
    }
    return method.apply(this, args);
  };
}

The decorator is applied to 15 methods via iteration at src/wrapper.js692-719:

const authenticatedMethods = [
  "get_personal_info",
  "get_student_bank_info",
  "change_password",
  "get_attendance_meta",
  // ... 10 more methods
];

authenticatedMethods.forEach((methodName) => {
  WebPortal.prototype[methodName] = authenticated(WebPortal.prototype[methodName]);
});

Encryption and Payload Serialization

All sensitive payloads are encrypted using AES-CBC with a date-based key derivation scheme. This is covered in detail in Encryption and Security, but the architectural integration points are:

Encryption Integration Points

Method Location Purpose
serialize_payload(payload) src/encryption.js91-95 Encrypts outgoing request payloads
deserialize_payload(payload) src/encryption.js80-84 Decrypts incoming response payloads (not currently used)
generate_local_name(date) src/encryption.js43-51 Creates encrypted request header value
generate_key(date) src/encryption.js32-36 Derives AES key from date sequence

Payload Serialization Flow

Architecture Diagram


Error Handling Strategy

The library implements a hierarchical exception system with custom error classes for different failure scenarios.

Exception Hierarchy

Architecture Diagram

Error Usage Mapping

Exception Thrown By Trigger Condition
LoginError src/wrapper.js175-183 Failed pretoken or token generation
SessionExpired src/wrapper.js142 HTTP 401 response
NotLoggedIn src/wrapper.js682 Authenticated method called without session
AccountAPIError src/wrapper.js234 Password change failure
APIError src/wrapper.js98 Default for all other API failures

Design Patterns

The library employs several established design patterns:

1. Facade Pattern

The src/index.js module implements a facade by re-exporting all public APIs from internal modules:

// From index.js:13-31
export {
  WebPortal,
  WebPortalSession,
  API,
  DEFCAPTCHA,
  AttendanceHeader,
  Semester,
  AttendanceMeta,
  RegisteredSubject,
  Registrations,
  ExamEvent,
  APIError,
  LoginError,
  // ... more exports
};

This provides a single import point for consumers: import { WebPortal } from 'jsjiit'.

2. Decorator Pattern

The authenticated() function decorates method prototypes to inject session validation logic:

// From wrapper.js:679-686
function authenticated(method) {
  return function (...args) {
    if (this.session == null) {
      throw new NotLoggedIn();
    }
    return method.apply(this, args);
  };
}

Applied at runtime to 15 methods via forEach iteration.

3. Factory Pattern

Domain model classes use static factory methods for construction from JSON:

// Pattern used in Semester, ExamEvent
static from_json(json) {
  return new ClassName(json);
}

This provides a clear API for constructing objects from API responses.

4. Singleton Session

The WebPortal class maintains a single session instance at src/wrapper.js80:

constructor() {
  this.session = null;
}

Once set via student_login(), this session is reused for all subsequent authenticated requests until the instance is destroyed.


API Constants and Configuration

API Endpoint Constant

The base API URL is defined at src/wrapper.js14:

export const API = "https://webportal.jiit.ac.in:6011/StudentPortalAPI";

All endpoint paths are concatenated with this base URL.

CAPTCHA Bypass Default

A hardcoded CAPTCHA value is defined at src/wrapper.js20:

export const DEFCAPTCHA = { captcha: "phw5n", hidden: "gmBctEffdSg=" };

This allows the library to bypass CAPTCHA validation by default (the portal accepts these values without visual verification).


Cryptographic Constants

Fixed Initialization Vector

The AES-CBC encryption uses a hardcoded IV at src/encryption.js25:

const IV = new TextEncoder().encode("dcek9wb8frty1pnm");

This is a 16-byte constant used for all encryption operations. While not cryptographically ideal (IVs should be unique per encryption), it matches the portal's server-side implementation.

Key Derivation Formula

The AES key is derived from the current date at src/encryption.js34:

const keyData = new TextEncoder().encode("qa8y" + dateSeq + "ty1pn");

Where dateSeq is formatted as MMDDHHmm (month, day, hour, minute). This creates a time-based shared secret between client and server.


Summary

The jsjiit library architecture is characterized by:

  1. Clear separation of concerns: Domain models, cryptography, HTTP communication, and error handling are isolated in separate modules
  2. Minimal dependencies: Only two devDependencies (esbuild, jsdoc) with no runtime dependencies
  3. Flat class hierarchy: Favors composition over inheritance for simplicity
  4. Decorator-based AOP: Authentication enforcement via method decoration
  5. Cryptographic abstraction: All encryption details hidden behind serialize_payload() and generate_local_name()
  6. Immutable sessions: WebPortalSession objects are created once and never modified
  7. Consistent error handling: Custom exception hierarchy with specific error types for different failure modes

For implementation details of specific subsystems, see: