diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 37e5b2dd3..e9d6f4b08 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -87,6 +87,7 @@ import { LoggingInterceptorService } from './services/logging-interceptor.servic import { PopupQuestionPipe } from './modals/popup-question.pipe'; import '@teamhive/capacitor-video-recorder'; import { tokenInterceptor } from './interceptors/token.interceptors'; +import { ChatTokenInterceptor } from './interceptors/chatToken.interceptor'; import { InputFilterDirective } from './services/directives/input-filter.directive'; import { VisibilityDirective } from './services/directives/visibility.directive'; @@ -216,7 +217,8 @@ import { FirebaseX } from '@ionic-native/firebase-x/ngx'; */ DocumentViewer, FFMpeg, { provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptorService, multi: true }, - tokenInterceptor + tokenInterceptor, + /* ChatTokenInterceptor */ ], bootstrap: [AppComponent], diff --git a/src/app/interceptors/chatToken.interceptor.ts b/src/app/interceptors/chatToken.interceptor.ts new file mode 100644 index 000000000..c1929a01e --- /dev/null +++ b/src/app/interceptors/chatToken.interceptor.ts @@ -0,0 +1,152 @@ +import { Injectable } from '@angular/core'; +import { + HttpInterceptor, + HttpRequest, + HttpHandler, + HttpEvent, + HttpErrorResponse, + HTTP_INTERCEPTORS, + HttpHeaders, +} from '@angular/common/http'; +import { Observable, throwError, BehaviorSubject } from 'rxjs'; +import { catchError, switchMap, filter, take } from 'rxjs/operators'; +import { HttpClient } from '@angular/common/http'; +import { Router } from '@angular/router'; +import { SessionStore } from '../store/session.service'; +import { environment } from "src/environments/environment"; +import { PermissionService } from '../services/permission.service'; +import { NetworkServiceService , ConnectionStatus} from 'src/app/services/network-service.service'; +import { RochetChatConnectorService } from 'src/app/services/chat/rochet-chat-connector.service'; + +@Injectable() +export class ChatTokenInterceptor implements HttpInterceptor { + private isRefreshing = false; + headers: HttpHeaders; + options: any; + private refreshTokenSubject: BehaviorSubject = new BehaviorSubject( + null + ); + + private excludedDomain = 'https://gdchat-dev.dyndns.info';// Add other domains as needed + + constructor(private http: HttpClient, private router: Router,private p: PermissionService,private NetworkServiceService: NetworkServiceService, + private RochetChatConnectorService: RochetChatConnectorService) {} + + intercept( + request: HttpRequest, + next: HttpHandler + ): Observable> { + if (this.shouldExcludeDomain(request)) { + return next.handle(request); + } + + return next.handle(request).pipe( + catchError((error) => { + if (error instanceof HttpErrorResponse && error.status === 401) { + return this.handle401Error(request, next); + } else { + return throwError(error); + } + }) + ); + } + + private shouldExcludeDomain(request: HttpRequest): boolean { + const url = request.url.toLowerCase(); + return !url.includes(this.excludedDomain.toLowerCase()); + } + + private handle401Error( + request: HttpRequest, + next: HttpHandler + ): Observable> { + if (!this.isRefreshing) { + this.isRefreshing = true; + this.refreshTokenSubject.next(null); + + return this.refreshToken().pipe( + switchMap((token: any) => { + this.isRefreshing = false; + + let data = { + status: token['status'], + data: { + userId: token['data'].userId, + authToken: token['data'].authToken + } + } + SessionStore.user.ChatData = data + SessionStore.save() + this.setheader() + + + + this.refreshTokenSubject.next(token.Authorization); + return next.handle(this.addToken(request, token.Authorization)); + }) + ); + } else { + return this.refreshTokenSubject.pipe( + filter((token) => token != null), + take(1), + switchMap((jwt) => { + return next.handle(this.addToken(request, jwt)); + }) + ); + } + } + + private addToken(request: HttpRequest, token: string) { + return request.clone({ + /* setHeaders: { + Authorization: `Bearer ${token}`, + }, */ + }); + } + + private refreshToken(): Observable { + return this.http + .get(environment.apiURL + 'UserAuthentication/RegenereChatToken', { + /* refreshToken: SessionStore.user.RefreshToken, */ + }) + .pipe( + catchError((error) => { + // Handle token refresh failure + console.log('ChatToken refresh failed:', error); + return throwError(error); + }) + ); + } + + + + setheader() { + try { + + if (this.p.userPermission(this.p.permissionList.Chat.access) && SessionStore.user.ChatData) { + this.headers = new HttpHeaders();; + + if (this.p.userPermission(this.p.permissionList.Chat.access)) { + // + this.headers = this.headers.set('X-User-Id', SessionStore.user.ChatData.data.userId); + this.headers = this.headers.set('X-Auth-Token', SessionStore.user.ChatData.data.authToken); + this.options = { + headers: this.headers, + }; + + } + } + } catch (error) { + + } + } +} + + + +export const tokenInterceptor = { + provide: HTTP_INTERCEPTORS, + useClass: ChatTokenInterceptor, + multi: true + }; + \ No newline at end of file diff --git a/src/app/interceptors/token.interceptors.ts b/src/app/interceptors/token.interceptors.ts index 1a4ad808d..13e4ebe71 100644 --- a/src/app/interceptors/token.interceptors.ts +++ b/src/app/interceptors/token.interceptors.ts @@ -14,6 +14,7 @@ import { catchError, filter, take, switchMap, tap } from "rxjs/operators"; import { SessionStore } from '../store/session.service'; import { environment } from "src/environments/environment"; import { Router } from "@angular/router"; +import { HttpErrorHandle } from 'src/app/services/http-error-handle.service'; @Injectable() export class TokenInterceptor implements HttpInterceptor { @@ -24,7 +25,7 @@ export class TokenInterceptor implements HttpInterceptor { private excludedDomains = ['Login', environment.apiChatUrl]; // Add the domains you want to exclude - constructor(private http: HttpClient, private router: Router,) { } + constructor(private http: HttpClient, private router: Router,private httpErrorHandle: HttpErrorHandle,) { } intercept( @@ -119,8 +120,9 @@ export class TokenInterceptor implements HttpInterceptor { window.location.pathname = '/auth' } else { /* const pathBeforeGoOut = window.location.pathname */ - this.router.navigateByUrl('/auth', { replaceUrl: true }); - + this.router.navigateByUrl('/auth', { replaceUrl: true }).then(() =>{ + this.httpErrorHandle.httpsSucessMessagge('sessonExpired') + }) } return of(false); }) diff --git a/src/app/pages/gabinete-digital/viewer-attachment/viewer-attachment.page.scss b/src/app/pages/gabinete-digital/viewer-attachment/viewer-attachment.page.scss index 62d3f8d8d..a5deba0cc 100644 --- a/src/app/pages/gabinete-digital/viewer-attachment/viewer-attachment.page.scss +++ b/src/app/pages/gabinete-digital/viewer-attachment/viewer-attachment.page.scss @@ -68,6 +68,7 @@ iframe { .container-img { background-image: url(/assets/gif/theme/gov/Blocks-loader.svg); + background-size: 100px; background-repeat: no-repeat; background-position-x: center; background-position-y: center; diff --git a/src/app/pages/search/search.page.ts b/src/app/pages/search/search.page.ts index ec9b21a31..e0e1779e0 100644 --- a/src/app/pages/search/search.page.ts +++ b/src/app/pages/search/search.page.ts @@ -119,16 +119,16 @@ export class SearchPage implements OnInit { if (this.currentPath.includes('/home/agenda')) { this.type = "Agenda" - + } else if (this.currentPath.includes('/home/gabinete-digital')) { this.type = "AccoesPresidenciais & ArquivoDespachoElect" - + } else if (this.currentPath.includes('/home/publications')) { this.type = "AccoesPresidenciais" - + } else { - + } } } @@ -381,7 +381,7 @@ export class SearchPage implements OnInit { this.showLoader = true; this.search.basicSearch(this.searchSubject, searchDocumentDate,searchDocumentDateEnd, this.searchSenderId , this.searchOrganicEntiryCode, this.searchDocTypeId, '0').subscribe(res => { - + if (!res.Categories.length) { this.searchResult = "Não encontramos o que procura"; } @@ -429,7 +429,7 @@ export class SearchPage implements OnInit { console.log('enter text'); } else { - + this.search.searchForDoc(this.searchSubject, searchDocumentDate, this.searchSenderId , this.searchOrganicEntiryCode, this.searchDocTypeId, '8').subscribe(res => { this.showLoader = true; diff --git a/src/app/services/http-error-handle.service.ts b/src/app/services/http-error-handle.service.ts index b3bab58fd..49b039f1a 100644 --- a/src/app/services/http-error-handle.service.ts +++ b/src/app/services/http-error-handle.service.ts @@ -223,7 +223,9 @@ export class HttpErrorHandle { case 'new event to aprove': this.toastService._successMessage('Enviado para os eventos para aprovação!'); break; - + case 'sessonExpired': + this.toastService._successMessage('Sessão expirada, por favor efectuar login novamente!'); + break; default: this.toastService._successMessage('Processo efetuado!') break; diff --git a/src/app/shared/gabinete-digital/generic/task-details/task-details.page.html b/src/app/shared/gabinete-digital/generic/task-details/task-details.page.html index 6c0c20607..f729bd008 100644 --- a/src/app/shared/gabinete-digital/generic/task-details/task-details.page.html +++ b/src/app/shared/gabinete-digital/generic/task-details/task-details.page.html @@ -123,12 +123,12 @@
- -