mirror of
https://github.com/classchartsapi/classcharts-api-js.git
synced 2026-05-14 11:58:13 +00:00
fix: revalidate auth token
This commit is contained in:
parent
91e956b642
commit
797c43ed56
6 changed files with 523 additions and 487 deletions
10
package.json
10
package.json
|
|
@ -25,7 +25,7 @@
|
||||||
"author": "James Cook",
|
"author": "James Cook",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.2.0"
|
"axios": "^1.3.5"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist/**"
|
"dist/**"
|
||||||
|
|
@ -47,5 +47,13 @@
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
"volta": {
|
"volta": {
|
||||||
"node": "18.12.1"
|
"node": "18.12.1"
|
||||||
|
},
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": "./dist/index.js",
|
||||||
|
"require": "./dist/index.js"
|
||||||
|
},
|
||||||
|
"./types": "./dist/index.d.ts",
|
||||||
|
"./package.json": "./package.json"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
940
pnpm-lock.yaml
generated
940
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -18,14 +18,16 @@ import type {
|
||||||
LessonsResponse,
|
LessonsResponse,
|
||||||
Student,
|
Student,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
import { PING_INTERVAL } from "./consts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base client
|
* The base client
|
||||||
*/
|
*/
|
||||||
export class ClasschartsClient {
|
export class ClasschartsClient {
|
||||||
protected studentId = 0;
|
public studentId = 0;
|
||||||
protected studentName = "";
|
|
||||||
public authCookies: Array<string> | undefined;
|
public authCookies: Array<string> | undefined;
|
||||||
public sessionId = "";
|
public sessionId = "";
|
||||||
|
public lastPing = 0;
|
||||||
protected API_BASE = "";
|
protected API_BASE = "";
|
||||||
protected axios: AxiosInstance;
|
protected axios: AxiosInstance;
|
||||||
/**
|
/**
|
||||||
|
|
@ -42,21 +44,49 @@ export class ClasschartsClient {
|
||||||
validateStatus: () => true,
|
validateStatus: () => true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
public async getNewSessionId() {
|
||||||
|
const pingFormData = new URLSearchParams();
|
||||||
|
pingFormData.append("include_data", "true");
|
||||||
|
const pingData = await this.makeAuthedRequest(
|
||||||
|
this.API_BASE + "/ping",
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
data: pingFormData.toString(),
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ includeMeta: true, revalidateToken: false }
|
||||||
|
);
|
||||||
|
this.sessionId = pingData.meta.session_id;
|
||||||
|
this.lastPing = Date.now();
|
||||||
|
}
|
||||||
public async makeAuthedRequest(
|
public async makeAuthedRequest(
|
||||||
path: string,
|
path: string,
|
||||||
axiosOptions: Omit<AxiosRequestConfig, "path">,
|
axiosOptions: Omit<AxiosRequestConfig, "path">,
|
||||||
options?: { includeMeta?: boolean }
|
options?: { includeMeta?: boolean; revalidateToken?: boolean }
|
||||||
) {
|
) {
|
||||||
if (!this.authCookies) throw new Error("Not authenticated");
|
if (!this.sessionId) throw new Error("No session ID");
|
||||||
|
if (!options) {
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
if (typeof options?.revalidateToken == "undefined") {
|
||||||
|
options.revalidateToken = true;
|
||||||
|
}
|
||||||
const requestOptions: AxiosRequestConfig = {
|
const requestOptions: AxiosRequestConfig = {
|
||||||
...axiosOptions,
|
...axiosOptions,
|
||||||
url: path,
|
url: path,
|
||||||
headers: {
|
headers: {
|
||||||
Cookie: this.authCookies.join(";"),
|
Cookie: this?.authCookies?.join(";") ?? [],
|
||||||
authorization: "Basic " + this.sessionId,
|
authorization: "Basic " + this.sessionId,
|
||||||
...axiosOptions.headers,
|
...axiosOptions.headers,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
if (options?.revalidateToken === true && this.lastPing) {
|
||||||
|
if (Date.now() - this.lastPing + 5000 > PING_INTERVAL) {
|
||||||
|
await this.getNewSessionId();
|
||||||
|
}
|
||||||
|
}
|
||||||
const request = await this.axios.request(requestOptions);
|
const request = await this.axios.request(requestOptions);
|
||||||
const responseJSON = request.data;
|
const responseJSON = request.data;
|
||||||
if (responseJSON.success == 0) {
|
if (responseJSON.success == 0) {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
export const BASE_URL = "https://www.classcharts.com";
|
export const BASE_URL = "https://www.classcharts.com";
|
||||||
export const API_BASE_STUDENT = `${BASE_URL}/apiv2student`;
|
export const API_BASE_STUDENT = `${BASE_URL}/apiv2student`;
|
||||||
export const API_BASE_PARENT = `${BASE_URL}/apiv2parent`;
|
export const API_BASE_PARENT = `${BASE_URL}/apiv2parent`;
|
||||||
|
|
||||||
|
export const PING_INTERVAL = 180 * 1000; // 3 minutes
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,6 @@ export class ClasschartsParentClient extends ClasschartsClient {
|
||||||
this.pupils = await this.getPupils();
|
this.pupils = await this.getPupils();
|
||||||
if (!this.pupils) throw new Error("Account has no pupils attached");
|
if (!this.pupils) throw new Error("Account has no pupils attached");
|
||||||
this.studentId = this.pupils[0].id;
|
this.studentId = this.pupils[0].id;
|
||||||
this.studentName = this.pupils[0].name;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Get Pupil details
|
* Get Pupil details
|
||||||
|
|
@ -83,7 +82,6 @@ export class ClasschartsParentClient extends ClasschartsClient {
|
||||||
const pupil = pupils[i];
|
const pupil = pupils[i];
|
||||||
if (pupil.id == pupilId) {
|
if (pupil.id == pupilId) {
|
||||||
this.studentId = pupil.id;
|
this.studentId = pupil.id;
|
||||||
this.studentName = pupil.name;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,22 +55,8 @@ export class ClasschartsStudentClient extends ClasschartsClient {
|
||||||
String(sessionCookies["student_session_credentials"])
|
String(sessionCookies["student_session_credentials"])
|
||||||
);
|
);
|
||||||
this.sessionId = sessionID.session_id;
|
this.sessionId = sessionID.session_id;
|
||||||
|
await this.getNewSessionId();
|
||||||
const user = await this.getStudentInfo();
|
const user = await this.getStudentInfo();
|
||||||
this.studentId = user.id;
|
this.studentId = user.id;
|
||||||
this.studentName = user.name;
|
|
||||||
const pingFormData = new URLSearchParams();
|
|
||||||
pingFormData.append("include_data", "true");
|
|
||||||
const pingData = await this.makeAuthedRequest(
|
|
||||||
this.API_BASE + "/ping",
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
data: pingFormData.toString(),
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ includeMeta: true }
|
|
||||||
);
|
|
||||||
this.sessionId = pingData.meta.session_id;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue