fix: 🐛 Adjusted cookie handling (#79)
This commit is contained in:
parent
c62dab9e2e
commit
16020a3d3c
93
lib/api.ts
93
lib/api.ts
|
@ -49,32 +49,42 @@ export class Api extends EventEmitter {
|
||||||
this.headers = {}
|
this.headers = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
getPersonalNumber() {
|
public getPersonalNumber(): string | undefined {
|
||||||
return this.personalNumber
|
return this.personalNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSession(url: string, options: RequestInit = {}): Promise<RequestInit> {
|
private getRequestInit(options: RequestInit = {}): RequestInit {
|
||||||
const cookie = await this.cookieManager.getCookieString(url)
|
|
||||||
return {
|
return {
|
||||||
...options,
|
...options,
|
||||||
headers: {
|
headers: {
|
||||||
...this.headers,
|
...this.headers,
|
||||||
...options.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,
|
cookie,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async clearSession(): Promise<void> {
|
private async clearSession(): Promise<void> {
|
||||||
this.headers = {}
|
this.headers = {}
|
||||||
await this.cookieManager.clearAll()
|
await this.cookieManager.clearAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
addHeader(name: string, value: string): void {
|
private addHeader(name: string, value: string): void {
|
||||||
this.headers[name] = value
|
this.headers[name] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
async login(personalNumber: string): Promise<LoginStatusChecker> {
|
public async login(personalNumber: string): Promise<LoginStatusChecker> {
|
||||||
if (personalNumber.endsWith('1212121212')) return this.fakeMode()
|
if (personalNumber.endsWith('1212121212')) return this.fakeMode()
|
||||||
|
|
||||||
this.isFake = false
|
this.isFake = false
|
||||||
|
@ -105,14 +115,14 @@ export class Api extends EventEmitter {
|
||||||
return status
|
return status
|
||||||
}
|
}
|
||||||
|
|
||||||
async retrieveSessionCookie(): Promise<void> {
|
private async retrieveSessionCookie(): Promise<void> {
|
||||||
const url = routes.loginCookie
|
const url = routes.loginCookie
|
||||||
await this.fetch('login-cookie', url)
|
await this.fetch('login-cookie', url)
|
||||||
}
|
}
|
||||||
|
|
||||||
async retrieveXsrfToken(): Promise<void> {
|
private async retrieveXsrfToken(): Promise<void> {
|
||||||
const url = routes.hemPage
|
const url = routes.hemPage
|
||||||
const session = await this.getSession(url)
|
const session = this.getRequestInit()
|
||||||
const response = await this.fetch('hemPage', url, session)
|
const response = await this.fetch('hemPage', url, session)
|
||||||
const text = await response.text()
|
const text = await response.text()
|
||||||
const doc = html.parse(decode(text))
|
const doc = html.parse(decode(text))
|
||||||
|
@ -120,9 +130,9 @@ export class Api extends EventEmitter {
|
||||||
this.addHeader('X-XSRF-Token', xsrfToken)
|
this.addHeader('X-XSRF-Token', xsrfToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
async retrieveApiKey(): Promise<void> {
|
private async retrieveApiKey(): Promise<void> {
|
||||||
const url = routes.startBundle
|
const url = routes.startBundle
|
||||||
const session = await this.getSession(url)
|
const session = this.getRequestInit()
|
||||||
const response = await this.fetch('startBundle', url, session)
|
const response = await this.fetch('startBundle', url, session)
|
||||||
const text = await response.text()
|
const text = await response.text()
|
||||||
|
|
||||||
|
@ -133,29 +143,27 @@ export class Api extends EventEmitter {
|
||||||
this.addHeader('API-Key', apiKey)
|
this.addHeader('API-Key', apiKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
async retrieveCdnUrl(): Promise<string> {
|
private async retrieveCdnUrl(): Promise<string> {
|
||||||
const url = routes.cdn
|
const url = routes.cdn
|
||||||
const session = await this.getSession(url)
|
const session = this.getRequestInit()
|
||||||
const response = await this.fetch('cdn', url, session)
|
const response = await this.fetch('cdn', url, session)
|
||||||
const cdnUrl = await response.text()
|
const cdnUrl = await response.text()
|
||||||
return cdnUrl
|
return cdnUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
async retrieveAuthBody(): Promise<string> {
|
private async retrieveAuthBody(): Promise<string> {
|
||||||
const url = routes.auth
|
const url = routes.auth
|
||||||
const session = await this.getSession(url)
|
const session = this.getRequestInit()
|
||||||
const response = await this.fetch('auth', url, session)
|
const response = await this.fetch('auth', url, session)
|
||||||
const authBody = await response.text()
|
const authBody = await response.text()
|
||||||
return authBody
|
return authBody
|
||||||
}
|
}
|
||||||
|
|
||||||
async retrieveAuthToken(url: string, authBody: string): Promise<string> {
|
private async retrieveAuthToken(url: string, authBody: string): Promise<string> {
|
||||||
const cdnHost = new URL(url).host
|
const session = this.getRequestInit({
|
||||||
const session = await this.getSession(url, {
|
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'text/plain',
|
Accept: 'text/plain',
|
||||||
Host: cdnHost,
|
|
||||||
Origin: 'https://etjanst.stockholm.se',
|
Origin: 'https://etjanst.stockholm.se',
|
||||||
Referer: 'https://etjanst.stockholm.se/',
|
Referer: 'https://etjanst.stockholm.se/',
|
||||||
Connection: 'keep-alive',
|
Connection: 'keep-alive',
|
||||||
|
@ -163,15 +171,14 @@ export class Api extends EventEmitter {
|
||||||
body: authBody,
|
body: authBody,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Delete cookies from session and empty cookie manager
|
// Temporarily remove cookies
|
||||||
delete session.headers.cookie
|
|
||||||
const cookies = await this.cookieManager.getCookies(url)
|
const cookies = await this.cookieManager.getCookies(url)
|
||||||
this.cookieManager.clearAll()
|
this.cookieManager.clearAll()
|
||||||
|
|
||||||
// Perform request
|
// Perform request
|
||||||
const response = await this.fetch('createItem', url, session)
|
const response = await this.fetch('createItem', url, session)
|
||||||
|
|
||||||
// Refill cookie manager
|
// Restore cookies
|
||||||
cookies.forEach((cookie) => {
|
cookies.forEach((cookie) => {
|
||||||
this.cookieManager.setCookie(cookie, url)
|
this.cookieManager.setCookie(cookie, url)
|
||||||
})
|
})
|
||||||
|
@ -184,7 +191,7 @@ export class Api extends EventEmitter {
|
||||||
return authData.token
|
return authData.token
|
||||||
}
|
}
|
||||||
|
|
||||||
async fakeMode(): Promise<LoginStatusChecker> {
|
private async fakeMode(): Promise<LoginStatusChecker> {
|
||||||
this.isFake = true
|
this.isFake = true
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -197,17 +204,17 @@ export class Api extends EventEmitter {
|
||||||
return emitter
|
return emitter
|
||||||
}
|
}
|
||||||
|
|
||||||
async getUser(): Promise<User> {
|
public async getUser(): Promise<User> {
|
||||||
if (this.isFake) return fakeResponse(fake.user())
|
if (this.isFake) return fakeResponse(fake.user())
|
||||||
|
|
||||||
const url = routes.user
|
const url = routes.user
|
||||||
const session = await this.getSession(url)
|
const session = this.getRequestInit()
|
||||||
const response = await this.fetch('user', url, session)
|
const response = await this.fetch('user', url, session)
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
return parse.user(data)
|
return parse.user(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(): Promise<Child[]> {
|
public async getChildren(): Promise<Child[]> {
|
||||||
if (this.isFake) return fakeResponse(fake.children())
|
if (this.isFake) return fakeResponse(fake.children())
|
||||||
|
|
||||||
const cdnUrl = await this.retrieveCdnUrl()
|
const cdnUrl = await this.retrieveCdnUrl()
|
||||||
|
@ -215,7 +222,7 @@ export class Api extends EventEmitter {
|
||||||
const token = await this.retrieveAuthToken(cdnUrl, authBody)
|
const token = await this.retrieveAuthToken(cdnUrl, authBody)
|
||||||
|
|
||||||
const url = routes.children
|
const url = routes.children
|
||||||
const session = await this.getSession(url, {
|
const session = this.getRequestInit({
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json;odata=verbose',
|
Accept: 'application/json;odata=verbose',
|
||||||
Auth: token,
|
Auth: token,
|
||||||
|
@ -225,8 +232,6 @@ export class Api extends EventEmitter {
|
||||||
})
|
})
|
||||||
const response = await this.fetch('children', url, session)
|
const response = await this.fetch('children', url, session)
|
||||||
|
|
||||||
console.log(session.headers)
|
|
||||||
console.log('children response', response)
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`Server Error [${response.status}] [${response.statusText}] [${url}]`)
|
throw new Error(`Server Error [${response.status}] [${response.statusText}] [${url}]`)
|
||||||
}
|
}
|
||||||
|
@ -235,78 +240,78 @@ export class Api extends EventEmitter {
|
||||||
return parse.children(data)
|
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))
|
if (this.isFake) return fakeResponse(fake.calendar(child))
|
||||||
|
|
||||||
const url = routes.calendar(child.id)
|
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 response = await this.fetch('calendar', url, session)
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
return parse.calendar(data)
|
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))
|
if (this.isFake) return fakeResponse(fake.classmates(child))
|
||||||
|
|
||||||
const url = routes.classmates(child.sdsId)
|
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 response = await this.fetch('classmates', url, session)
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
return parse.classmates(data)
|
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))
|
if (this.isFake) return fakeResponse(fake.schedule(child))
|
||||||
|
|
||||||
const url = routes.schedule(child.sdsId, from.toISODate(), to.toISODate())
|
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 response = await this.fetch('schedule', url, session)
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
return parse.schedule(data)
|
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))
|
if (this.isFake) return fakeResponse(fake.news(child))
|
||||||
|
|
||||||
const url = routes.news(child.id)
|
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 response = await this.fetch('news', url, session)
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
return parse.news(data)
|
return parse.news(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getNewsDetails(child: Child, item: NewsItem): Promise<any> {
|
public async getNewsDetails(child: Child, item: NewsItem): Promise<any> {
|
||||||
if (this.isFake) {
|
if (this.isFake) {
|
||||||
return fakeResponse(fake.news(child).find((ni) => ni.id === item.id))
|
return fakeResponse(fake.news(child).find((ni) => ni.id === item.id))
|
||||||
}
|
}
|
||||||
const url = routes.newsDetails(child.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 response = await this.fetch(`news_${item.id}`, url, session)
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
return parse.newsItemDetails(data)
|
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))
|
if (this.isFake) return fakeResponse(fake.menu(child))
|
||||||
|
|
||||||
const url = routes.menu(child.id)
|
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 response = await this.fetch('menu', url, session)
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
return parse.menu(data)
|
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))
|
if (this.isFake) return fakeResponse(fake.notifications(child))
|
||||||
|
|
||||||
const url = routes.notifications(child.sdsId)
|
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 response = await this.fetch('notifications', url, session)
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
return parse.notifications(data)
|
return parse.notifications(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
async logout() {
|
public async logout() {
|
||||||
this.isFake = false
|
this.isFake = false
|
||||||
this.personalNumber = undefined
|
this.personalNumber = undefined
|
||||||
this.isLoggedIn = false
|
this.isLoggedIn = false
|
||||||
|
|
16
run.js
16
run.js
|
@ -91,14 +91,14 @@ async function run() {
|
||||||
api.on('login', async () => {
|
api.on('login', async () => {
|
||||||
console.log('Logged in')
|
console.log('Logged in')
|
||||||
|
|
||||||
console.log('user')
|
// console.log('user')
|
||||||
const user = await api.getUser()
|
// const user = await api.getUser()
|
||||||
console.log(user)
|
// console.log(user)
|
||||||
|
|
||||||
console.log('children')
|
console.log('children')
|
||||||
const children = await api.getChildren()
|
const children = await api.getChildren()
|
||||||
console.log(children)
|
console.log(children)
|
||||||
|
/*
|
||||||
console.log('calendar')
|
console.log('calendar')
|
||||||
const calendar = await api.getCalendar(children[0])
|
const calendar = await api.getCalendar(children[0])
|
||||||
console.log(calendar)
|
console.log(calendar)
|
||||||
|
@ -113,7 +113,7 @@ async function run() {
|
||||||
|
|
||||||
console.log('news')
|
console.log('news')
|
||||||
const news = await api.getNews(children[0])
|
const news = await api.getNews(children[0])
|
||||||
|
*/
|
||||||
/*console.log('news details')
|
/*console.log('news details')
|
||||||
const newsItems = await Promise.all(
|
const newsItems = await Promise.all(
|
||||||
news.map((newsItem) =>
|
news.map((newsItem) =>
|
||||||
|
@ -127,9 +127,9 @@ async function run() {
|
||||||
const menu = await api.getMenu(children[0])
|
const menu = await api.getMenu(children[0])
|
||||||
console.log(menu)*/
|
console.log(menu)*/
|
||||||
|
|
||||||
console.log('notifications')
|
// console.log('notifications')
|
||||||
const notifications = await api.getNotifications(children[0])
|
// const notifications = await api.getNotifications(children[0])
|
||||||
console.log(notifications)
|
// console.log(notifications)
|
||||||
|
|
||||||
await api.logout()
|
await api.logout()
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue