mirror of
https://github.com/xuthus83/pigallery2.git
synced 2025-01-14 14:43:17 +08:00
Improving notification and CSRF error logging
This commit is contained in:
parent
3b82b71203
commit
b37d4ec8c8
@ -105,7 +105,7 @@ export class RenderingMWs {
|
|||||||
const message = new Message<any>(err, null);
|
const message = new Message<any>(err, null);
|
||||||
return res.json(message);
|
return res.json(message);
|
||||||
}
|
}
|
||||||
NotificationManager.error('Unknown server error', err);
|
NotificationManager.error('Unknown server error', err, req);
|
||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import {NotificationDTO, NotificationType} from '../../common/entities/NotificationDTO';
|
import {NotificationDTO, NotificationType} from '../../common/entities/NotificationDTO';
|
||||||
|
import {Request} from 'express';
|
||||||
|
|
||||||
export class NotificationManager {
|
export class NotificationManager {
|
||||||
public static notifications: NotificationDTO[] = [];
|
public static notifications: NotificationDTO[] = [];
|
||||||
@ -11,19 +12,35 @@ export class NotificationManager {
|
|||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
public static error(message: string, details?: any) {
|
public static error(message: string, details?: any, req?: Request) {
|
||||||
NotificationManager.notifications.push({
|
const noti: NotificationDTO = {
|
||||||
type: NotificationType.error,
|
type: NotificationType.error,
|
||||||
message: message,
|
message: message,
|
||||||
details: details
|
details: details
|
||||||
});
|
};
|
||||||
|
if (req) {
|
||||||
|
noti.request = {
|
||||||
|
method: req.method,
|
||||||
|
url: req.url,
|
||||||
|
statusCode: req.statusCode
|
||||||
|
};
|
||||||
|
}
|
||||||
|
NotificationManager.notifications.push(noti);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static warning(message: string, details?: any) {
|
public static warning(message: string, details?: any, req?: Request) {
|
||||||
NotificationManager.notifications.push({
|
const noti: NotificationDTO = {
|
||||||
type: NotificationType.warning,
|
type: NotificationType.warning,
|
||||||
message: message,
|
message: message,
|
||||||
details: details
|
details: details
|
||||||
});
|
};
|
||||||
|
if (req) {
|
||||||
|
noti.request = {
|
||||||
|
method: req.method,
|
||||||
|
url: req.url,
|
||||||
|
statusCode: req.statusCode
|
||||||
|
};
|
||||||
|
}
|
||||||
|
NotificationManager.notifications.push(noti);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,11 +24,18 @@ export class ErrorRouter {
|
|||||||
res.status(401);
|
res.status(401);
|
||||||
return next(new ErrorDTO(ErrorCodes.NOT_AUTHENTICATED, 'Invalid token'));
|
return next(new ErrorDTO(ErrorCodes.NOT_AUTHENTICATED, 'Invalid token'));
|
||||||
}
|
}
|
||||||
|
if (err.name === 'ForbiddenError' && err.code === 'EBADCSRFTOKEN') {
|
||||||
|
// jwt authentication error
|
||||||
|
res.status(401);
|
||||||
|
return next(new ErrorDTO(ErrorCodes.NOT_AUTHENTICATED, 'Invalid CSRF token', err, req));
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(err);
|
||||||
|
|
||||||
// Flush out the stack to the console
|
// Flush out the stack to the console
|
||||||
Logger.error('Unexpected error:');
|
Logger.error('Unexpected error:');
|
||||||
console.error(err);
|
console.error(err);
|
||||||
return next(new ErrorDTO(ErrorCodes.SERVER_ERROR, 'Unknown server side error', err));
|
return next(new ErrorDTO(ErrorCodes.SERVER_ERROR, 'Unknown server side error', err, req));
|
||||||
},
|
},
|
||||||
RenderingMWs.renderError
|
RenderingMWs.renderError
|
||||||
);
|
);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import {Request} from 'express';
|
||||||
|
|
||||||
export enum ErrorCodes {
|
export enum ErrorCodes {
|
||||||
NOT_AUTHENTICATED = 1,
|
NOT_AUTHENTICATED = 1,
|
||||||
ALREADY_AUTHENTICATED = 2,
|
ALREADY_AUTHENTICATED = 2,
|
||||||
@ -25,9 +27,16 @@ export enum ErrorCodes {
|
|||||||
|
|
||||||
export class ErrorDTO {
|
export class ErrorDTO {
|
||||||
public detailsStr: string;
|
public detailsStr: string;
|
||||||
|
public request: {
|
||||||
|
method: string, url: string
|
||||||
|
} = {method: '', url: ''};
|
||||||
|
|
||||||
constructor(public code: ErrorCodes, public message?: string, public details?: any) {
|
constructor(public code: ErrorCodes, public message?: string, public details?: any, req?: Request) {
|
||||||
this.detailsStr = (this.details ? this.details.toString() : '') || ErrorCodes[code];
|
this.detailsStr = (this.details ? this.details.toString() : '') || ErrorCodes[code];
|
||||||
|
this.request = {
|
||||||
|
method: req.method,
|
||||||
|
url: req.url
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string {
|
toString(): string {
|
||||||
|
@ -6,4 +6,9 @@ export interface NotificationDTO {
|
|||||||
type: NotificationType;
|
type: NotificationType;
|
||||||
message: string;
|
message: string;
|
||||||
details?: any;
|
details?: any;
|
||||||
|
request?: {
|
||||||
|
method: string,
|
||||||
|
url: string,
|
||||||
|
statusCode: number
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,10 @@ import {NotificationDTO, NotificationType} from '../../../common/entities/Notifi
|
|||||||
import {UserDTO, UserRoles} from '../../../common/entities/UserDTO';
|
import {UserDTO, UserRoles} from '../../../common/entities/UserDTO';
|
||||||
import {I18n} from '@ngx-translate/i18n-polyfill';
|
import {I18n} from '@ngx-translate/i18n-polyfill';
|
||||||
|
|
||||||
|
export interface CountedNotificationDTO extends NotificationDTO {
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class NotificationService {
|
export class NotificationService {
|
||||||
|
|
||||||
@ -13,7 +17,8 @@ export class NotificationService {
|
|||||||
positionClass: 'toast-top-center',
|
positionClass: 'toast-top-center',
|
||||||
animate: 'flyLeft'
|
animate: 'flyLeft'
|
||||||
};
|
};
|
||||||
notifications: NotificationDTO[] = [];
|
countedNotifications: CountedNotificationDTO[] = [];
|
||||||
|
numberOfNotifications = 0;
|
||||||
lastUser: UserDTO = null;
|
lastUser: UserDTO = null;
|
||||||
|
|
||||||
constructor(private _toastr: ToastrService,
|
constructor(private _toastr: ToastrService,
|
||||||
@ -36,11 +41,30 @@ export class NotificationService {
|
|||||||
return this._toastr;
|
return this._toastr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
groupNotifications(notifications: NotificationDTO[]) {
|
||||||
|
const groups: { [key: string]: { notification: NotificationDTO, count: number } } = {};
|
||||||
|
notifications.forEach(n => {
|
||||||
|
let key = n.message;
|
||||||
|
if (n.details) {
|
||||||
|
key += JSON.stringify(n.details);
|
||||||
|
}
|
||||||
|
groups[key] = groups[key] || {notification: n, count: 0};
|
||||||
|
groups[key].count++;
|
||||||
|
});
|
||||||
|
this.numberOfNotifications = notifications.length;
|
||||||
|
this.countedNotifications = [];
|
||||||
|
for (const key of Object.keys(groups)) {
|
||||||
|
(groups[key].notification as CountedNotificationDTO).count = groups[key].count;
|
||||||
|
this.countedNotifications.push(groups[key].notification as CountedNotificationDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
async getServerNotifications() {
|
async getServerNotifications() {
|
||||||
try {
|
try {
|
||||||
this.notifications = (await this._networkService.getJson<NotificationDTO[]>('/notifications')) || [];
|
this.groupNotifications((await this._networkService.getJson<NotificationDTO[]>('/notifications')) || []);
|
||||||
this.notifications.forEach((noti) => {
|
this.countedNotifications.forEach((noti) => {
|
||||||
let msg = noti.message;
|
let msg = '(' + noti.count + ') ' + noti.message;
|
||||||
if (noti.details) {
|
if (noti.details) {
|
||||||
msg += ' Details: ' + JSON.stringify(noti.details);
|
msg += ' Details: ' + JSON.stringify(noti.details);
|
||||||
}
|
}
|
||||||
|
@ -12,17 +12,21 @@
|
|||||||
<app-frame>
|
<app-frame>
|
||||||
<div body class="container-fluid">
|
<div body class="container-fluid">
|
||||||
|
|
||||||
<div class="card mb-4" *ngIf="notificationService.notifications.length>0">
|
<div class="card mb-4" *ngIf="notificationService.countedNotifications.length>0">
|
||||||
<h5 class="card-header" i18n>
|
<h5 class="card-header" i18n>
|
||||||
Server notifications
|
Server notifications
|
||||||
</h5>
|
</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<ng-container *ngFor="let notification of notificationService.notifications">
|
<ng-container *ngFor="let notification of notificationService.countedNotifications">
|
||||||
|
|
||||||
<div class="alert alert-{{getCss(notification.type)}}" role="alert">
|
<div class="alert alert-{{getCss(notification.type)}}" role="alert">
|
||||||
{{notification.message}}
|
({{notification.count}}) {{notification.message}}
|
||||||
<br *ngIf="notification.details"/>
|
<br *ngIf="notification.details"/>
|
||||||
{{notification.details | json}}
|
{{notification.details | json}}
|
||||||
|
<ng-container *ngIf="notification.request">
|
||||||
|
<br/>
|
||||||
|
Request: "{{notification.request.method}}", url: "{{notification.request.url}}", status code: "{{notification.request.statusCode}}"
|
||||||
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
@ -40,7 +44,7 @@
|
|||||||
class="version"
|
class="version"
|
||||||
href="https://github.com/bpatrik/pigallery2/releases">
|
href="https://github.com/bpatrik/pigallery2/releases">
|
||||||
<span
|
<span
|
||||||
i18n>App version:</span> <span>{{'v'+((settingsService.settings | async).Server.Environment.appVersion || '----')}}</span>
|
i18n>App version:</span> <span>{{'v' + ((settingsService.settings | async).Server.Environment.appVersion || '----')}}</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -38,8 +38,8 @@
|
|||||||
type="button" class="btn btn-dark dropdown-toggle"
|
type="button" class="btn btn-dark dropdown-toggle"
|
||||||
aria-controls="dropdown-alignment">
|
aria-controls="dropdown-alignment">
|
||||||
<span class="oi oi-menu"></span>
|
<span class="oi oi-menu"></span>
|
||||||
<span *ngIf="isAdmin() && notificationService.notifications.length>0"
|
<span *ngIf="isAdmin() && notificationService.numberOfNotifications>0"
|
||||||
class="navbar-badge badge badge-warning">{{notificationService.notifications.length}}</span>
|
class="navbar-badge badge badge-warning">{{notificationService.numberOfNotifications}}</span>
|
||||||
</button>
|
</button>
|
||||||
<ul id="dropdown-alignment" *dropdownMenu
|
<ul id="dropdown-alignment" *dropdownMenu
|
||||||
class="dropdown-menu dropdown-menu-right"
|
class="dropdown-menu dropdown-menu-right"
|
||||||
@ -54,8 +54,8 @@
|
|||||||
<li role="menuitem" *ngIf="isAdmin()">
|
<li role="menuitem" *ngIf="isAdmin()">
|
||||||
<a class="dropdown-item" [routerLink]="['/admin']">
|
<a class="dropdown-item" [routerLink]="['/admin']">
|
||||||
<span class="oi oi-wrench"></span>
|
<span class="oi oi-wrench"></span>
|
||||||
<span *ngIf="notificationService.notifications.length>0"
|
<span *ngIf="notificationService.numberOfNotifications>0"
|
||||||
class="badge">{{notificationService.notifications.length}}</span>
|
class="badge">{{notificationService.numberOfNotifications}}</span>
|
||||||
<ng-container i18n>Settings</ng-container>
|
<ng-container i18n>Settings</ng-container>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user