Merge pull request #416 from allerta-vvf/master

Redirect to login if server response has status code 401 and replace keys
This commit is contained in:
Matteo Gheza 2022-01-04 00:30:58 +01:00 committed by GitHub
commit 6af6fd5fb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 68 additions and 11 deletions

4
backend/.gitignore vendored
View File

@ -3,4 +3,6 @@ dist-frontend
tmp/*
!tmp/.gitkeep
uploads/*
!uploads/.gitkeep
!uploads/.gitkeep
keys/*
!keys/gen.ps1

View File

@ -15,6 +15,10 @@ define('DB_HOST', '@@host@@');
/* Database hostname */
define('DB_PREFIX', '@@prefix@@');
/* JWT Keys */
define('JWT_PUBLIC_KEY', '@@public_key@@');
define('JWT_PRIVATE_KEY', '@@private_key@@');
/* Telegram bot options */
define('BOT_TELEGRAM_API_KEY', '');
define('BOT_TELEGRAM_USERNAME', '');

25
backend/keys/gen.ps1 Normal file
View File

@ -0,0 +1,25 @@
openssl req -newkey rsa:2048 -new -nodes -keyout key.pem -out csr.pem
openssl x509 -req -days 365 -in csr.pem -signkey key.pem -out server.crt
$Public = Get-Content server.crt
$Private = Get-Content key.pem
Write-Output "" ""
Write-Output "" ""
Write-Output "Public Key"
Write-Output $Public
Write-Output "" ""
Write-Output "Private Key"
Write-Output $Private
Write-Output "" ""
Write-Output "" ""
$PublicBytes = [System.Text.Encoding]::Unicode.GetBytes($Public)
$EncodedPublic = [Convert]::ToBase64String($PublicBytes)
$PrivateBytes = [System.Text.Encoding]::Unicode.GetBytes($Private)
$EncodedPrivate = [Convert]::ToBase64String($PrivateBytes)
Write-Output "/* JWT Keys */"
Write-Output "define('JWT_PUBLIC_KEY', '$EncodedPublic');"
Write-Output "define('JWT_PRIVATE_KEY', '$EncodedPrivate');"

View File

@ -49,8 +49,8 @@ function get_ip()
$JWTconfig = Configuration::forAsymmetricSigner(
new Signer\Rsa\Sha256(),
InMemory::base64Encoded('LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRRFR2d0U4N010Z1JFWUwKVEw0YUhoUW8zWnpvZ214eHZNVXNLblB6eXhSczFZclhPU09wd04wbnBzWGFyQktLVklVTU5MZkZPRHAvdm5RbgoyWnAwNk44WEc1OVdBT0t3dkM0TWZ4TERRa0ErSlhnZ3pIbGtiVm9UTitkVWtkWUlGcVNLdUFQR3dpV1RvUksyClN4RWhpajNyRTJGT044alFadkR4WmtpUDlhNHZ4Sk8zT1RQUXdLcmVkWEZpT2JzWEQvYzNSdExGaEtjdGpDeUgKT0lyUDBiUUVzZWUvbTdKTnRHNHJ5NkJQdXNONndiK3ZKbzVpZUJZUGEzYzE5YWtOcTZxL25ZV2hwbGhra0pTdQphT3JMNXhYRUZ6STVUdmN2blhSNTY4R1ZjeEs4WUxmRmtkeHBzWEd0NXJBYmVoMGgvVTVrSUxFQXF2OFA5UEdUClpwaWNLYnJuQWdNQkFBRUNnZ0VBZDN5VFFFUUhSOTEvQVNWZktQSE1RbnM3N2VDYlBWdGVrRnVzYnVnc01IWVkKRVBkSGJxVk1wdkZ2T01SYytmNVR6ZDE1emlxNnFCZGJDSm04bFRoTG00aVUwejFRcnBhaURaOHZnVXZEWU01WQpDWG9aRGxpK3VaV1VUcDYwL245NGZtYjBpcFpJQ2hTY3NJMlByek9KV1R2b2J2RC91c284TUp5ZFdjOHphZlFtCnVxWXp5Z09makZadlU0bFNmZ3pwZWZocHF1eTBKVXk1VGlLUm1HVW53TGIzVHRjc1ZhdmpzbjRRbU53TFlnT0YKMk9FK1IxMmV4M3BBS1RpUkU2RmNuRTF4RklvMUdLaEJhMk90Z3czTURPNkdnK2tuOFE0YWxLejZDNlJSbGdhSApSN3NZekVmSmhzay9HR0ZUWU96WEtRejJsU2FTdEt0OXdLQ29yMDRSY1FLQmdRRHpQT3U1akNUZmF5VW83eFkyCmpIdGlvZ0h5S0xMT2J0OWwzcWJ3Z1huYUQ2cm54WU52Q3JBME9NdlQraVpYc0ZaS0prWXpKcjhaT3hPcFBST2sKMTBXZE9hZWZpd1V5TDVkeXB1ZVN3bElEd1ZtK2hJNEJzODJNYWpIdHpPb3poKzczd0ErYXc1clBzODRVaXg5dwpWYmJ3YVZSNnFQL0JWMDl5SllTNWtRN2Ztd0tCZ1FEZTJ4anl3WDJkMk1DK3F6UnIrTGZVKzErZ3EwampoQkNYCldIcVJONklFQ0IweFRuWFVmOVdML1ZDb0kxLzU1QmhkYmJFamErNGJ0WWdjWFNQbWxYQklSS1E0VnRGZlZtWUIKa1BYZUQ4b1o3THl1TmRDc2JLTmUreDFJSFhEZTZXZnMzTDl1bENmWHhlSUU4NHd5M2ZkNjZtUWFoeVhWOWlEOQpDa3VpZk1xVXBRS0JnUUNpeWRIbFkxTEdKL285dEEyRXdtNU5hNm1ydk9zMlYyT3gxTnFiT2J3b1liWDYyZWlGCjUzeFg1dThiVmw1VTc1SkFtKzc5aXQvNGJkNVJ0S3V4OWRVRVRiTE9od2NhT0ZtK2hNK1ZHL0l4eXpSWjJuTUQKMXFjcFkyVTVCcHh6a25VdllGM1JNVG9wNmVkeFBrN3pLcHA5dWJDdFN1K29JTnZ0eEFoWS9Ta2NJd0tCZ0dQMQp1cGNJbXlPMkdaNXNoTEw1ZU51YmRTVklMd1YrTTBMdmVPcXlIWVhaYmQ2ejVyNU9LS2NHRkt1V1VuSndFVTIyCjZnR05ZOXdoN005c0o3SkJ6WDljNnB3cXRQY2lkZGEyQXRKOEdwYk9UVU9HOS9hZk5CaGlZcHY2T0txRDN3MnIKWm1KZktnL3F2cHFoODN6TmV6Z3k4bnZEcXdEeHlaSTJqLzV1SXgvUkFvR0JBTVdSbXh0djZIMmNLaGliSS9hSQpNVEpNNFFSanlQTnhRcXZBUXN2K29IVWJpZDA2VkszSkUrOWlReWl0aGpjZk5Pd25DYW9PN0k3cUFqOVFFZkpTCk1aUWMvVy80REhKZWJvMmtkMTF5b1hQVlRYWE91RXdMU0tDZWpCWEFCQlkwTVBOdVBVbWlYZVUwTzNUeWkzN0oKVFVLenJnY2Q3TnZsQTQxWTR4S2NPcUVBCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0='),
InMemory::base64Encoded('LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUEwNzhCUE96TFlFUkdDMHkrR2g0VQpLTjJjNklKc2NiekZMQ3B6ODhzVWJOV0sxemtqcWNEZEo2YkYycXdTaWxTRkREUzN4VGc2Zjc1MEo5bWFkT2pmCkZ4dWZWZ0Rpc0x3dURIOFN3MEpBUGlWNElNeDVaRzFhRXpmblZKSFdDQmFraXJnRHhzSWxrNkVTdGtzUklZbzkKNnhOaFRqZkkwR2J3OFdaSWovV3VMOFNUdHprejBNQ3EzblZ4WWptN0Z3LzNOMGJTeFlTbkxZd3NoemlLejlHMApCTEhudjV1eVRiUnVLOHVnVDdyRGVzRy9yeWFPWW5nV0QydDNOZldwRGF1cXY1MkZvYVpZWkpDVXJtanF5K2NWCnhCY3lPVTczTDUxMGVldkJsWE1TdkdDM3haSGNhYkZ4cmVhd0czb2RJZjFPWkNDeEFLci9EL1R4azJhWW5DbTYKNXdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0t')
InMemory::base64Encoded(JWT_PRIVATE_KEY),
InMemory::base64Encoded(JWT_PUBLIC_KEY)
);
$auth = new \Delight\Auth\Auth($db, $JWTconfig, get_ip(), DB_PREFIX."_");

View File

@ -9,6 +9,7 @@ $baseConfig = [
*.json
config.old.php
config.php
keys
*tests*
*tests
*examples*

View File

@ -0,0 +1,23 @@
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http';
import { Observable, tap } from 'rxjs';
import { AuthService } from '../_services/auth.service';
@Injectable()
export class UnauthorizedInterceptor implements HttpInterceptor {
constructor(private auth: AuthService) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe( tap({
next: () => {},
error: (err: any) => {
if (err instanceof HttpErrorResponse) {
if (err.status !== 401 || request.url.includes('/login')) {
return;
}
console.log("Login required");
this.auth.logout();
}
}}));
}
}

View File

@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { HttpClient, HttpHeaders } from '@angular/common/http';
@Injectable({
providedIn: 'root'
@ -60,9 +60,6 @@ export class ApiClientService {
}
public put(endpoint: string, data: any) {
let params = new HttpParams({
fromObject: data,
});
return new Promise<any>((resolve, reject) => {
this.http.put(this.apiEndpoint(endpoint), this.dataToParams(data), this.requestOptions).subscribe((data: any) => {
resolve(data);
@ -81,4 +78,4 @@ export class ApiClientService {
});
});
}
}
}

View File

@ -1,7 +1,7 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule } from '@angular/common/http';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { FormsModule } from '@angular/forms';
import { ToastrModule } from 'ngx-toastr';
import { ModalModule } from 'ngx-bootstrap/modal';
@ -23,6 +23,8 @@ import { LogsComponent } from './_components/logs/logs.component';
import { ServicesComponent } from './_components/services/services.component';
import { TrainingsComponent } from './_components/trainings/trainings.component';
import { UnauthorizedInterceptor } from './_providers/unauthorized-interceptor.provider';
@NgModule({
declarations: [
AppComponent,
@ -59,7 +61,11 @@ import { TrainingsComponent } from './_components/trainings/trainings.component'
registrationStrategy: 'registerWhenStable:30000'
})
],
providers: [],
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: UnauthorizedInterceptor,
multi: true
}],
bootstrap: [AppComponent]
})
export class AppModule { }

View File

@ -2,7 +2,6 @@
"extends": [
"config:base"
],
"dependencyDashboard": true,
"automerge": true,
"packageRules": [
{