fix: 🐛 Adjusted cookie handling (#79)

This commit is contained in:
Johan Öbrink 2021-03-11 17:27:26 +01:00 committed by GitHub
parent c62dab9e2e
commit 16020a3d3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 52 deletions

View File

@ -49,32 +49,42 @@ export class Api extends EventEmitter {
this.headers = {}
}
getPersonalNumber() {
public getPersonalNumber(): string | undefined {
return this.personalNumber
}
async getSession(url: string, options: RequestInit = {}): Promise<RequestInit> {
const cookie = await this.cookieManager.getCookieString(url)
private getRequestInit(options: RequestInit = {}): RequestInit {
return {
...options,
headers: {
...this.headers,
...options.headers,
},
}
}
public async getSession(url: string, options?: RequestInit): Promise<RequestInit> {
const init = this.getRequestInit(options)
const cookie = await this.cookieManager.getCookieString(url)
return {
...init,
headers: {
...init.headers,
cookie,
},
}
}
async clearSession(): Promise<void> {
private async clearSession(): Promise<void> {
this.headers = {}
await this.cookieManager.clearAll()
}
addHeader(name: string, value: string): void {
private addHeader(name: string, value: string): void {
this.headers[name] = value
}
async login(personalNumber: string): Promise<LoginStatusChecker> {
public async login(personalNumber: string): Promise<LoginStatusChecker> {
if (personalNumber.endsWith('1212121212')) return this.fakeMode()
this.isFake = false
@ -105,14 +115,14 @@ export class Api extends EventEmitter {
return status
}
async retrieveSessionCookie(): Promise<void> {
private async retrieveSessionCookie(): Promise<void> {
const url = routes.loginCookie
await this.fetch('login-cookie', url)
}
async retrieveXsrfToken(): Promise<void> {
private async retrieveXsrfToken(): Promise<void> {
const url = routes.hemPage
const session = await this.getSession(url)
const session = this.getRequestInit()
const response = await this.fetch('hemPage', url, session)
const text = await response.text()
const doc = html.parse(decode(text))
@ -120,9 +130,9 @@ export class Api extends EventEmitter {
this.addHeader('X-XSRF-Token', xsrfToken)
}
async retrieveApiKey(): Promise<void> {
private async retrieveApiKey(): Promise<void> {
const url = routes.startBundle
const session = await this.getSession(url)
const session = this.getRequestInit()
const response = await this.fetch('startBundle', url, session)
const text = await response.text()
@ -133,29 +143,27 @@ export class Api extends EventEmitter {
this.addHeader('API-Key', apiKey)
}
async retrieveCdnUrl(): Promise<string> {
private async retrieveCdnUrl(): Promise<string> {
const url = routes.cdn
const session = await this.getSession(url)
const session = this.getRequestInit()
const response = await this.fetch('cdn', url, session)
const cdnUrl = await response.text()
return cdnUrl
}
async retrieveAuthBody(): Promise<string> {
private async retrieveAuthBody(): Promise<string> {
const url = routes.auth
const session = await this.getSession(url)
const session = this.getRequestInit()
const response = await this.fetch('auth', url, session)
const authBody = await response.text()
return authBody
}
async retrieveAuthToken(url: string, authBody: string): Promise<string> {
const cdnHost = new URL(url).host
const session = await this.getSession(url, {
private async retrieveAuthToken(url: string, authBody: string): Promise<string> {
const session = this.getRequestInit({
method: 'POST',
headers: {
Accept: 'text/plain',
Host: cdnHost,
Origin: 'https://etjanst.stockholm.se',
Referer: 'https://etjanst.stockholm.se/',
Connection: 'keep-alive',
@ -163,15 +171,14 @@ export class Api extends EventEmitter {
body: authBody,
})
// Delete cookies from session and empty cookie manager
delete session.headers.cookie
// Temporarily remove cookies
const cookies = await this.cookieManager.getCookies(url)
this.cookieManager.clearAll()
// Perform request
const response = await this.fetch('createItem', url, session)
// Refill cookie manager
// Restore cookies
cookies.forEach((cookie) => {
this.cookieManager.setCookie(cookie, url)
})
@ -184,7 +191,7 @@ export class Api extends EventEmitter {
return authData.token
}
async fakeMode(): Promise<LoginStatusChecker> {
private async fakeMode(): Promise<LoginStatusChecker> {
this.isFake = true
setTimeout(() => {
@ -197,17 +204,17 @@ export class Api extends EventEmitter {
return emitter
}
async getUser(): Promise<User> {
public async getUser(): Promise<User> {
if (this.isFake) return fakeResponse(fake.user())
const url = routes.user
const session = await this.getSession(url)
const session = this.getRequestInit()
const response = await this.fetch('user', url, session)
const data = await response.json()
return parse.user(data)
}
async getChildren(): Promise<Child[]> {
public async getChildren(): Promise<Child[]> {
if (this.isFake) return fakeResponse(fake.children())
const cdnUrl = await this.retrieveCdnUrl()
@ -215,7 +222,7 @@ export class Api extends EventEmitter {
const token = await this.retrieveAuthToken(cdnUrl, authBody)
const url = routes.children
const session = await this.getSession(url, {
const session = this.getRequestInit({
headers: {
Accept: 'application/json;odata=verbose',
Auth: token,
@ -225,8 +232,6 @@ export class Api extends EventEmitter {
})
const response = await this.fetch('children', url, session)
console.log(session.headers)
console.log('children response', response)
if (!response.ok) {
throw new Error(`Server Error [${response.status}] [${response.statusText}] [${url}]`)
}
@ -235,78 +240,78 @@ export class Api extends EventEmitter {
return parse.children(data)
}
async getCalendar(child: Child): Promise<CalendarItem[]> {
public async getCalendar(child: Child): Promise<CalendarItem[]> {
if (this.isFake) return fakeResponse(fake.calendar(child))
const url = routes.calendar(child.id)
const session = await this.getSession(url)
const session = this.getRequestInit()
const response = await this.fetch('calendar', url, session)
const data = await response.json()
return parse.calendar(data)
}
async getClassmates(child: Child): Promise<Classmate[]> {
public async getClassmates(child: Child): Promise<Classmate[]> {
if (this.isFake) return fakeResponse(fake.classmates(child))
const url = routes.classmates(child.sdsId)
const session = await this.getSession(url)
const session = this.getRequestInit()
const response = await this.fetch('classmates', url, session)
const data = await response.json()
return parse.classmates(data)
}
async getSchedule(child: Child, from: DateTime, to: DateTime): Promise<ScheduleItem[]> {
public async getSchedule(child: Child, from: DateTime, to: DateTime): Promise<ScheduleItem[]> {
if (this.isFake) return fakeResponse(fake.schedule(child))
const url = routes.schedule(child.sdsId, from.toISODate(), to.toISODate())
const session = await this.getSession(url)
const session = this.getRequestInit()
const response = await this.fetch('schedule', url, session)
const data = await response.json()
return parse.schedule(data)
}
async getNews(child: Child): Promise<NewsItem[]> {
public async getNews(child: Child): Promise<NewsItem[]> {
if (this.isFake) return fakeResponse(fake.news(child))
const url = routes.news(child.id)
const session = await this.getSession(url)
const session = this.getRequestInit()
const response = await this.fetch('news', url, session)
const data = await response.json()
return parse.news(data)
}
async getNewsDetails(child: Child, item: NewsItem): Promise<any> {
public async getNewsDetails(child: Child, item: NewsItem): Promise<any> {
if (this.isFake) {
return fakeResponse(fake.news(child).find((ni) => ni.id === item.id))
}
const url = routes.newsDetails(child.id, item.id)
const session = await this.getSession(url)
const session = this.getRequestInit()
const response = await this.fetch(`news_${item.id}`, url, session)
const data = await response.json()
return parse.newsItemDetails(data)
}
async getMenu(child: Child): Promise<MenuItem[]> {
public async getMenu(child: Child): Promise<MenuItem[]> {
if (this.isFake) return fakeResponse(fake.menu(child))
const url = routes.menu(child.id)
const session = await this.getSession(url)
const session = this.getRequestInit()
const response = await this.fetch('menu', url, session)
const data = await response.json()
return parse.menu(data)
}
async getNotifications(child: Child): Promise<Notification[]> {
public async getNotifications(child: Child): Promise<Notification[]> {
if (this.isFake) return fakeResponse(fake.notifications(child))
const url = routes.notifications(child.sdsId)
const session = await this.getSession(url)
const session = this.getRequestInit()
const response = await this.fetch('notifications', url, session)
const data = await response.json()
return parse.notifications(data)
}
async logout() {
public async logout() {
this.isFake = false
this.personalNumber = undefined
this.isLoggedIn = false

16
run.js
View File

@ -91,14 +91,14 @@ async function run() {
api.on('login', async () => {
console.log('Logged in')
console.log('user')
const user = await api.getUser()
console.log(user)
// console.log('user')
// const user = await api.getUser()
// console.log(user)
console.log('children')
const children = await api.getChildren()
console.log(children)
/*
console.log('calendar')
const calendar = await api.getCalendar(children[0])
console.log(calendar)
@ -113,7 +113,7 @@ async function run() {
console.log('news')
const news = await api.getNews(children[0])
*/
/*console.log('news details')
const newsItems = await Promise.all(
news.map((newsItem) =>
@ -127,9 +127,9 @@ async function run() {
const menu = await api.getMenu(children[0])
console.log(menu)*/
console.log('notifications')
const notifications = await api.getNotifications(children[0])
console.log(notifications)
// console.log('notifications')
// const notifications = await api.getNotifications(children[0])
// console.log(notifications)
await api.logout()
})