Optimized Notifications
MODIFY
src/server/rest/v1/service/NotificationService.ts
src/server/rest/v1/service/NotificationService.ts
@@ -6,7 +6,6 @@ import Authorizations from '../../../../authorization/Authorizations';
import Constants from '../../../../utils/Constants';
import { EndUserErrorNotification } from '../../../../types/UserNotifications';
import { HTTPAuthError } from '../../../../types/HTTPError';
-import Logging from '../../../../utils/Logging';
import NotificationHandler from '../../../../notification/NotificationHandler';
import NotificationSecurity from './security/NotificationSecurity';
import NotificationStorage from '../../../../storage/mongodb/NotificationStorage';
@@ -19,9 +18,18 @@ const MODULE_NAME = 'NotificationService';
export default class NotificationService {
static async handleGetNotifications(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
- try {
// Filter
const filteredRequest = NotificationSecurity.filterNotificationsRequest(req.query);
+ // Check User
+ let userProject: string[] = [];
+ if (Authorizations.canListUsers(req.user)) {
+ userProject = [ 'userID', 'user.id', 'user.name', 'user.firstName', 'user.email', 'data' ];
+ }
+ // Check Charging Station
+ let chargingStationProject: string[] = [];
+ if (Authorizations.canListChargingStations(req.user)) {
+ chargingStationProject = [ 'chargeBoxID' ];
+ }
// Get the Notification
const notifications = await NotificationStorage.getNotifications(req.user.tenantID, {
'userID': filteredRequest.UserID,
@@ -31,16 +39,14 @@ export default class NotificationService {
limit: filteredRequest.Limit,
skip: filteredRequest.Skip,
sort: filteredRequest.Sort
- });
- // Filter
- NotificationSecurity.filterNotificationsResponse(notifications, req.user);
+ },
+ [
+ 'id', 'timestamp', 'channel', 'sourceId', 'sourceDescr', 'chargeBoxID',
+ ...userProject, ...chargingStationProject
+ ]);
// Return
res.json(notifications);
next();
- } catch (error) {
- // Log
- Logging.logActionExceptionMessageAndSendResponse(action, error, req, res, next);
- }
}
static async handleEndUserReportError(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {

MODIFY
src/server/rest/v1/service/security/NotificationSecurity.ts
src/server/rest/v1/service/security/NotificationSecurity.ts
import { HttpEndUserReportErrorRequest, HttpNotificationRequest } from '../../../../../types/requests/HttpNotificationRequest';
-import Authorizations from '../../../../../authorization/Authorizations';
-import { DataResult } from '../../../../../types/DataResult';
-import { Notification } from '../../../../../types/UserNotifications';
-import UserSecurity from './UserSecurity';
-import UserToken from '../../../../../types/UserToken';
import UtilsSecurity from './UtilsSecurity';
import sanitize from 'mongo-sanitize';
@@ -27,55 +22,5 @@ export default class NotificationSecurity {
};
return filteredRequest;
}
-
- static filterNotificationsResponse(notifications: DataResult<Notification>, loggedUser: UserToken): void {
- const filteredNotifications = [];
-
- if (!notifications.result) {
- return null;
- }
- for (const notification of notifications.result) {
- // Filter
- const filteredNotification = NotificationSecurity.filterNotificationResponse(notification, loggedUser);
- // Ok?
- if (filteredNotification) {
- // Add
- filteredNotifications.push(filteredNotification);
- }
- }
- notifications.result = filteredNotifications;
- }
-
- // Notification
- static filterNotificationResponse(notification: Notification, loggedUser: UserToken): Notification {
- let filteredNotification = null;
-
- if (!notification) {
- return null;
- }
- // Check auth
- if (!notification.userID || Authorizations.canReadUser(loggedUser, notification.userID)) {
- // No user provided and you are not admin?
- if (!notification.userID && !Authorizations.isAdmin(loggedUser)) {
- // Yes: do not send this notif
- return null;
- }
- filteredNotification = {};
- // Set only necessary info
- filteredNotification.id = notification.id;
- filteredNotification.timestamp = notification.timestamp;
- filteredNotification.channel = notification.channel;
- filteredNotification.sourceId = notification.sourceId;
- filteredNotification.sourceDescr = notification.sourceDescr;
- filteredNotification.userID = notification.userID;
- filteredNotification.chargeBoxID = notification.chargeBoxID;
- filteredNotification.data = notification.data;
- // Handle users
- if (notification.user) {
- filteredNotification.user = UserSecurity.filterMinimalUserResponse(notification.user, loggedUser);
- }
- }
- return filteredNotification;
- }
}

MODIFY
src/storage/mongodb/NotificationStorage.ts
src/storage/mongodb/NotificationStorage.ts
@@ -16,7 +16,7 @@ export default class NotificationStorage {
static async getNotifications(tenantID: string,
params: { userID?: string; dateFrom?: Date; channel?: string; sourceId?: string;
sourceDescr?: string; additionalFilters?: any; chargeBoxID?: string },
- dbParams: DbParams): Promise<DataResult<Notification>> {
+ dbParams: DbParams, projectFields?: string[]): Promise<DataResult<Notification>> {
// Debug
const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'getNotifications');
// Check Tenant
@@ -109,6 +109,8 @@ export default class NotificationStorage {
aggregation.push({
$limit: dbParams.limit
});
+ // Project
+ DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB
const notificationsMDB = await global.database.getCollection<any>(tenantID, 'notifications')
.aggregate(aggregation, { collation: { locale: Constants.DEFAULT_LOCALE, strength: 2 }, allowDiskUse: true })

Optimized Notifications