Add ping route and maintenance mode handling
This commit is contained in:
parent
cc266c8e39
commit
52fd6d6d2f
|
@ -106,6 +106,12 @@ Route::get('/owner_image', function() {
|
|||
);
|
||||
});
|
||||
|
||||
Route::get('/ping', function() {
|
||||
return response()->json([
|
||||
'message' => 'pong'
|
||||
]);
|
||||
});
|
||||
|
||||
Route::post('/cron/execute', function(Request $request) {
|
||||
//Go to app/Console/Kernel.php to view schedules
|
||||
if(config('cron.external_cron_enabled') && $request->header('Cron') == config('cron.execution_code')) {
|
||||
|
|
|
@ -37,7 +37,7 @@ const genericRetryStrategy = ({
|
|||
// retry after 1s, 2s, etc...
|
||||
return timer(retryAttempt * scalingDuration);
|
||||
}),
|
||||
finalize(() => console.log('We are done!'))
|
||||
//finalize(() => console.log('We are done!'))
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -86,15 +86,26 @@ export class AuthInterceptor implements HttpInterceptor {
|
|||
}
|
||||
|
||||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<Object>> {
|
||||
//If maintenance mode is enabled, return 503 except for ping
|
||||
if (this.api.maintenanceMode && !req.url.includes("ping")) {
|
||||
return new Observable<HttpEvent<Object>>((observer) => {
|
||||
observer.next(new HttpResponse({
|
||||
body: { message: "Maintenance mode" },
|
||||
status: 503,
|
||||
statusText: "Service Unavailable",
|
||||
url: req.url
|
||||
}));
|
||||
observer.complete();
|
||||
});
|
||||
}
|
||||
return next.handle(this.updateRequest(req)).pipe(
|
||||
retryWhen(genericRetryStrategy({
|
||||
maxRetryAttempts: 3,
|
||||
scalingDuration: 1,
|
||||
excludedStatusCodes: [304, 400, 404, 419, 500, 503],
|
||||
excludedUrls: ["login", "logout", "me", "impersonate", "stop_impersonating"]
|
||||
excludedUrls: ["login", "logout", "me", "impersonate", "stop_impersonating", "ping"]
|
||||
})),
|
||||
catchError(error => {
|
||||
console.log(error);
|
||||
if (error.status === 304) {
|
||||
//Return current response as successfully
|
||||
return new Observable<HttpEvent<Object>>((observer) => {
|
||||
|
@ -107,6 +118,9 @@ export class AuthInterceptor implements HttpInterceptor {
|
|||
}));
|
||||
observer.complete();
|
||||
});
|
||||
} else if (error.status === 503) {
|
||||
this.api.maintenanceMode = true;
|
||||
return throwError(() => error);
|
||||
} else if (error.status === 419) {
|
||||
return new Observable<HttpEvent<Object>>((observer) => {
|
||||
this.api.get("csrf-cookie").then(() => {
|
||||
|
@ -115,7 +129,6 @@ export class AuthInterceptor implements HttpInterceptor {
|
|||
});
|
||||
}
|
||||
if (error instanceof HttpErrorResponse && !req.url.includes('login') && !req.url.includes('me') && !req.url.includes('logout')) {
|
||||
console.log("Error: " + error.status);
|
||||
if (error.status === 400) {
|
||||
this.router.navigate(["logout"]);
|
||||
return throwError(() => error);
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
<div class="text-center">
|
||||
<h3 *ngIf="available !== undefined">{{ 'list.your_availability_is'|translate }} <b>{{ available ? ("available"|translate|uppercase) : ("unavailable"|translate|uppercase) }}{{ manual_mode ? "" : " ("+('programmed'|translate)+")" }}</b></h3>
|
||||
<div id="availability-btn-group">
|
||||
<button (click)="changeAvailibility(1)" type="button" id="activate-btn" class="btn btn-lg btn-success me-1">{{ 'set_available'|translate|ftitlecase }}</button>
|
||||
<button (click)="changeAvailibility(0)" type="button" id="deactivate-btn" class="btn btn-lg btn-danger">{{ 'set_unavailable'|translate|ftitlecase }}</button>
|
||||
<button (click)="changeAvailibility(1)" [disabled]="api.maintenanceMode" type="button" id="activate-btn" class="btn btn-lg btn-success me-1">{{ 'set_available'|translate|ftitlecase }}</button>
|
||||
<button (click)="changeAvailibility(0)" [disabled]="api.maintenanceMode" type="button" id="deactivate-btn" class="btn btn-lg btn-danger">{{ 'set_unavailable'|translate|ftitlecase }}</button>
|
||||
</div>
|
||||
<ng-container *ngIf="manual_mode !== undefined">
|
||||
<button type="button" class="btn btn-secondary" *ngIf="manual_mode" (click)="updateManualMode(0)">
|
||||
<button type="button" class="btn btn-secondary" *ngIf="manual_mode" (click)="updateManualMode(0)" [disabled]="api.maintenanceMode">
|
||||
{{ 'list.enable_schedules'|translate }}
|
||||
</button>
|
||||
<button type="button" class="btn btn-secondary" *ngIf="!manual_mode" (click)="updateManualMode(1)">
|
||||
<button type="button" class="btn btn-secondary" *ngIf="!manual_mode" (click)="updateManualMode(1)" [disabled]="api.maintenanceMode">
|
||||
{{ 'list.disable_schedules'|translate }}
|
||||
</button>
|
||||
<br>
|
||||
</ng-container>
|
||||
<button type="button" class="btn btn-lg" (click)="openScheduleModal()">
|
||||
<button type="button" class="btn btn-lg" (click)="openScheduleModal()" [disabled]="api.maintenanceMode">
|
||||
{{ 'list.update_schedules'|translate }}
|
||||
</button>
|
||||
</div>
|
||||
<owner-image></owner-image>
|
||||
<div class="text-center" *ngIf="auth.profile.can('alerts-create')">
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-danger" (click)="addAlert('full')" [disabled]="!api.availableUsers || api.availableUsers! < 5 || alertLoading">
|
||||
<button type="button" class="btn btn-danger" (click)="addAlert('full')" [disabled]="!api.availableUsers || api.availableUsers! < 5 || alertLoading || api.maintenanceMode">
|
||||
🚒 Richiedi squadra completa
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning" (click)="addAlert('support')" [disabled]="!api.availableUsers || api.availableUsers! < 2 || alertLoading">
|
||||
<button type="button" class="btn btn-warning" (click)="addAlert('support')" [disabled]="!api.availableUsers || api.availableUsers! < 2 || alertLoading || api.maintenanceMode">
|
||||
Richiedi squadra di supporto 🧯
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<app-table [sourceType]="'list'" (changeAvailability)="changeAvailibility($event.newState, $event.user)" (moreDetails)="openUserInfoPage($event.rowId)" #table></app-table>
|
||||
<div class="text-center">
|
||||
<button (click)="requestTelegramToken()" class="btn btn-md btn-success mt-3">{{ 'list.connect_telegram_bot'|translate }}</button>
|
||||
<button (click)="requestTelegramToken()" [disabled]="api.maintenanceMode" class="btn btn-md btn-success mt-3">{{ 'list.connect_telegram_bot'|translate }}</button>
|
||||
<div class="alert alert-primary mt-4" role="alert" translate>
|
||||
list.availability_minutes_updated_at_deactivation
|
||||
</div>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<input type="password" class="form-control" (keydown.enter)="login()" [(ngModel)]="password" id="password" [placeholder]="'password'|translate" #inputPassword>
|
||||
<label for="password">{{ 'password'|translate|ftitlecase }}</label>
|
||||
</div>
|
||||
<button class="w-100 btn btn-lg btn-primary" (click)="login()" [disabled]="loading">
|
||||
<button class="w-100 btn btn-lg btn-primary" (click)="login()" [disabled]="loading || api.maintenanceMode">
|
||||
<span *ngIf="!loading" translate>login.submit_btn</span>
|
||||
<div class="spinner-border spinner-border-sm text-white" *ngIf="loading"></div>
|
||||
</button>
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Component } from '@angular/core';
|
|||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { AuthService, LoginResponse } from 'src/app/_services/auth.service';
|
||||
import { GuardLoaderIconService } from 'src/app/_services/guard-loader-icon.service';
|
||||
import { ApiClientService } from 'src/app/_services/api-client.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-login',
|
||||
|
@ -22,7 +23,8 @@ export class LoginComponent {
|
|||
public route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private authService: AuthService,
|
||||
private guardLoaderIconService: GuardLoaderIconService
|
||||
private guardLoaderIconService: GuardLoaderIconService,
|
||||
public api: ApiClientService
|
||||
) {
|
||||
this.route.params.subscribe((params) => {
|
||||
if (params["redirect"]) {
|
||||
|
|
|
@ -14,6 +14,28 @@ export class ApiClientService {
|
|||
public alertsChanged = new Subject<void>();
|
||||
public availableUsers: undefined | number = undefined;
|
||||
|
||||
private _maintenanceMode = false;
|
||||
private _maintenanceModeInterval: any = undefined;
|
||||
public maintenanceModeChanged = new Subject<void>();
|
||||
|
||||
get maintenanceMode(): boolean {
|
||||
return this._maintenanceMode;
|
||||
}
|
||||
set maintenanceMode(value: boolean) {
|
||||
if(value && !this._maintenanceMode) {
|
||||
//Every 5 seconds, check if maintenance mode is still active
|
||||
this._maintenanceModeInterval = setInterval(() => {
|
||||
this.get("ping").then(() => {
|
||||
console.log("Maintenance mode disabled");
|
||||
this.maintenanceMode = false;
|
||||
clearInterval(this._maintenanceModeInterval);
|
||||
}).catch(() => {});
|
||||
}, 10000);
|
||||
}
|
||||
this._maintenanceMode = value;
|
||||
this.maintenanceModeChanged.next();
|
||||
}
|
||||
|
||||
constructor(private http: HttpClient) { }
|
||||
|
||||
public apiEndpoint(endpoint: string): string {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div [className]="menuButtonClicked ? 'topnav responsive' : 'topnav'" id="topNavBar" *ngIf="auth.profile.id !== undefined">
|
||||
<div [className]="menuButtonClicked ? 'topnav responsive' : 'topnav'" id="topNavBar" *ngIf="auth.profile.id !== undefined && !api.maintenanceMode">
|
||||
<a routerLinkActive="active" (click)="menuButtonClicked = false" routerLink="/list" translate>menu.list</a>
|
||||
<a routerLinkActive="active" (click)="menuButtonClicked = false" routerLink="/services" translate>menu.services</a>
|
||||
<a routerLinkActive="active" (click)="menuButtonClicked = false" routerLink="/trainings" translate>menu.trainings</a>
|
||||
|
@ -13,7 +13,13 @@
|
|||
<div class="spinner spinner-border"></div>
|
||||
</div>
|
||||
|
||||
<alert type="danger" *ngIf="alerts.length > 0">
|
||||
<div class="mt-2" *ngIf="api.maintenanceMode">
|
||||
<alert type="danger">
|
||||
<strong>{{ 'warning'|translate|ftitlecase }}!</strong> {{ 'maintenance_mode_warning'|translate }}<br>
|
||||
</alert>
|
||||
</div>
|
||||
|
||||
<alert type="danger" *ngIf="alerts.length > 0 && !api.maintenanceMode">
|
||||
<strong>{{ 'warning'|translate|ftitlecase }}!</strong> {{ 'alert.warning_body'|translate }}<br>
|
||||
<ng-container *ngIf="alerts.length == 1">
|
||||
{{ 'alert.current_alert'|translate }}: <a (click)="openAlert(alerts[0]['id'])"><b>{{ alerts[0]["created_at"] | date:'dd/MM/YYYY, HH:mm:ss' }}</b> ({{ 'press_for_more_info'|translate }})</a>
|
||||
|
|
|
@ -28,7 +28,7 @@ export class AppComponent {
|
|||
private locationBackService: LocationBackService,
|
||||
public guardLoaderIconService: GuardLoaderIconService,
|
||||
private router: Router,
|
||||
private api: ApiClientService,
|
||||
public api: ApiClientService,
|
||||
private modalService: BsModalService,
|
||||
public guard: AuthorizeGuard
|
||||
) {
|
||||
|
|
|
@ -130,6 +130,7 @@
|
|||
"document_format_not_supported": "Document format not supported",
|
||||
"file_too_big": "File too big"
|
||||
},
|
||||
"maintenance_mode_warning": "The application is currently in maintenance mode. Some features may not be available.",
|
||||
"property": "property",
|
||||
"value": "value",
|
||||
"user_agent": "User Agent",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"image_format_not_supported": "Formato immagine non supportato",
|
||||
"file_too_big": "File troppo grande"
|
||||
},
|
||||
"maintenance_mode_warning": "Il gestionale è in manutenzione. Alcune funzionalità potrebbero non essere disponibili.",
|
||||
"property": "proprietà",
|
||||
"value": "valore",
|
||||
"user_agent": "User Agent",
|
||||
|
|
Loading…
Reference in New Issue