-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15 from bodhivb/development
Development
- Loading branch information
Showing
36 changed files
with
663 additions
and
151 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { IXeduleAppointment } from "../interfaces/xedule/xeduleAppointment"; | ||
import { XeduleApi } from "./xeduleApi"; | ||
|
||
export class AppointmentApi extends XeduleApi<IXeduleAppointment> { | ||
constructor() { | ||
super("Appointment/Date/"); | ||
} | ||
|
||
/** | ||
* Get the appointment for the current week with selected attendee | ||
* @returns | ||
*/ | ||
public async getAppointment(...attendeeIds: number[]): Promise<any[]> { | ||
// Week date | ||
const today = new Date(); | ||
const nextWeek = new Date( | ||
today.getFullYear(), | ||
today.getMonth(), | ||
today.getDate() + 7 | ||
); | ||
|
||
return super.get( | ||
this.dateToPath(today) + | ||
"/" + | ||
this.dateToPath(nextWeek) + | ||
"/Attendee?id=" + | ||
attendeeIds.join("&id=") | ||
); | ||
} | ||
|
||
/** | ||
* Convert date to xedule path format | ||
* @param date | ||
* @returns | ||
*/ | ||
public dateToPath(date: Date) { | ||
const day = date.getDate(); | ||
const month = date.getMonth() + 1; // January is 0 | ||
const year = date.getFullYear(); | ||
|
||
return `${year}-${month}-${day}`; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios"; | ||
|
||
interface ForwardResponse { | ||
errorText: string; | ||
forwardCount: number; | ||
lastResponse: AxiosResponse; | ||
} | ||
|
||
interface LoginData { | ||
username: string; | ||
password: string; | ||
} | ||
|
||
interface AuthenticationResponse { | ||
isSuccess: boolean; | ||
errorMessage?: string; | ||
token?: string; | ||
} | ||
|
||
export class AuthenticationApi { | ||
private httpService: AxiosInstance; | ||
private readonly authenticationUrl: string = | ||
"https://myx-silu.xedule.nl/Authentication/sso/SSOLogin.aspx?ngsw-bypass=true"; | ||
|
||
constructor() { | ||
this.httpService = axios.create({ withCredentials: true }); | ||
} | ||
|
||
public async checkAuthStatus() { | ||
return this.httpService.get(this.authenticationUrl); | ||
} | ||
|
||
/** | ||
* Authenticated via SURFConext authentication and return token | ||
* @param body login data | ||
* @returns response result status with token | ||
*/ | ||
public async authentication( | ||
body: LoginData | ||
): Promise<AuthenticationResponse> { | ||
// Setup first request | ||
const firstRequest: AxiosRequestConfig = { | ||
method: "get", | ||
url: this.authenticationUrl, | ||
}; | ||
|
||
// Forward the request | ||
const { errorText, lastResponse } = await this.createForwardRequest( | ||
this.httpService, | ||
firstRequest, | ||
5, | ||
body | ||
); | ||
|
||
// Error handling | ||
if (errorText) { | ||
return { isSuccess: false, errorMessage: errorText }; | ||
} | ||
// Error handling | ||
if (!lastResponse.config.url?.includes("sso.xedule.nl")) { | ||
return { isSuccess: false, errorMessage: "Result is different" }; | ||
} | ||
|
||
// Get the token | ||
let token: string = ( | ||
lastResponse.request.path ?? lastResponse.request.responseURL | ||
).toString(); | ||
|
||
if (token) { | ||
if (token.includes("token=")) { | ||
token = token.substring(token.indexOf("token=") + "token=".length); | ||
} | ||
|
||
if (token.includes("&ngsw-bypass=")) { | ||
token = token.substring(0, token.indexOf("&ngsw-bypass=")); | ||
} | ||
|
||
// Return token | ||
return { isSuccess: true, token }; | ||
} | ||
|
||
return { | ||
isSuccess: false, | ||
errorMessage: "This application is out of date", | ||
}; | ||
} | ||
|
||
/** | ||
* createForwardRequest will be forwarded automatically if there is submit form in response | ||
* @param axiosInstance | ||
* @param firstRequest | ||
* @param maxForwards | ||
* @param loginData | ||
* @returns The last response | ||
*/ | ||
async createForwardRequest( | ||
axiosInstance: AxiosInstance, | ||
firstRequest: AxiosRequestConfig, | ||
maxForwards: number = 5, | ||
loginData: { username: string; password: string } | ||
): Promise<ForwardResponse> { | ||
let errorText = ""; | ||
let forwardCount = 0; | ||
let lastResponse = await axiosInstance.request(firstRequest); | ||
const dom = new DOMParser(); | ||
|
||
for (; forwardCount < maxForwards; forwardCount++) { | ||
const document = dom.parseFromString(lastResponse.data, "text/html"); | ||
const forwardForm = document.querySelector("form"); | ||
|
||
// Stop forward if response has no form | ||
if (!forwardForm) { | ||
break; | ||
} | ||
|
||
// Stop forward if there are errors | ||
const errorElement = document.getElementById("errorText"); | ||
if (errorElement && errorElement.innerHTML) { | ||
errorText = errorElement.innerHTML; | ||
break; | ||
} | ||
|
||
// Create a new config request | ||
const config: AxiosRequestConfig<any> = {}; | ||
config.url = forwardForm.action; | ||
config.method = forwardForm.method ?? "post"; | ||
config.data = {}; | ||
|
||
// Copy the form data into a new request | ||
const inputs = forwardForm.querySelectorAll("input"); | ||
inputs.forEach((input) => (config.data[input.name] = input.value)); | ||
|
||
// Login page | ||
if (lastResponse.data.includes("FormsAuthentication")) { | ||
// Fill the username and password in | ||
config.data["UserName"] = loginData.username; | ||
config.data["Password"] = loginData.password; | ||
|
||
if (config.url.startsWith(window.location.origin)) { | ||
// Remove the origin from the url | ||
config.url = config.url.substring(window.location.origin.length); | ||
} | ||
|
||
if (!config.url.startsWith("http")) { | ||
// Fix the url with domain name | ||
config.url = "https://adfsproxy.sintlucas.nl:443" + config.url; | ||
} | ||
} | ||
|
||
// Stop forward if a new request is same as previous | ||
if (lastResponse.config.url == config.url) { | ||
errorText = "The request has been black holed."; | ||
break; | ||
} | ||
|
||
// Convert json object to http query string | ||
config.data = new URLSearchParams(config.data); | ||
lastResponse = await axiosInstance.request(config); | ||
} | ||
|
||
return { errorText, forwardCount, lastResponse }; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { IXeduleClassroom } from "../interfaces/xedule/xeduleClassroom"; | ||
import { XeduleApi } from "./xeduleApi"; | ||
|
||
export class ClassroomApi extends XeduleApi<IXeduleClassroom> { | ||
constructor() { | ||
super("Attendee/Type/Classroom"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { IXeduleTeacher } from "../interfaces/xedule/xeduleTeacher"; | ||
import { XeduleApi } from "./xeduleApi"; | ||
|
||
export class TeacherApi extends XeduleApi<IXeduleTeacher> { | ||
constructor() { | ||
super("Attendee/Type/Teacher"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import axios from "axios"; | ||
|
||
export class XeduleApi<T = any> { | ||
private baseUrl: string = "https://myx-silu.xedule.nl/api/"; | ||
private basePath: string; | ||
|
||
public data: T[] = []; | ||
|
||
/** | ||
* Abstract class | ||
* @param basePath The path to the api endpoint | ||
*/ | ||
constructor(basePath: string) { | ||
this.basePath = basePath; | ||
} | ||
|
||
/** | ||
* Get the data from the xedule api | ||
* @param path URL parameters to add to the base path | ||
* @returns | ||
*/ | ||
public async get(path: string = ""): Promise<T[]> { | ||
const res = await axios.get(this.baseUrl + this.basePath + path, { | ||
headers: { Authorization: "Bearer " + localStorage.getItem("token") }, | ||
}); | ||
|
||
if (res.status == 200 && res.data.result && res.data.result.length > 0) { | ||
this.data = res.data.result; | ||
} else { | ||
//TODO error handling | ||
} | ||
|
||
return this.data; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.