diff --git a/src/app/account.service.spec.ts b/src/app/account.service.spec.ts deleted file mode 100644 index 2ffad6f..0000000 --- a/src/app/account.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { AccountService } from './account.service'; - -describe('AccountService', () => { - let service: AccountService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(AccountService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/account.service.spec.ts b/src/app/account.service.spec.ts deleted file mode 100644 index 2ffad6f..0000000 --- a/src/app/account.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { AccountService } from './account.service'; - -describe('AccountService', () => { - let service: AccountService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(AccountService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/account.service.ts b/src/app/account.service.ts deleted file mode 100644 index e0690a2..0000000 --- a/src/app/account.service.ts +++ /dev/null @@ -1,163 +0,0 @@ -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 Swal from 'sweetalert2'; - -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) { - 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) { - Swal.fire('Password changed!', 'Watch out, \nyour old password won\'t work anymore', 'success') - } else { - this.logout() - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - 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) { - Swal.fire('You posted a status', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } - - 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) { - Swal.fire('You updated your quote', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } -} diff --git a/src/app/account.service.spec.ts b/src/app/account.service.spec.ts deleted file mode 100644 index 2ffad6f..0000000 --- a/src/app/account.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { AccountService } from './account.service'; - -describe('AccountService', () => { - let service: AccountService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(AccountService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/account.service.ts b/src/app/account.service.ts deleted file mode 100644 index e0690a2..0000000 --- a/src/app/account.service.ts +++ /dev/null @@ -1,163 +0,0 @@ -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 Swal from 'sweetalert2'; - -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) { - 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) { - Swal.fire('Password changed!', 'Watch out, \nyour old password won\'t work anymore', 'success') - } else { - this.logout() - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - 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) { - Swal.fire('You posted a status', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } - - 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) { - Swal.fire('You updated your quote', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } -} diff --git a/src/app/admin/admin.component.ts b/src/app/admin/admin.component.ts index 4b518fa..8e5dd3c 100644 --- a/src/app/admin/admin.component.ts +++ b/src/app/admin/admin.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; -import { AccountService } from '../account.service'; +import { AccountService } from '../login/account.service'; interface TimeEntry { value: number @@ -70,6 +70,8 @@ return } this.account.postStatus(this.statusForm.controls['status'].value, this.statusForm.controls['time'].value) + this.statusForm.reset() + this.statusForm.get('time')?.setValue(60) } onQuoteSubmit() { @@ -77,5 +79,6 @@ return } this.account.updateQuote(this.quoteForm.controls['quote'].value) + this.quoteForm.reset() } } diff --git a/src/app/account.service.spec.ts b/src/app/account.service.spec.ts deleted file mode 100644 index 2ffad6f..0000000 --- a/src/app/account.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { AccountService } from './account.service'; - -describe('AccountService', () => { - let service: AccountService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(AccountService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/account.service.ts b/src/app/account.service.ts deleted file mode 100644 index e0690a2..0000000 --- a/src/app/account.service.ts +++ /dev/null @@ -1,163 +0,0 @@ -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 Swal from 'sweetalert2'; - -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) { - 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) { - Swal.fire('Password changed!', 'Watch out, \nyour old password won\'t work anymore', 'success') - } else { - this.logout() - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - 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) { - Swal.fire('You posted a status', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } - - 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) { - Swal.fire('You updated your quote', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } -} diff --git a/src/app/admin/admin.component.ts b/src/app/admin/admin.component.ts index 4b518fa..8e5dd3c 100644 --- a/src/app/admin/admin.component.ts +++ b/src/app/admin/admin.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; -import { AccountService } from '../account.service'; +import { AccountService } from '../login/account.service'; interface TimeEntry { value: number @@ -70,6 +70,8 @@ return } this.account.postStatus(this.statusForm.controls['status'].value, this.statusForm.controls['time'].value) + this.statusForm.reset() + this.statusForm.get('time')?.setValue(60) } onQuoteSubmit() { @@ -77,5 +79,6 @@ return } this.account.updateQuote(this.quoteForm.controls['quote'].value) + this.quoteForm.reset() } } diff --git a/src/app/alert/alert.component.html b/src/app/alert/alert.component.html new file mode 100644 index 0000000..bf39dfe --- /dev/null +++ b/src/app/alert/alert.component.html @@ -0,0 +1,3 @@ +

{{data.title}}

+

{{data.content}}

+ \ No newline at end of file diff --git a/src/app/account.service.spec.ts b/src/app/account.service.spec.ts deleted file mode 100644 index 2ffad6f..0000000 --- a/src/app/account.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { AccountService } from './account.service'; - -describe('AccountService', () => { - let service: AccountService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(AccountService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/account.service.ts b/src/app/account.service.ts deleted file mode 100644 index e0690a2..0000000 --- a/src/app/account.service.ts +++ /dev/null @@ -1,163 +0,0 @@ -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 Swal from 'sweetalert2'; - -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) { - 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) { - Swal.fire('Password changed!', 'Watch out, \nyour old password won\'t work anymore', 'success') - } else { - this.logout() - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - 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) { - Swal.fire('You posted a status', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } - - 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) { - Swal.fire('You updated your quote', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } -} diff --git a/src/app/admin/admin.component.ts b/src/app/admin/admin.component.ts index 4b518fa..8e5dd3c 100644 --- a/src/app/admin/admin.component.ts +++ b/src/app/admin/admin.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; -import { AccountService } from '../account.service'; +import { AccountService } from '../login/account.service'; interface TimeEntry { value: number @@ -70,6 +70,8 @@ return } this.account.postStatus(this.statusForm.controls['status'].value, this.statusForm.controls['time'].value) + this.statusForm.reset() + this.statusForm.get('time')?.setValue(60) } onQuoteSubmit() { @@ -77,5 +79,6 @@ return } this.account.updateQuote(this.quoteForm.controls['quote'].value) + this.quoteForm.reset() } } diff --git a/src/app/alert/alert.component.html b/src/app/alert/alert.component.html new file mode 100644 index 0000000..bf39dfe --- /dev/null +++ b/src/app/alert/alert.component.html @@ -0,0 +1,3 @@ +

{{data.title}}

+

{{data.content}}

+ \ No newline at end of file diff --git a/src/app/alert/alert.component.scss b/src/app/alert/alert.component.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/app/alert/alert.component.scss diff --git a/src/app/account.service.spec.ts b/src/app/account.service.spec.ts deleted file mode 100644 index 2ffad6f..0000000 --- a/src/app/account.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { AccountService } from './account.service'; - -describe('AccountService', () => { - let service: AccountService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(AccountService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/account.service.ts b/src/app/account.service.ts deleted file mode 100644 index e0690a2..0000000 --- a/src/app/account.service.ts +++ /dev/null @@ -1,163 +0,0 @@ -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 Swal from 'sweetalert2'; - -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) { - 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) { - Swal.fire('Password changed!', 'Watch out, \nyour old password won\'t work anymore', 'success') - } else { - this.logout() - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - 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) { - Swal.fire('You posted a status', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } - - 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) { - Swal.fire('You updated your quote', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } -} diff --git a/src/app/admin/admin.component.ts b/src/app/admin/admin.component.ts index 4b518fa..8e5dd3c 100644 --- a/src/app/admin/admin.component.ts +++ b/src/app/admin/admin.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; -import { AccountService } from '../account.service'; +import { AccountService } from '../login/account.service'; interface TimeEntry { value: number @@ -70,6 +70,8 @@ return } this.account.postStatus(this.statusForm.controls['status'].value, this.statusForm.controls['time'].value) + this.statusForm.reset() + this.statusForm.get('time')?.setValue(60) } onQuoteSubmit() { @@ -77,5 +79,6 @@ return } this.account.updateQuote(this.quoteForm.controls['quote'].value) + this.quoteForm.reset() } } diff --git a/src/app/alert/alert.component.html b/src/app/alert/alert.component.html new file mode 100644 index 0000000..bf39dfe --- /dev/null +++ b/src/app/alert/alert.component.html @@ -0,0 +1,3 @@ +

{{data.title}}

+

{{data.content}}

+ \ No newline at end of file diff --git a/src/app/alert/alert.component.scss b/src/app/alert/alert.component.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/app/alert/alert.component.scss diff --git a/src/app/alert/alert.component.spec.ts b/src/app/alert/alert.component.spec.ts new file mode 100644 index 0000000..8e3decb --- /dev/null +++ b/src/app/alert/alert.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AlertComponent } from './alert.component'; + +describe('AlertComponent', () => { + let component: AlertComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AlertComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AlertComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/account.service.spec.ts b/src/app/account.service.spec.ts deleted file mode 100644 index 2ffad6f..0000000 --- a/src/app/account.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { AccountService } from './account.service'; - -describe('AccountService', () => { - let service: AccountService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(AccountService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/account.service.ts b/src/app/account.service.ts deleted file mode 100644 index e0690a2..0000000 --- a/src/app/account.service.ts +++ /dev/null @@ -1,163 +0,0 @@ -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 Swal from 'sweetalert2'; - -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) { - 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) { - Swal.fire('Password changed!', 'Watch out, \nyour old password won\'t work anymore', 'success') - } else { - this.logout() - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - 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) { - Swal.fire('You posted a status', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } - - 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) { - Swal.fire('You updated your quote', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } -} diff --git a/src/app/admin/admin.component.ts b/src/app/admin/admin.component.ts index 4b518fa..8e5dd3c 100644 --- a/src/app/admin/admin.component.ts +++ b/src/app/admin/admin.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; -import { AccountService } from '../account.service'; +import { AccountService } from '../login/account.service'; interface TimeEntry { value: number @@ -70,6 +70,8 @@ return } this.account.postStatus(this.statusForm.controls['status'].value, this.statusForm.controls['time'].value) + this.statusForm.reset() + this.statusForm.get('time')?.setValue(60) } onQuoteSubmit() { @@ -77,5 +79,6 @@ return } this.account.updateQuote(this.quoteForm.controls['quote'].value) + this.quoteForm.reset() } } diff --git a/src/app/alert/alert.component.html b/src/app/alert/alert.component.html new file mode 100644 index 0000000..bf39dfe --- /dev/null +++ b/src/app/alert/alert.component.html @@ -0,0 +1,3 @@ +

{{data.title}}

+

{{data.content}}

+ \ No newline at end of file diff --git a/src/app/alert/alert.component.scss b/src/app/alert/alert.component.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/app/alert/alert.component.scss diff --git a/src/app/alert/alert.component.spec.ts b/src/app/alert/alert.component.spec.ts new file mode 100644 index 0000000..8e3decb --- /dev/null +++ b/src/app/alert/alert.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AlertComponent } from './alert.component'; + +describe('AlertComponent', () => { + let component: AlertComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AlertComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AlertComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/alert/alert.component.ts b/src/app/alert/alert.component.ts new file mode 100644 index 0000000..74e4db4 --- /dev/null +++ b/src/app/alert/alert.component.ts @@ -0,0 +1,20 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +@Component({ + selector: 'app-alert', + templateUrl: './alert.component.html', + styleUrls: ['./alert.component.scss'] +}) +export class AlertComponent implements OnInit { + constructor( + @Inject(MAT_DIALOG_DATA) public data: {title: string, content: string}, + private dilogRef: MatDialogRef) { } + + ngOnInit(): void { + } + + onClose() { + this.dilogRef.close() + } +} diff --git a/src/app/account.service.spec.ts b/src/app/account.service.spec.ts deleted file mode 100644 index 2ffad6f..0000000 --- a/src/app/account.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { AccountService } from './account.service'; - -describe('AccountService', () => { - let service: AccountService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(AccountService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/account.service.ts b/src/app/account.service.ts deleted file mode 100644 index e0690a2..0000000 --- a/src/app/account.service.ts +++ /dev/null @@ -1,163 +0,0 @@ -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 Swal from 'sweetalert2'; - -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) { - 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) { - Swal.fire('Password changed!', 'Watch out, \nyour old password won\'t work anymore', 'success') - } else { - this.logout() - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - 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) { - Swal.fire('You posted a status', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } - - 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) { - Swal.fire('You updated your quote', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } -} diff --git a/src/app/admin/admin.component.ts b/src/app/admin/admin.component.ts index 4b518fa..8e5dd3c 100644 --- a/src/app/admin/admin.component.ts +++ b/src/app/admin/admin.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; -import { AccountService } from '../account.service'; +import { AccountService } from '../login/account.service'; interface TimeEntry { value: number @@ -70,6 +70,8 @@ return } this.account.postStatus(this.statusForm.controls['status'].value, this.statusForm.controls['time'].value) + this.statusForm.reset() + this.statusForm.get('time')?.setValue(60) } onQuoteSubmit() { @@ -77,5 +79,6 @@ return } this.account.updateQuote(this.quoteForm.controls['quote'].value) + this.quoteForm.reset() } } diff --git a/src/app/alert/alert.component.html b/src/app/alert/alert.component.html new file mode 100644 index 0000000..bf39dfe --- /dev/null +++ b/src/app/alert/alert.component.html @@ -0,0 +1,3 @@ +

{{data.title}}

+

{{data.content}}

+ \ No newline at end of file diff --git a/src/app/alert/alert.component.scss b/src/app/alert/alert.component.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/app/alert/alert.component.scss diff --git a/src/app/alert/alert.component.spec.ts b/src/app/alert/alert.component.spec.ts new file mode 100644 index 0000000..8e3decb --- /dev/null +++ b/src/app/alert/alert.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AlertComponent } from './alert.component'; + +describe('AlertComponent', () => { + let component: AlertComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AlertComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AlertComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/alert/alert.component.ts b/src/app/alert/alert.component.ts new file mode 100644 index 0000000..74e4db4 --- /dev/null +++ b/src/app/alert/alert.component.ts @@ -0,0 +1,20 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +@Component({ + selector: 'app-alert', + templateUrl: './alert.component.html', + styleUrls: ['./alert.component.scss'] +}) +export class AlertComponent implements OnInit { + constructor( + @Inject(MAT_DIALOG_DATA) public data: {title: string, content: string}, + private dilogRef: MatDialogRef) { } + + ngOnInit(): void { + } + + onClose() { + this.dilogRef.close() + } +} diff --git a/src/app/alert/alert.service.spec.ts b/src/app/alert/alert.service.spec.ts new file mode 100644 index 0000000..b20ed8c --- /dev/null +++ b/src/app/alert/alert.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AlertService } from './alert.service'; + +describe('AlertService', () => { + let service: AlertService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AlertService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/account.service.spec.ts b/src/app/account.service.spec.ts deleted file mode 100644 index 2ffad6f..0000000 --- a/src/app/account.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { AccountService } from './account.service'; - -describe('AccountService', () => { - let service: AccountService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(AccountService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/account.service.ts b/src/app/account.service.ts deleted file mode 100644 index e0690a2..0000000 --- a/src/app/account.service.ts +++ /dev/null @@ -1,163 +0,0 @@ -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 Swal from 'sweetalert2'; - -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) { - 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) { - Swal.fire('Password changed!', 'Watch out, \nyour old password won\'t work anymore', 'success') - } else { - this.logout() - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - 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) { - Swal.fire('You posted a status', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } - - 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) { - Swal.fire('You updated your quote', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } -} diff --git a/src/app/admin/admin.component.ts b/src/app/admin/admin.component.ts index 4b518fa..8e5dd3c 100644 --- a/src/app/admin/admin.component.ts +++ b/src/app/admin/admin.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; -import { AccountService } from '../account.service'; +import { AccountService } from '../login/account.service'; interface TimeEntry { value: number @@ -70,6 +70,8 @@ return } this.account.postStatus(this.statusForm.controls['status'].value, this.statusForm.controls['time'].value) + this.statusForm.reset() + this.statusForm.get('time')?.setValue(60) } onQuoteSubmit() { @@ -77,5 +79,6 @@ return } this.account.updateQuote(this.quoteForm.controls['quote'].value) + this.quoteForm.reset() } } diff --git a/src/app/alert/alert.component.html b/src/app/alert/alert.component.html new file mode 100644 index 0000000..bf39dfe --- /dev/null +++ b/src/app/alert/alert.component.html @@ -0,0 +1,3 @@ +

{{data.title}}

+

{{data.content}}

+ \ No newline at end of file diff --git a/src/app/alert/alert.component.scss b/src/app/alert/alert.component.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/app/alert/alert.component.scss diff --git a/src/app/alert/alert.component.spec.ts b/src/app/alert/alert.component.spec.ts new file mode 100644 index 0000000..8e3decb --- /dev/null +++ b/src/app/alert/alert.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AlertComponent } from './alert.component'; + +describe('AlertComponent', () => { + let component: AlertComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AlertComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AlertComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/alert/alert.component.ts b/src/app/alert/alert.component.ts new file mode 100644 index 0000000..74e4db4 --- /dev/null +++ b/src/app/alert/alert.component.ts @@ -0,0 +1,20 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +@Component({ + selector: 'app-alert', + templateUrl: './alert.component.html', + styleUrls: ['./alert.component.scss'] +}) +export class AlertComponent implements OnInit { + constructor( + @Inject(MAT_DIALOG_DATA) public data: {title: string, content: string}, + private dilogRef: MatDialogRef) { } + + ngOnInit(): void { + } + + onClose() { + this.dilogRef.close() + } +} diff --git a/src/app/alert/alert.service.spec.ts b/src/app/alert/alert.service.spec.ts new file mode 100644 index 0000000..b20ed8c --- /dev/null +++ b/src/app/alert/alert.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AlertService } from './alert.service'; + +describe('AlertService', () => { + let service: AlertService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AlertService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/alert/alert.service.ts b/src/app/alert/alert.service.ts new file mode 100644 index 0000000..22a4e76 --- /dev/null +++ b/src/app/alert/alert.service.ts @@ -0,0 +1,15 @@ +import { Injectable } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { AlertComponent } from './alert.component'; + +@Injectable({ + providedIn: 'root' +}) +export class AlertService { + + constructor(private dialog: MatDialog) { } + + alert(title: string, content: string) { + this.dialog.open(AlertComponent, {data: {title: title, content: content}}) + } +} diff --git a/src/app/account.service.spec.ts b/src/app/account.service.spec.ts deleted file mode 100644 index 2ffad6f..0000000 --- a/src/app/account.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { AccountService } from './account.service'; - -describe('AccountService', () => { - let service: AccountService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(AccountService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/account.service.ts b/src/app/account.service.ts deleted file mode 100644 index e0690a2..0000000 --- a/src/app/account.service.ts +++ /dev/null @@ -1,163 +0,0 @@ -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 Swal from 'sweetalert2'; - -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) { - 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) { - Swal.fire('Password changed!', 'Watch out, \nyour old password won\'t work anymore', 'success') - } else { - this.logout() - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - 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) { - Swal.fire('You posted a status', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } - - 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) { - Swal.fire('You updated your quote', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } -} diff --git a/src/app/admin/admin.component.ts b/src/app/admin/admin.component.ts index 4b518fa..8e5dd3c 100644 --- a/src/app/admin/admin.component.ts +++ b/src/app/admin/admin.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; -import { AccountService } from '../account.service'; +import { AccountService } from '../login/account.service'; interface TimeEntry { value: number @@ -70,6 +70,8 @@ return } this.account.postStatus(this.statusForm.controls['status'].value, this.statusForm.controls['time'].value) + this.statusForm.reset() + this.statusForm.get('time')?.setValue(60) } onQuoteSubmit() { @@ -77,5 +79,6 @@ return } this.account.updateQuote(this.quoteForm.controls['quote'].value) + this.quoteForm.reset() } } diff --git a/src/app/alert/alert.component.html b/src/app/alert/alert.component.html new file mode 100644 index 0000000..bf39dfe --- /dev/null +++ b/src/app/alert/alert.component.html @@ -0,0 +1,3 @@ +

{{data.title}}

+

{{data.content}}

+ \ No newline at end of file diff --git a/src/app/alert/alert.component.scss b/src/app/alert/alert.component.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/app/alert/alert.component.scss diff --git a/src/app/alert/alert.component.spec.ts b/src/app/alert/alert.component.spec.ts new file mode 100644 index 0000000..8e3decb --- /dev/null +++ b/src/app/alert/alert.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AlertComponent } from './alert.component'; + +describe('AlertComponent', () => { + let component: AlertComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AlertComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AlertComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/alert/alert.component.ts b/src/app/alert/alert.component.ts new file mode 100644 index 0000000..74e4db4 --- /dev/null +++ b/src/app/alert/alert.component.ts @@ -0,0 +1,20 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +@Component({ + selector: 'app-alert', + templateUrl: './alert.component.html', + styleUrls: ['./alert.component.scss'] +}) +export class AlertComponent implements OnInit { + constructor( + @Inject(MAT_DIALOG_DATA) public data: {title: string, content: string}, + private dilogRef: MatDialogRef) { } + + ngOnInit(): void { + } + + onClose() { + this.dilogRef.close() + } +} diff --git a/src/app/alert/alert.service.spec.ts b/src/app/alert/alert.service.spec.ts new file mode 100644 index 0000000..b20ed8c --- /dev/null +++ b/src/app/alert/alert.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AlertService } from './alert.service'; + +describe('AlertService', () => { + let service: AlertService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AlertService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/alert/alert.service.ts b/src/app/alert/alert.service.ts new file mode 100644 index 0000000..22a4e76 --- /dev/null +++ b/src/app/alert/alert.service.ts @@ -0,0 +1,15 @@ +import { Injectable } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { AlertComponent } from './alert.component'; + +@Injectable({ + providedIn: 'root' +}) +export class AlertService { + + constructor(private dialog: MatDialog) { } + + alert(title: string, content: string) { + this.dialog.open(AlertComponent, {data: {title: title, content: content}}) + } +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 2aab2ac..14b230f 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -14,6 +14,7 @@ import { MatSelectModule } from '@angular/material/select'; import { MatOptionModule } from '@angular/material/core'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner' +import {MatDialogModule} from '@angular/material/dialog'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @@ -23,11 +24,13 @@ import { FooterComponent } from './footer/footer.component'; import { GridComponent } from './grid/grid.component'; -import { AccountService } from './account.service'; +import { AccountService } from './login/account.service'; import { LoginComponent } from './login/login.component' import { HttpClientModule } from '@angular/common/http'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { AdminComponent } from './admin/admin.component'; +import { AlertComponent } from './alert/alert.component'; +import { AlertService } from './alert/alert.service'; @NgModule({ declarations: [ @@ -37,7 +40,8 @@ FooterComponent, GridComponent, LoginComponent, - AdminComponent + AdminComponent, + AlertComponent, ], imports: [ BrowserModule, @@ -60,8 +64,12 @@ MatSelectModule, MatOptionModule, MatProgressSpinnerModule, + MatDialogModule, ], - providers: [AccountService], + providers: [ + AccountService, + AlertService, + ], bootstrap: [AppComponent] }) export class AppModule { } diff --git a/src/app/account.service.spec.ts b/src/app/account.service.spec.ts deleted file mode 100644 index 2ffad6f..0000000 --- a/src/app/account.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { AccountService } from './account.service'; - -describe('AccountService', () => { - let service: AccountService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(AccountService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/account.service.ts b/src/app/account.service.ts deleted file mode 100644 index e0690a2..0000000 --- a/src/app/account.service.ts +++ /dev/null @@ -1,163 +0,0 @@ -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 Swal from 'sweetalert2'; - -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) { - 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) { - Swal.fire('Password changed!', 'Watch out, \nyour old password won\'t work anymore', 'success') - } else { - this.logout() - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - 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) { - Swal.fire('You posted a status', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } - - 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) { - Swal.fire('You updated your quote', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } -} diff --git a/src/app/admin/admin.component.ts b/src/app/admin/admin.component.ts index 4b518fa..8e5dd3c 100644 --- a/src/app/admin/admin.component.ts +++ b/src/app/admin/admin.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; -import { AccountService } from '../account.service'; +import { AccountService } from '../login/account.service'; interface TimeEntry { value: number @@ -70,6 +70,8 @@ return } this.account.postStatus(this.statusForm.controls['status'].value, this.statusForm.controls['time'].value) + this.statusForm.reset() + this.statusForm.get('time')?.setValue(60) } onQuoteSubmit() { @@ -77,5 +79,6 @@ return } this.account.updateQuote(this.quoteForm.controls['quote'].value) + this.quoteForm.reset() } } diff --git a/src/app/alert/alert.component.html b/src/app/alert/alert.component.html new file mode 100644 index 0000000..bf39dfe --- /dev/null +++ b/src/app/alert/alert.component.html @@ -0,0 +1,3 @@ +

{{data.title}}

+

{{data.content}}

+ \ No newline at end of file diff --git a/src/app/alert/alert.component.scss b/src/app/alert/alert.component.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/app/alert/alert.component.scss diff --git a/src/app/alert/alert.component.spec.ts b/src/app/alert/alert.component.spec.ts new file mode 100644 index 0000000..8e3decb --- /dev/null +++ b/src/app/alert/alert.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AlertComponent } from './alert.component'; + +describe('AlertComponent', () => { + let component: AlertComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AlertComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AlertComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/alert/alert.component.ts b/src/app/alert/alert.component.ts new file mode 100644 index 0000000..74e4db4 --- /dev/null +++ b/src/app/alert/alert.component.ts @@ -0,0 +1,20 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +@Component({ + selector: 'app-alert', + templateUrl: './alert.component.html', + styleUrls: ['./alert.component.scss'] +}) +export class AlertComponent implements OnInit { + constructor( + @Inject(MAT_DIALOG_DATA) public data: {title: string, content: string}, + private dilogRef: MatDialogRef) { } + + ngOnInit(): void { + } + + onClose() { + this.dilogRef.close() + } +} diff --git a/src/app/alert/alert.service.spec.ts b/src/app/alert/alert.service.spec.ts new file mode 100644 index 0000000..b20ed8c --- /dev/null +++ b/src/app/alert/alert.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AlertService } from './alert.service'; + +describe('AlertService', () => { + let service: AlertService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AlertService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/alert/alert.service.ts b/src/app/alert/alert.service.ts new file mode 100644 index 0000000..22a4e76 --- /dev/null +++ b/src/app/alert/alert.service.ts @@ -0,0 +1,15 @@ +import { Injectable } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { AlertComponent } from './alert.component'; + +@Injectable({ + providedIn: 'root' +}) +export class AlertService { + + constructor(private dialog: MatDialog) { } + + alert(title: string, content: string) { + this.dialog.open(AlertComponent, {data: {title: title, content: content}}) + } +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 2aab2ac..14b230f 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -14,6 +14,7 @@ import { MatSelectModule } from '@angular/material/select'; import { MatOptionModule } from '@angular/material/core'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner' +import {MatDialogModule} from '@angular/material/dialog'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @@ -23,11 +24,13 @@ import { FooterComponent } from './footer/footer.component'; import { GridComponent } from './grid/grid.component'; -import { AccountService } from './account.service'; +import { AccountService } from './login/account.service'; import { LoginComponent } from './login/login.component' import { HttpClientModule } from '@angular/common/http'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { AdminComponent } from './admin/admin.component'; +import { AlertComponent } from './alert/alert.component'; +import { AlertService } from './alert/alert.service'; @NgModule({ declarations: [ @@ -37,7 +40,8 @@ FooterComponent, GridComponent, LoginComponent, - AdminComponent + AdminComponent, + AlertComponent, ], imports: [ BrowserModule, @@ -60,8 +64,12 @@ MatSelectModule, MatOptionModule, MatProgressSpinnerModule, + MatDialogModule, ], - providers: [AccountService], + providers: [ + AccountService, + AlertService, + ], bootstrap: [AppComponent] }) export class AppModule { } diff --git a/src/app/login/account.service.spec.ts b/src/app/login/account.service.spec.ts new file mode 100644 index 0000000..2ffad6f --- /dev/null +++ b/src/app/login/account.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AccountService } from './account.service'; + +describe('AccountService', () => { + let service: AccountService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AccountService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/account.service.spec.ts b/src/app/account.service.spec.ts deleted file mode 100644 index 2ffad6f..0000000 --- a/src/app/account.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { AccountService } from './account.service'; - -describe('AccountService', () => { - let service: AccountService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(AccountService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/account.service.ts b/src/app/account.service.ts deleted file mode 100644 index e0690a2..0000000 --- a/src/app/account.service.ts +++ /dev/null @@ -1,163 +0,0 @@ -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 Swal from 'sweetalert2'; - -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) { - 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) { - Swal.fire('Password changed!', 'Watch out, \nyour old password won\'t work anymore', 'success') - } else { - this.logout() - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - 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) { - Swal.fire('You posted a status', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } - - 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) { - Swal.fire('You updated your quote', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } -} diff --git a/src/app/admin/admin.component.ts b/src/app/admin/admin.component.ts index 4b518fa..8e5dd3c 100644 --- a/src/app/admin/admin.component.ts +++ b/src/app/admin/admin.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; -import { AccountService } from '../account.service'; +import { AccountService } from '../login/account.service'; interface TimeEntry { value: number @@ -70,6 +70,8 @@ return } this.account.postStatus(this.statusForm.controls['status'].value, this.statusForm.controls['time'].value) + this.statusForm.reset() + this.statusForm.get('time')?.setValue(60) } onQuoteSubmit() { @@ -77,5 +79,6 @@ return } this.account.updateQuote(this.quoteForm.controls['quote'].value) + this.quoteForm.reset() } } diff --git a/src/app/alert/alert.component.html b/src/app/alert/alert.component.html new file mode 100644 index 0000000..bf39dfe --- /dev/null +++ b/src/app/alert/alert.component.html @@ -0,0 +1,3 @@ +

{{data.title}}

+

{{data.content}}

+ \ No newline at end of file diff --git a/src/app/alert/alert.component.scss b/src/app/alert/alert.component.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/app/alert/alert.component.scss diff --git a/src/app/alert/alert.component.spec.ts b/src/app/alert/alert.component.spec.ts new file mode 100644 index 0000000..8e3decb --- /dev/null +++ b/src/app/alert/alert.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AlertComponent } from './alert.component'; + +describe('AlertComponent', () => { + let component: AlertComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AlertComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AlertComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/alert/alert.component.ts b/src/app/alert/alert.component.ts new file mode 100644 index 0000000..74e4db4 --- /dev/null +++ b/src/app/alert/alert.component.ts @@ -0,0 +1,20 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +@Component({ + selector: 'app-alert', + templateUrl: './alert.component.html', + styleUrls: ['./alert.component.scss'] +}) +export class AlertComponent implements OnInit { + constructor( + @Inject(MAT_DIALOG_DATA) public data: {title: string, content: string}, + private dilogRef: MatDialogRef) { } + + ngOnInit(): void { + } + + onClose() { + this.dilogRef.close() + } +} diff --git a/src/app/alert/alert.service.spec.ts b/src/app/alert/alert.service.spec.ts new file mode 100644 index 0000000..b20ed8c --- /dev/null +++ b/src/app/alert/alert.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AlertService } from './alert.service'; + +describe('AlertService', () => { + let service: AlertService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AlertService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/alert/alert.service.ts b/src/app/alert/alert.service.ts new file mode 100644 index 0000000..22a4e76 --- /dev/null +++ b/src/app/alert/alert.service.ts @@ -0,0 +1,15 @@ +import { Injectable } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { AlertComponent } from './alert.component'; + +@Injectable({ + providedIn: 'root' +}) +export class AlertService { + + constructor(private dialog: MatDialog) { } + + alert(title: string, content: string) { + this.dialog.open(AlertComponent, {data: {title: title, content: content}}) + } +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 2aab2ac..14b230f 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -14,6 +14,7 @@ import { MatSelectModule } from '@angular/material/select'; import { MatOptionModule } from '@angular/material/core'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner' +import {MatDialogModule} from '@angular/material/dialog'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @@ -23,11 +24,13 @@ import { FooterComponent } from './footer/footer.component'; import { GridComponent } from './grid/grid.component'; -import { AccountService } from './account.service'; +import { AccountService } from './login/account.service'; import { LoginComponent } from './login/login.component' import { HttpClientModule } from '@angular/common/http'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { AdminComponent } from './admin/admin.component'; +import { AlertComponent } from './alert/alert.component'; +import { AlertService } from './alert/alert.service'; @NgModule({ declarations: [ @@ -37,7 +40,8 @@ FooterComponent, GridComponent, LoginComponent, - AdminComponent + AdminComponent, + AlertComponent, ], imports: [ BrowserModule, @@ -60,8 +64,12 @@ MatSelectModule, MatOptionModule, MatProgressSpinnerModule, + MatDialogModule, ], - providers: [AccountService], + providers: [ + AccountService, + AlertService, + ], bootstrap: [AppComponent] }) export class AppModule { } diff --git a/src/app/login/account.service.spec.ts b/src/app/login/account.service.spec.ts new file mode 100644 index 0000000..2ffad6f --- /dev/null +++ b/src/app/login/account.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AccountService } from './account.service'; + +describe('AccountService', () => { + let service: AccountService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AccountService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/login/account.service.ts b/src/app/login/account.service.ts new file mode 100644 index 0000000..ca31e9f --- /dev/null +++ b/src/app/login/account.service.ts @@ -0,0 +1,164 @@ +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?') + } + }) + } +} diff --git a/src/app/account.service.spec.ts b/src/app/account.service.spec.ts deleted file mode 100644 index 2ffad6f..0000000 --- a/src/app/account.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { AccountService } from './account.service'; - -describe('AccountService', () => { - let service: AccountService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(AccountService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/account.service.ts b/src/app/account.service.ts deleted file mode 100644 index e0690a2..0000000 --- a/src/app/account.service.ts +++ /dev/null @@ -1,163 +0,0 @@ -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 Swal from 'sweetalert2'; - -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) { - 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) { - Swal.fire('Password changed!', 'Watch out, \nyour old password won\'t work anymore', 'success') - } else { - this.logout() - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - 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) { - Swal.fire('You posted a status', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } - - 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) { - Swal.fire('You updated your quote', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } -} diff --git a/src/app/admin/admin.component.ts b/src/app/admin/admin.component.ts index 4b518fa..8e5dd3c 100644 --- a/src/app/admin/admin.component.ts +++ b/src/app/admin/admin.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; -import { AccountService } from '../account.service'; +import { AccountService } from '../login/account.service'; interface TimeEntry { value: number @@ -70,6 +70,8 @@ return } this.account.postStatus(this.statusForm.controls['status'].value, this.statusForm.controls['time'].value) + this.statusForm.reset() + this.statusForm.get('time')?.setValue(60) } onQuoteSubmit() { @@ -77,5 +79,6 @@ return } this.account.updateQuote(this.quoteForm.controls['quote'].value) + this.quoteForm.reset() } } diff --git a/src/app/alert/alert.component.html b/src/app/alert/alert.component.html new file mode 100644 index 0000000..bf39dfe --- /dev/null +++ b/src/app/alert/alert.component.html @@ -0,0 +1,3 @@ +

{{data.title}}

+

{{data.content}}

+ \ No newline at end of file diff --git a/src/app/alert/alert.component.scss b/src/app/alert/alert.component.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/app/alert/alert.component.scss diff --git a/src/app/alert/alert.component.spec.ts b/src/app/alert/alert.component.spec.ts new file mode 100644 index 0000000..8e3decb --- /dev/null +++ b/src/app/alert/alert.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AlertComponent } from './alert.component'; + +describe('AlertComponent', () => { + let component: AlertComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AlertComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AlertComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/alert/alert.component.ts b/src/app/alert/alert.component.ts new file mode 100644 index 0000000..74e4db4 --- /dev/null +++ b/src/app/alert/alert.component.ts @@ -0,0 +1,20 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +@Component({ + selector: 'app-alert', + templateUrl: './alert.component.html', + styleUrls: ['./alert.component.scss'] +}) +export class AlertComponent implements OnInit { + constructor( + @Inject(MAT_DIALOG_DATA) public data: {title: string, content: string}, + private dilogRef: MatDialogRef) { } + + ngOnInit(): void { + } + + onClose() { + this.dilogRef.close() + } +} diff --git a/src/app/alert/alert.service.spec.ts b/src/app/alert/alert.service.spec.ts new file mode 100644 index 0000000..b20ed8c --- /dev/null +++ b/src/app/alert/alert.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AlertService } from './alert.service'; + +describe('AlertService', () => { + let service: AlertService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AlertService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/alert/alert.service.ts b/src/app/alert/alert.service.ts new file mode 100644 index 0000000..22a4e76 --- /dev/null +++ b/src/app/alert/alert.service.ts @@ -0,0 +1,15 @@ +import { Injectable } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { AlertComponent } from './alert.component'; + +@Injectable({ + providedIn: 'root' +}) +export class AlertService { + + constructor(private dialog: MatDialog) { } + + alert(title: string, content: string) { + this.dialog.open(AlertComponent, {data: {title: title, content: content}}) + } +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 2aab2ac..14b230f 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -14,6 +14,7 @@ import { MatSelectModule } from '@angular/material/select'; import { MatOptionModule } from '@angular/material/core'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner' +import {MatDialogModule} from '@angular/material/dialog'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @@ -23,11 +24,13 @@ import { FooterComponent } from './footer/footer.component'; import { GridComponent } from './grid/grid.component'; -import { AccountService } from './account.service'; +import { AccountService } from './login/account.service'; import { LoginComponent } from './login/login.component' import { HttpClientModule } from '@angular/common/http'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { AdminComponent } from './admin/admin.component'; +import { AlertComponent } from './alert/alert.component'; +import { AlertService } from './alert/alert.service'; @NgModule({ declarations: [ @@ -37,7 +40,8 @@ FooterComponent, GridComponent, LoginComponent, - AdminComponent + AdminComponent, + AlertComponent, ], imports: [ BrowserModule, @@ -60,8 +64,12 @@ MatSelectModule, MatOptionModule, MatProgressSpinnerModule, + MatDialogModule, ], - providers: [AccountService], + providers: [ + AccountService, + AlertService, + ], bootstrap: [AppComponent] }) export class AppModule { } diff --git a/src/app/login/account.service.spec.ts b/src/app/login/account.service.spec.ts new file mode 100644 index 0000000..2ffad6f --- /dev/null +++ b/src/app/login/account.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AccountService } from './account.service'; + +describe('AccountService', () => { + let service: AccountService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AccountService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/login/account.service.ts b/src/app/login/account.service.ts new file mode 100644 index 0000000..ca31e9f --- /dev/null +++ b/src/app/login/account.service.ts @@ -0,0 +1,164 @@ +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?') + } + }) + } +} diff --git a/src/app/login/login.component.ts b/src/app/login/login.component.ts index c8f045f..89f243c 100644 --- a/src/app/login/login.component.ts +++ b/src/app/login/login.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, NgForm, Validators } from '@angular/forms'; import { environment } from 'src/environments/environment'; -import { AccountService } from '../account.service'; +import { AccountService } from './account.service'; class LoginInformation { constructor(public username: string, public password: string) { diff --git a/src/app/account.service.spec.ts b/src/app/account.service.spec.ts deleted file mode 100644 index 2ffad6f..0000000 --- a/src/app/account.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { AccountService } from './account.service'; - -describe('AccountService', () => { - let service: AccountService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(AccountService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/account.service.ts b/src/app/account.service.ts deleted file mode 100644 index e0690a2..0000000 --- a/src/app/account.service.ts +++ /dev/null @@ -1,163 +0,0 @@ -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 Swal from 'sweetalert2'; - -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) { - 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) { - Swal.fire('Password changed!', 'Watch out, \nyour old password won\'t work anymore', 'success') - } else { - this.logout() - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - 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) { - Swal.fire('You posted a status', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } - - 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) { - Swal.fire('You updated your quote', 'Everyone can see it', 'success') - } else { - Swal.fire('Error!', 'Something went wrong, bad user token?', 'error') - } - }) - } -} diff --git a/src/app/admin/admin.component.ts b/src/app/admin/admin.component.ts index 4b518fa..8e5dd3c 100644 --- a/src/app/admin/admin.component.ts +++ b/src/app/admin/admin.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; -import { AccountService } from '../account.service'; +import { AccountService } from '../login/account.service'; interface TimeEntry { value: number @@ -70,6 +70,8 @@ return } this.account.postStatus(this.statusForm.controls['status'].value, this.statusForm.controls['time'].value) + this.statusForm.reset() + this.statusForm.get('time')?.setValue(60) } onQuoteSubmit() { @@ -77,5 +79,6 @@ return } this.account.updateQuote(this.quoteForm.controls['quote'].value) + this.quoteForm.reset() } } diff --git a/src/app/alert/alert.component.html b/src/app/alert/alert.component.html new file mode 100644 index 0000000..bf39dfe --- /dev/null +++ b/src/app/alert/alert.component.html @@ -0,0 +1,3 @@ +

{{data.title}}

+

{{data.content}}

+ \ No newline at end of file diff --git a/src/app/alert/alert.component.scss b/src/app/alert/alert.component.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/app/alert/alert.component.scss diff --git a/src/app/alert/alert.component.spec.ts b/src/app/alert/alert.component.spec.ts new file mode 100644 index 0000000..8e3decb --- /dev/null +++ b/src/app/alert/alert.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AlertComponent } from './alert.component'; + +describe('AlertComponent', () => { + let component: AlertComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AlertComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AlertComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/alert/alert.component.ts b/src/app/alert/alert.component.ts new file mode 100644 index 0000000..74e4db4 --- /dev/null +++ b/src/app/alert/alert.component.ts @@ -0,0 +1,20 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +@Component({ + selector: 'app-alert', + templateUrl: './alert.component.html', + styleUrls: ['./alert.component.scss'] +}) +export class AlertComponent implements OnInit { + constructor( + @Inject(MAT_DIALOG_DATA) public data: {title: string, content: string}, + private dilogRef: MatDialogRef) { } + + ngOnInit(): void { + } + + onClose() { + this.dilogRef.close() + } +} diff --git a/src/app/alert/alert.service.spec.ts b/src/app/alert/alert.service.spec.ts new file mode 100644 index 0000000..b20ed8c --- /dev/null +++ b/src/app/alert/alert.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AlertService } from './alert.service'; + +describe('AlertService', () => { + let service: AlertService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AlertService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/alert/alert.service.ts b/src/app/alert/alert.service.ts new file mode 100644 index 0000000..22a4e76 --- /dev/null +++ b/src/app/alert/alert.service.ts @@ -0,0 +1,15 @@ +import { Injectable } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { AlertComponent } from './alert.component'; + +@Injectable({ + providedIn: 'root' +}) +export class AlertService { + + constructor(private dialog: MatDialog) { } + + alert(title: string, content: string) { + this.dialog.open(AlertComponent, {data: {title: title, content: content}}) + } +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 2aab2ac..14b230f 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -14,6 +14,7 @@ import { MatSelectModule } from '@angular/material/select'; import { MatOptionModule } from '@angular/material/core'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner' +import {MatDialogModule} from '@angular/material/dialog'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @@ -23,11 +24,13 @@ import { FooterComponent } from './footer/footer.component'; import { GridComponent } from './grid/grid.component'; -import { AccountService } from './account.service'; +import { AccountService } from './login/account.service'; import { LoginComponent } from './login/login.component' import { HttpClientModule } from '@angular/common/http'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { AdminComponent } from './admin/admin.component'; +import { AlertComponent } from './alert/alert.component'; +import { AlertService } from './alert/alert.service'; @NgModule({ declarations: [ @@ -37,7 +40,8 @@ FooterComponent, GridComponent, LoginComponent, - AdminComponent + AdminComponent, + AlertComponent, ], imports: [ BrowserModule, @@ -60,8 +64,12 @@ MatSelectModule, MatOptionModule, MatProgressSpinnerModule, + MatDialogModule, ], - providers: [AccountService], + providers: [ + AccountService, + AlertService, + ], bootstrap: [AppComponent] }) export class AppModule { } diff --git a/src/app/login/account.service.spec.ts b/src/app/login/account.service.spec.ts new file mode 100644 index 0000000..2ffad6f --- /dev/null +++ b/src/app/login/account.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AccountService } from './account.service'; + +describe('AccountService', () => { + let service: AccountService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AccountService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/login/account.service.ts b/src/app/login/account.service.ts new file mode 100644 index 0000000..ca31e9f --- /dev/null +++ b/src/app/login/account.service.ts @@ -0,0 +1,164 @@ +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?') + } + }) + } +} diff --git a/src/app/login/login.component.ts b/src/app/login/login.component.ts index c8f045f..89f243c 100644 --- a/src/app/login/login.component.ts +++ b/src/app/login/login.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, NgForm, Validators } from '@angular/forms'; import { environment } from 'src/environments/environment'; -import { AccountService } from '../account.service'; +import { AccountService } from './account.service'; class LoginInformation { constructor(public username: string, public password: string) { diff --git a/src/app/toolbar/toolbar.component.ts b/src/app/toolbar/toolbar.component.ts index f05f027..bb44218 100644 --- a/src/app/toolbar/toolbar.component.ts +++ b/src/app/toolbar/toolbar.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { AccountService } from '../account.service'; +import { AccountService } from '../login/account.service'; @Component({