This commit is contained in:
Polianin Nikita 2024-08-04 23:03:06 +03:00
parent e82a0ecb5e
commit e9735a4e99
8 changed files with 46 additions and 42 deletions

View File

@ -98,7 +98,7 @@ export class RequestBuilder {
data: null, data: null,
silenceMode: false, silenceMode: false,
withCredentials: false withCredentials: false
} };
} }
public reset(): void { public reset(): void {

View File

@ -73,17 +73,16 @@ export default abstract class ApiService implements SetRequestBuilderAfterBuild
} }
protected get combinedUrl() { protected get combinedUrl() {
return ApiService.addQuery(ApiService.combineUrls(this.apiUrl, AvailableVersion[this.version], this.basePath, this.request.endpoint), this.request.queryParams) return ApiService.addQuery(ApiService.combineUrls(this.apiUrl, AvailableVersion[this.version], this.basePath, this.request.endpoint), this.request.queryParams);
} }
private makeHttpRequest<Type>(method: 'get' | 'post' | 'delete' | 'put'): Observable<Type> { private makeHttpRequest<Type>(method: 'get' | 'post' | 'delete' | 'put'): Observable<Type> {
const doneEndpoint = this.combinedUrl; const doneEndpoint = this.combinedUrl;
return this.tokenRefreshService.getTokenRefreshing$().pipe( return this.tokenRefreshService.getTokenRefreshing$().pipe(
filter(refreshing => !refreshing), filter(isRefreshing => !isRefreshing),
take(1), switchMap(() =>
switchMap(_ => { this.http.request<Type>(method, doneEndpoint, {
return this.http.request<Type>(method, doneEndpoint, {
withCredentials: this.request.withCredentials, withCredentials: this.request.withCredentials,
headers: this.request.httpHeaders, headers: this.request.httpHeaders,
body: this.request.data body: this.request.data
@ -97,8 +96,8 @@ export default abstract class ApiService implements SetRequestBuilderAfterBuild
this.request = RequestBuilder.getStandardRequestData(); this.request = RequestBuilder.getStandardRequestData();
throw error; throw error;
}) })
); )
}) )
); );
} }
@ -138,7 +137,7 @@ export default abstract class ApiService implements SetRequestBuilderAfterBuild
return this; return this;
const authToken = AuthToken.httpHeader((JSON.parse(token) as AuthToken)); const authToken = AuthToken.httpHeader((JSON.parse(token) as AuthToken));
authToken.keys().forEach(key => this.request.httpHeaders = this.request.httpHeaders.append(key, authToken.get(key) ?? '')) authToken.keys().forEach(key => this.request.httpHeaders = this.request.httpHeaders.append(key, authToken.get(key) ?? ''));
return this; return this;
} }

View File

@ -26,7 +26,7 @@ export class ScheduleService extends ApiService {
.post<ScheduleResponse[]>(); .post<ScheduleResponse[]>();
} }
public getByGroup(id : number, isEven: boolean | null = null, disciplines: Array<number> | null = null, professors: Array<number> | null = null, lectureHalls: Array<number> | null = null) { public getByGroup(id: number, isEven: boolean | null = null, disciplines: Array<number> | null = null, professors: Array<number> | null = null, lectureHalls: Array<number> | null = null) {
return this.createRequestBuilder() return this.createRequestBuilder()
.setEndpoint('GetByGroup/' + id.toString()) .setEndpoint('GetByGroup/' + id.toString())
.setQueryParams({isEven: isEven, disciplines: disciplines, professors: professors, lectureHalls: lectureHalls}) .setQueryParams({isEven: isEven, disciplines: disciplines, professors: professors, lectureHalls: lectureHalls})
@ -34,7 +34,7 @@ export class ScheduleService extends ApiService {
.get<ScheduleResponse[]>(); .get<ScheduleResponse[]>();
} }
public getByProfessor(id : number, isEven: boolean | null = null, disciplines: Array<number> | null = null, groups: Array<number> | null = null, lectureHalls: Array<number> | null = null) { public getByProfessor(id: number, isEven: boolean | null = null, disciplines: Array<number> | null = null, groups: Array<number> | null = null, lectureHalls: Array<number> | null = null) {
return this.createRequestBuilder() return this.createRequestBuilder()
.setEndpoint('GetByProfessor/' + id.toString()) .setEndpoint('GetByProfessor/' + id.toString())
.setQueryParams({isEven: isEven, disciplines: disciplines, groups: groups, lectureHalls: lectureHalls}) .setQueryParams({isEven: isEven, disciplines: disciplines, groups: groups, lectureHalls: lectureHalls})
@ -42,7 +42,7 @@ export class ScheduleService extends ApiService {
.get<ScheduleResponse[]>(); .get<ScheduleResponse[]>();
} }
public getByLectureHall(id : number, isEven: boolean | null = null, disciplines: Array<number> | null = null, groups: Array<number> | null = null, professors: Array<number> | null = null) { public getByLectureHall(id: number, isEven: boolean | null = null, disciplines: Array<number> | null = null, groups: Array<number> | null = null, professors: Array<number> | null = null) {
return this.createRequestBuilder() return this.createRequestBuilder()
.setEndpoint('GetByLectureHall/' + id.toString()) .setEndpoint('GetByLectureHall/' + id.toString())
.setQueryParams({isEven: isEven, disciplines: disciplines, groups: groups, professors: professors}) .setQueryParams({isEven: isEven, disciplines: disciplines, groups: groups, professors: professors})
@ -50,7 +50,7 @@ export class ScheduleService extends ApiService {
.get<ScheduleResponse[]>(); .get<ScheduleResponse[]>();
} }
public getByDiscipline(id : number, isEven: boolean | null = null, groups: Array<number> | null = null, professors: Array<number> | null = null, lectureHalls: Array<number> | null = null) { public getByDiscipline(id: number, isEven: boolean | null = null, groups: Array<number> | null = null, professors: Array<number> | null = null, lectureHalls: Array<number> | null = null) {
return this.createRequestBuilder() return this.createRequestBuilder()
.setEndpoint('GetByDiscipline/' + id.toString()) .setEndpoint('GetByDiscipline/' + id.toString())
.setQueryParams({isEven: isEven, groups: groups, professors: professors, lectureHalls: lectureHalls}) .setQueryParams({isEven: isEven, groups: groups, professors: professors, lectureHalls: lectureHalls})

View File

@ -2,7 +2,7 @@ import {Component} from '@angular/core';
import {RouterOutlet} from '@angular/router'; import {RouterOutlet} from '@angular/router';
import {FooterComponent} from "@component/common/footer/footer.component"; import {FooterComponent} from "@component/common/footer/footer.component";
import localeRu from '@angular/common/locales/ru'; import localeRu from '@angular/common/locales/ru';
import { registerLocaleData } from '@angular/common'; import {registerLocaleData} from '@angular/common';
import {FocusNextDirective} from "@/directives/focus-next.directive"; import {FocusNextDirective} from "@/directives/focus-next.directive";
import {TokenRefreshService} from "@service/token-refresh.service"; import {TokenRefreshService} from "@service/token-refresh.service";

View File

@ -1,8 +1,8 @@
import { ApplicationConfig } from '@angular/core'; import {ApplicationConfig} from '@angular/core';
import { provideRouter } from '@angular/router'; import {provideRouter} from '@angular/router';
import { routes } from './app.routes'; import {routes} from './app.routes';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; import {provideAnimationsAsync} from '@angular/platform-browser/animations/async';
import {provideHttpClient} from "@angular/common/http"; import {provideHttpClient} from "@angular/common/http";
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {

View File

@ -1,5 +1,6 @@
<mat-sidenav-container class="schedule"> <mat-sidenav-container class="schedule">
<app-tabs (eventResult)="result($event)"/> <app-tabs (eventResult)="result($event)"/>
<app-table-header [startWeek]="startWeek" [currentWeek]="currentWeek" (weekEvent)="handleWeekEvent($event)" #tableHeader/> <app-table-header [startWeek]="startWeek" [currentWeek]="currentWeek" (weekEvent)="handleWeekEvent($event)"
#tableHeader/>
<app-table [currentWeek]="currentWeek" [startWeek]="startWeek" [data]="data" [isLoad]="isLoadTable"/> <app-table [currentWeek]="currentWeek" [startWeek]="startWeek" [data]="data" [isLoad]="isLoadTable"/>
</mat-sidenav-container> </mat-sidenav-container>

View File

@ -61,7 +61,7 @@ export class AuthService {
const token = localStorage.getItem(ApiService.tokenKey); const token = localStorage.getItem(ApiService.tokenKey);
if (!token) if (!token)
return of(); return of({} as TokenResponse);
const authToken = JSON.parse(token) as AuthToken; const authToken = JSON.parse(token) as AuthToken;

View File

@ -1,7 +1,8 @@
import {BehaviorSubject, interval, Subscription, switchMap} from "rxjs"; import {BehaviorSubject, filter, interval, Subscription, switchMap} from "rxjs";
import {Injectable} from "@angular/core"; import {Injectable} from "@angular/core";
import {AuthService} from "@service/auth.service"; import {AuthService} from "@service/auth.service";
import {environment} from "@environment"; import {environment} from "@environment";
import ApiService from "@api/api.service";
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',
@ -15,12 +16,12 @@ export class TokenRefreshService {
this.setRefreshTokenExpireMs(AuthService.tokenExpiresIn.getTime() - 1000 - Date.now()); this.setRefreshTokenExpireMs(AuthService.tokenExpiresIn.getTime() - 1000 - Date.now());
authService.tokenChangeError.subscribe(_ => { authService.tokenChangeError.subscribe(_ => {
console.log('Token change error event received'); console.debug('Token change error event received');
this.tokenRefreshing$.next(false); this.tokenRefreshing$.next(false);
this.stopTokenRefresh(); this.stopTokenRefresh();
}); });
authService.expireTokenChange.subscribe(date => { authService.expireTokenChange.subscribe(date => {
console.log('Expire token change event received:', date); console.debug('Expire token change event received:', date);
this.setRefreshTokenExpireMs(date.getTime() - 1000 - Date.now()); this.setRefreshTokenExpireMs(date.getTime() - 1000 - Date.now());
}); });
} }
@ -29,10 +30,15 @@ export class TokenRefreshService {
if (date) if (date)
this.refreshTokenExpireMs = new Date(date).getTime() - 1000 - Date.now(); this.refreshTokenExpireMs = new Date(date).getTime() - 1000 - Date.now();
if (!this.tokenRefreshSubscription || this.tokenRefreshSubscription.closed) { console.debug(this.tokenRefreshSubscription);
if (this.tokenRefreshSubscription && !this.tokenRefreshSubscription.closed)
return;
this.tokenRefreshSubscription = interval(this.refreshTokenExpireMs).pipe( this.tokenRefreshSubscription = interval(this.refreshTokenExpireMs).pipe(
filter(isRefreshing => !isRefreshing),
switchMap(() => { switchMap(() => {
this.tokenRefreshing$.next(true); this.tokenRefreshing$.next(true);
console.debug('Send query to refresh token');
return this.authService.refreshToken(); return this.authService.refreshToken();
}) })
).subscribe({ ).subscribe({
@ -40,12 +46,11 @@ export class TokenRefreshService {
this.tokenRefreshing$.next(false); this.tokenRefreshing$.next(false);
}, },
error: error => { error: error => {
console.error('Token refresh error:', error);
this.tokenRefreshing$.next(false); this.tokenRefreshing$.next(false);
localStorage.removeItem(ApiService.tokenKey);
} }
}); });
} }
}
public getTokenRefreshing$(): BehaviorSubject<boolean> { public getTokenRefreshing$(): BehaviorSubject<boolean> {
return this.tokenRefreshing$; return this.tokenRefreshing$;
@ -60,13 +65,12 @@ export class TokenRefreshService {
public setRefreshTokenExpireMs(expireMs: number): void { public setRefreshTokenExpireMs(expireMs: number): void {
if (expireMs < environment.retryDelay) if (expireMs < environment.retryDelay)
expireMs = 3000; expireMs = environment.retryDelay;
console.log(expireMs);
this.refreshTokenExpireMs = expireMs; this.refreshTokenExpireMs = expireMs;
console.log(expireMs);
this.stopTokenRefresh(); this.stopTokenRefresh();
this.startTokenRefresh(); this.startTokenRefresh();
} }
} }