import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { environment } from 'src/environments/environment'; import { sha256 } from 'sha.js'; import { Router } from '@angular/router'; import { AlertService } from '../alert/alert.service'; class Answer { success: Boolean = false } class PresaltAnswer extends Answer { presalt: string = '' } class AuthenticateAnswer extends Answer { token: string = '' } class CheckTokenAnswer extends Answer { valid: Boolean = false } class TokenData { iss: string = '' dat: string = '' typ: string = '' usr: string = '' admin: number = 0 } @Injectable({ providedIn: 'root' }) export class AccountService { public username = '?' public isAdmin = false private callbacks: Function[] = [] subscribe(f: Function) { this.callbacks.push(f) } constructor(private http: HttpClient, private router: Router, private alert: AlertService) { this.updateUserInfo() } getPresalt(then: Function, onFail: Function = () => {}, onConnectionError: Function = () => {}, username: string = this.username) { this.http.post(`${environment.apiURL}/users/presalt`, {username}) .subscribe((answer: Object) => { var presaltAnswer = Object.assign(new PresaltAnswer(), answer) if (!presaltAnswer.success) { onFail() return } then(presaltAnswer.presalt) }, () => { onConnectionError() }) } public login(username: string, password: string, onFail: Function, onConnectionError: Function) { this.setUser('') localStorage.removeItem('userToken') this.getPresalt((presalt: string) => { var passwordHash = new sha256().update(password + presalt).digest('hex') this.http.post(`${environment.apiURL}/users/authenticate`, {username, passwordHash}) .subscribe((answer) => { var authenticateAnswer = Object.assign(new AuthenticateAnswer(), answer) var loginSuccess = authenticateAnswer.success == true && authenticateAnswer.token.length > 0 if (loginSuccess) { localStorage.setItem('userToken', authenticateAnswer.token) this.setUser(username) this.updateUserInfo() this.router.navigate(['admin']) } else { onFail() } }, () => {onConnectionError()}) }, onFail, onConnectionError, username) } updateUserInfo(then: Function = () => {}) { var token = localStorage.getItem('userToken') if (token == null) { this.logout() return } var data = JSON.parse(atob(token?.split('.')[1] as string)) var tokenData = Object.assign(new TokenData(), data) this.setUser(tokenData.usr) this.isAdmin = tokenData.admin == 1 this.http.post(`${environment.apiURL}/users/checkToken`, {token, username: this.username}) .subscribe((answer: Object) => { var checkTokenAnswer = Object.assign(new CheckTokenAnswer(), answer) if (checkTokenAnswer.valid) { } else { this.logout() } then() }, () => { this.logout() }) } logout() { this.setUser('') localStorage.removeItem('userToken') } changePassword(newPassword: string, then: Function, onConnectionError: Function) { this.getPresalt((presalt: string) => { var passwordHash = new sha256().update(newPassword + presalt).digest('hex') this.http.post(`${environment.apiURL}/users/changePassword`, {username: this.username, passwordHash, token: localStorage.getItem('userToken')}).subscribe((answer) => { var status = Object.assign(new Answer(), answer) if (status.success) { this.alert.alert('Password changed!', 'Watch out, \nyour old password won\'t work anymore') } else { this.logout() this.alert.alert('Error!', 'Something went wrong, bad user token?') } then() }) }, onConnectionError = onConnectionError) // if you get a on Error, you have done something wrong } setUser(username: string) { if (username == this.username) { return } this.username = username this.callbacks.forEach(f => { f(this.username) }); } postStatus(status: string, time: number) { this.http.post(`${environment.apiURL}/users/postStatus`, {username: this.username, status, lifetime: time, token: localStorage.getItem('userToken')}).subscribe((answer) => { var status = Object.assign(new Answer(), answer) if (status.success) { this.alert.alert('Success', 'You posted a new status.\nEveryone can see it now!') } else { this.alert.alert('Error!', 'Something went wrong, bad user token?') } }) } updateQuote(quote: string) { this.http.post(`${environment.apiURL}/users/updateQuote`, {username: this.username, quote, token: localStorage.getItem('userToken')}).subscribe((answer) => { var status = Object.assign(new Answer(), answer) if (status.success) { this.alert.alert('You updated your quote', 'Everyone can see it') } else { this.alert.alert('Error!', 'Something went wrong, bad user token?') } }) } }