Reviewed-on: #20 Co-authored-by: Patrick Müller <mail@pmueller.me> Co-committed-by: Patrick Müller <mail@pmueller.me>
This commit was merged in pull request #20.
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import {Component, OnDestroy, OnInit} from '@angular/core';
|
||||
import {Subject} from 'rxjs';
|
||||
import {takeUntil} from 'rxjs/operators';
|
||||
import {HttpErrorResponse} from '@angular/common/http';
|
||||
import {ApiService} from '../../services/api.service';
|
||||
import {UtilsService} from '../../services/utils.service';
|
||||
import {AdminAuthService} from '../../services/admin-auth.service';
|
||||
import {Event} from '../../models/event';
|
||||
import {Session} from '../../models/session';
|
||||
import {User} from '../../models/user';
|
||||
|
||||
@Component({
|
||||
@@ -19,15 +20,20 @@ export class AdminComponent implements OnInit, OnDestroy {
|
||||
isLoggedIn: boolean = false;
|
||||
events: Event[] = [];
|
||||
selectedCalendar: string = '';
|
||||
password: string = '';
|
||||
name: string = '';
|
||||
email: string = '';
|
||||
eventFilter: string = 'future'; // Default value for filter
|
||||
eventSorting: string = 'start_asc'; // Default value for sorting
|
||||
isActive: boolean = false;
|
||||
registerEmail: string = '';
|
||||
registerPassword: string = '';
|
||||
registerPasswordConfirm: string = '';
|
||||
|
||||
/**
|
||||
* Why the page is not showing events, when it is not.
|
||||
*
|
||||
* 'denied' and 'unavailable' are kept apart on purpose. Only a 401 is worth
|
||||
* sending someone to the login page; bouncing them there for a 403 produces
|
||||
* a loop where signing in succeeds and lands them straight back here, and
|
||||
* bouncing them for an unreachable API produces the same loop with no way
|
||||
* out at all.
|
||||
*/
|
||||
failure: 'denied' | 'unavailable' | null = null;
|
||||
|
||||
constructor(
|
||||
private api: ApiService
|
||||
@@ -35,16 +41,29 @@ export class AdminComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (UtilsService.getSessionInfoFromLocalStorage().sessionId !== -1) {
|
||||
this.api.checkSession(UtilsService.getSessionInfoFromLocalStorage()).pipe(takeUntil(this.destroy$)).subscribe((user: User) => {
|
||||
if(user.userId != null && user.userId !== -1) {
|
||||
this.isLoggedIn = true;
|
||||
this.name = user.fullName;
|
||||
this.isActive = user.isActive;
|
||||
this.getEvents();
|
||||
this.api.me().pipe(takeUntil(this.destroy$)).subscribe({
|
||||
next: (user: User) => {
|
||||
this.isLoggedIn = true;
|
||||
this.name = user.fullName;
|
||||
UtilsService.saveNameToLocalStorage(user.fullName);
|
||||
|
||||
// Signed in, but not for this app. The API would answer 403 to
|
||||
// every events call, so say so once instead of failing per call.
|
||||
if (!user.apps.includes('calendar')) {
|
||||
this.failure = 'denied';
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.getEvents();
|
||||
},
|
||||
error: (error: HttpErrorResponse) => {
|
||||
if (error.status === 401) {
|
||||
AdminAuthService.goToLogin();
|
||||
return;
|
||||
}
|
||||
this.failure = error.status === 403 ? 'denied' : 'unavailable';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
@@ -59,20 +78,33 @@ export class AdminComponent implements OnInit, OnDestroy {
|
||||
return;
|
||||
}
|
||||
|
||||
this.api.getEvents(this.selectedCalendar).pipe(takeUntil(this.destroy$)).subscribe((events: Event[]): void => {
|
||||
for (let event of events) {
|
||||
if(event.status !== 'DELETED') {
|
||||
this.events.push({
|
||||
...event,
|
||||
startDateTime: new Date(event.startDateTime),
|
||||
endDateTime: new Date(event.endDateTime),
|
||||
createdDate: new Date(event.createdDate),
|
||||
lastModifiedDate: new Date(event.lastModifiedDate)
|
||||
});
|
||||
this.api.getEvents(this.selectedCalendar).pipe(takeUntil(this.destroy$)).subscribe({
|
||||
next: (events: Event[]): void => {
|
||||
for (let event of events) {
|
||||
if (event.status !== 'DELETED') {
|
||||
this.events.push({
|
||||
...event,
|
||||
startDateTime: new Date(event.startDateTime),
|
||||
endDateTime: new Date(event.endDateTime),
|
||||
createdDate: new Date(event.createdDate),
|
||||
lastModifiedDate: new Date(event.lastModifiedDate)
|
||||
});
|
||||
}
|
||||
}
|
||||
this.filterEvents();
|
||||
this.sortEvents();
|
||||
},
|
||||
// Without this a failed load is indistinguishable from an empty
|
||||
// calendar - which is exactly what the old bundle looks like against
|
||||
// the post-cutover API, and how a deploy in progress gets mistaken for
|
||||
// lost data.
|
||||
error: (error: HttpErrorResponse): void => {
|
||||
if (error.status === 401) {
|
||||
AdminAuthService.goToLogin();
|
||||
return;
|
||||
}
|
||||
this.failure = error.status === 403 ? 'denied' : 'unavailable';
|
||||
}
|
||||
this.filterEvents();
|
||||
this.sortEvents();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -156,68 +188,20 @@ export class AdminComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
login(): void {
|
||||
this.api.login(this.email, this.password).pipe(takeUntil(this.destroy$)).subscribe((session: Session): void => {
|
||||
if(session.sessionId != null && session.sessionId !== -1) {
|
||||
UtilsService.saveSessionInfoToLocalStorage(session.sessionId, session.sessionKey);
|
||||
|
||||
// Get user info
|
||||
this.api.checkSession(UtilsService.getSessionInfoFromLocalStorage()).pipe(takeUntil(this.destroy$)).subscribe((user: User) => {
|
||||
if(user.userId != null && user.userId !== -1) {
|
||||
this.isLoggedIn = true;
|
||||
this.name = user.fullName;
|
||||
this.isActive = user.isActive;
|
||||
this.getEvents();
|
||||
} else {
|
||||
alert('Login unsuccessful. Please check if you provided the correct username and password.');
|
||||
}
|
||||
});
|
||||
}
|
||||
}, (error) => {
|
||||
alert('Login unsuccessful. Reported problem from server: ' + error?.error?.message);
|
||||
});
|
||||
}
|
||||
|
||||
register(): void {
|
||||
this.api.register(this.registerEmail, this.name, this.registerPassword).pipe(takeUntil(this.destroy$)).subscribe((session: Session): void => {
|
||||
if(session.sessionId != null && session.sessionId !== -1) {
|
||||
UtilsService.saveSessionInfoToLocalStorage(session.sessionId, session.sessionKey);
|
||||
this.isLoggedIn = true;
|
||||
this.getEvents();
|
||||
alert('An email was sent to your Nachklang address. Please click the link in the email to activate your account. You can\'t use this application before the activation.');
|
||||
} else {
|
||||
alert('Registration unsuccessful. Please contact Patrick.');
|
||||
}
|
||||
}, (error) => {
|
||||
alert('Registration unsuccessful. Reported problem from server: ' + error?.error?.message);
|
||||
});
|
||||
/**
|
||||
* There is no sign-in form here any more, and no account creation: accounts
|
||||
* exist only by invitation from the admin app. Both are one redirect.
|
||||
*/
|
||||
signIn(): void {
|
||||
AdminAuthService.goToLogin();
|
||||
}
|
||||
|
||||
logout(): void {
|
||||
UtilsService.clearSessionInfo();
|
||||
this.isLoggedIn = false;
|
||||
UtilsService.clearName();
|
||||
void AdminAuthService.signOut();
|
||||
}
|
||||
|
||||
checkUserInactive(): boolean {
|
||||
return !this.isActive;
|
||||
}
|
||||
|
||||
checkPasswordsMatch(): boolean {
|
||||
return this.registerPassword === this.registerPasswordConfirm;
|
||||
}
|
||||
|
||||
checkPasswordPolicy(): boolean {
|
||||
let isLongEnough = this.registerPassword.length >= 12;
|
||||
|
||||
var lowercaseRegex = /[a-z]/g
|
||||
let hasLowercase = lowercaseRegex.test(this.registerPassword);
|
||||
|
||||
var uppercaseRegex = /[A-Z]/g
|
||||
let hasUppercase = uppercaseRegex.test(this.registerPassword);
|
||||
|
||||
var numberRegex = /[0-9]/g
|
||||
let hasNumbers = numberRegex.test(this.registerPassword);
|
||||
|
||||
return isLongEnough && hasLowercase && hasUppercase && hasNumbers;
|
||||
reload(): void {
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user