Code review 1/2
MODIFY
src/authorization/Authorizations.ts
src/authorization/Authorizations.ts
@@ -200,7 +200,7 @@ export default class Authorizations {
return { user, alternateUser };
}
- public static canListLogging(loggedUser: UserToken): boolean {
+ public static canListLoggings(loggedUser: UserToken): boolean {
return Authorizations.canPerformAction(loggedUser, Entity.LOGGINGS, Action.LIST);
}
@@ -417,6 +417,14 @@ export default class Authorizations {
return Authorizations.canPerformAction(loggedUser, Entity.OCPI_ENDPOINT, Action.GENERATE_LOCAL_TOKEN);
}
+ public static canListChargingProfiles(loggedUser: UserToken): boolean {
+ return Authorizations.canPerformAction(loggedUser, Entity.CHARGING_PROFILES, Action.LIST);
+ }
+
+ public static canReadChargingProfile(loggedUser: UserToken): boolean {
+ return Authorizations.canPerformAction(loggedUser, Entity.CHARGING_PROFILE, Action.READ);
+ }
+
public static canListSiteAreas(loggedUser: UserToken): boolean {
return Authorizations.canPerformAction(loggedUser, Entity.SITE_AREAS, Action.LIST);
}

MODIFY
src/authorization/AuthorizationsDefinition.ts
src/authorization/AuthorizationsDefinition.ts
@@ -32,6 +32,8 @@ const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
condition: { Fn: 'NOT_EQUALS', args: { 'user': '$.owner' } }
},
{ resource: Entity.COMPANIES, action: Action.LIST, attributes: ['*'] },
+ { resource: Entity.CHARGING_PROFILES, action: Action.LIST, attributes: ['*'] },
+ { resource: Entity.CHARGING_PROFILE, action: [Action.READ], attributes: ['*'] },
{ resource: Entity.COMPANY, action: [Action.CREATE, Action.READ, Action.UPDATE, Action.DELETE], attributes: ['*'] },
{ resource: Entity.SITES, action: Action.LIST, attributes: ['*'] },
{ resource: Entity.SITE, action: [Action.CREATE, Action.READ, Action.UPDATE, Action.DELETE], attributes: ['*'] },
@@ -259,6 +261,11 @@ const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
attributes: ['*'],
condition: { Fn: 'LIST_CONTAINS', args: { 'sitesAdmin': '$.site' } }
},
+ { resource: Entity.CHARGING_PROFILES, action: Action.LIST, attributes: ['*'] },
+ {
+ resource: Entity.CHARGING_PROFILE, action: [Action.READ], attributes: ['*'],
+ condition: { Fn: 'LIST_CONTAINS', args: { 'sitesAdmin': '$.site' } }
+ },
{
resource: Entity.TRANSACTION, action: [Action.READ], attributes: ['*'],
condition: { Fn: 'LIST_CONTAINS', args: { 'sitesAdmin': '$.site' } }

MODIFY
src/migration/tasks/AddInactivityStatusInTransactionsTask.ts
src/migration/tasks/AddInactivityStatusInTransactionsTask.ts
@@ -31,14 +31,10 @@ export default class AddInactivityStatusInTransactionsTask extends MigrationTask
});
// Add Charge Box
DatabaseUtils.pushChargingStationLookupInAggregation({
- tenantID: tenant.id,
- aggregation: aggregation,
- localField: 'chargeBoxID',
- foreignField: '_id',
- asField: 'chargeBox',
- oneToOneCardinality: true,
- oneToOneCardinalityNotNull: false
+ tenantID: tenant.id, aggregation: aggregation, localField: 'chargeBoxID',
+ foreignField: '_id', asField: 'chargeBox', oneToOneCardinality: true, oneToOneCardinalityNotNull: false
});
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'chargeBox.siteAreaID');
// Call
const transactionsMDB: Transaction[] = await global.database.getCollection<any>(tenant.id, 'transactions')
.aggregate(aggregation).toArray();

MODIFY
src/server/rest/service/ChargingStationService.ts
src/server/rest/service/ChargingStationService.ts
@@ -295,16 +295,17 @@ export default class ChargingStationService {
// Filter
const filteredRequest = ChargingStationSecurity.filterChargingProfilesRequest(req.query);
// Check auth
- if (!Authorizations.canListChargingStations(req.user)) {
+ if (!Authorizations.canListChargingProfiles(req.user)) {
throw new AppAuthError({
errorCode: HTTPAuthError.ERROR,
user: req.user,
action: Action.LIST,
- entity: Entity.CHARGING_STATION,
+ entity: Entity.CHARGING_PROFILES,
module: MODULE_NAME,
method: 'handleGetChargingProfiles'
});
}
+ // Get the profiles
const chargingProfiles = await ChargingStationStorage.getChargingProfiles(req.user.tenantID,
{ search: filteredRequest.Search,
chargingStationIDs: filteredRequest.ChargeBoxID ? filteredRequest.ChargeBoxID.split('|') : null,
@@ -312,11 +313,8 @@ export default class ChargingStationService {
withChargingStation: filteredRequest.WithChargingStation,
withSiteArea: true },
{ limit: filteredRequest.Limit, skip: filteredRequest.Skip, sort: filteredRequest.Sort, onlyRecordCount: filteredRequest.OnlyRecordCount });
-
// Build the result
- ChargingStationSecurity.filterChargingProfilesResponse(chargingProfiles, req.user,
- Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION), filteredRequest);
-
+ ChargingStationSecurity.filterChargingProfilesResponse(chargingProfiles, req.user);
res.json(chargingProfiles);
next();
}
@@ -657,8 +655,7 @@ export default class ChargingStationService {
}
res.json(
// Filter
- ChargingStationSecurity.filterChargingStationResponse(
- chargingStation, req.user, Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION))
+ ChargingStationSecurity.filterChargingStationResponse(chargingStation, req.user)
);
next();
}
@@ -785,8 +782,7 @@ export default class ChargingStationService {
}
);
// Build the result
- ChargingStationSecurity.filterChargingStationsResponse(chargingStations, req.user,
- Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION));
+ ChargingStationSecurity.filterChargingStationsResponse(chargingStations, req.user);
// Return
res.json(chargingStations);
next();
@@ -1154,8 +1150,7 @@ export default class ChargingStationService {
}
);
// Filter
- ChargingStationSecurity.filterChargingStationsResponse(
- chargingStations, req.user, Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION));
+ ChargingStationSecurity.filterChargingStationsResponse(chargingStations, req.user);
return chargingStations;
}

MODIFY
src/server/rest/service/LoggingService.ts
src/server/rest/service/LoggingService.ts
@@ -20,7 +20,7 @@ const MODULE_NAME = 'LoggingService';
export default class LoggingService {
static async handleGetLoggings(action: ServerAction, req: Request, res: Response, next: NextFunction) {
// Check auth
- if (!Authorizations.canListLogging(req.user)) {
+ if (!Authorizations.canListLoggings(req.user)) {
throw new AppAuthError({
errorCode: HTTPAuthError.ERROR,
user: req.user,
@@ -80,7 +80,7 @@ export default class LoggingService {
static async handleGetLoggingsExport(action: ServerAction, req: Request, res: Response, next: NextFunction) {
// Check auth
- if (!Authorizations.canListLogging(req.user)) {
+ if (!Authorizations.canListLoggings(req.user)) {
throw new AppAuthError({
errorCode: HTTPAuthError.ERROR,
user: req.user,

MODIFY
src/server/rest/service/security/ChargingStationSecurity.ts
src/server/rest/service/security/ChargingStationSecurity.ts
-import { ChargePointStatus, OCPPBootNotificationRequestExtended, OCPPStatusNotificationRequestExtended } from '../../../../types/ocpp/OCPPServer';
+import sanitize from 'mongo-sanitize';
+import Authorizations from '../../../../authorization/Authorizations';
import { ChargingProfile, ChargingSchedule, ChargingSchedulePeriod, Profile } from '../../../../types/ChargingProfile';
import ChargingStation, { Command } from '../../../../types/ChargingStation';
-import { HttpChargingProfilesRequest, HttpChargingStationCommandRequest, HttpChargingStationGetFirmwareRequest, HttpChargingStationLimitPowerRequest, HttpChargingStationOcppParametersRequest, HttpChargingStationParamsUpdateRequest, HttpChargingStationRequest, HttpChargingStationSetMaxIntensitySocketRequest, HttpChargingStationsRequest, HttpIsAuthorizedRequest, HttpTriggerSmartChargingRequest } from '../../../../types/requests/HttpChargingStationRequest';
-
-import Authorizations from '../../../../authorization/Authorizations';
-import { ChargingStationInError } from '../../../../types/InError';
import { DataResult } from '../../../../types/DataResult';
+import { ChargingStationInError } from '../../../../types/InError';
+import { ChargePointStatus, OCPPBootNotificationRequestExtended, OCPPStatusNotificationRequestExtended } from '../../../../types/ocpp/OCPPServer';
import HttpByIDRequest from '../../../../types/requests/HttpByIDRequest';
+import { HttpChargingProfilesRequest, HttpChargingStationCommandRequest, HttpChargingStationGetFirmwareRequest, HttpChargingStationLimitPowerRequest, HttpChargingStationOcppParametersRequest, HttpChargingStationParamsUpdateRequest, HttpChargingStationRequest, HttpChargingStationSetMaxIntensitySocketRequest, HttpChargingStationsRequest, HttpIsAuthorizedRequest, HttpTriggerSmartChargingRequest } from '../../../../types/requests/HttpChargingStationRequest';
import HttpDatabaseRequest from '../../../../types/requests/HttpDatabaseRequest';
-import { InactivityStatus } from '../../../../types/Transaction';
-import UserSecurity from './UserSecurity';
+import TenantComponents from '../../../../types/TenantComponents';
import UserToken from '../../../../types/UserToken';
import Utils from '../../../../utils/Utils';
+import SiteAreaSecurity from './SiteAreaSecurity';
+import UserSecurity from './UserSecurity';
import UtilsSecurity from './UtilsSecurity';
-import sanitize from 'mongo-sanitize';
+
export default class ChargingStationSecurity {
@@ -26,43 +27,50 @@ export default class ChargingStationSecurity {
};
}
- public static filterChargingStationResponse(chargingStation: ChargingStation, loggedUser: UserToken, organizationIsActive: boolean): ChargingStation | ChargingStationInError {
+ public static filterChargingStationResponse(chargingStation: ChargingStation, loggedUser: UserToken): ChargingStation | ChargingStationInError {
let filteredChargingStation: ChargingStation;
- if (!chargingStation || !Authorizations.canReadChargingStation(loggedUser)) {
+ if (!chargingStation) {
return null;
}
const siteID = chargingStation.siteArea ? chargingStation.siteArea.siteID : null;
- if (organizationIsActive && !Authorizations.canReadSiteArea(loggedUser, siteID)) {
+ if (Utils.isComponentActiveFromToken(loggedUser, TenantComponents.ORGANIZATION) &&
+ !Authorizations.canReadSiteArea(loggedUser, siteID)) {
return null;
}
// Check connectors
Utils.checkAndUpdateConnectorsStatus(chargingStation);
// Check Auth
+ if (Authorizations.canReadChargingStation(loggedUser)) {
+ filteredChargingStation = {} as ChargingStation;
if (Authorizations.canUpdateChargingStation(loggedUser, siteID)) {
- // Yes: set all params
- filteredChargingStation = chargingStation;
- for (const connector of filteredChargingStation.connectors) {
- if (connector) {
- // Inactive
- if (filteredChargingStation.inactive) {
- connector.status = ChargePointStatus.UNAVAILABLE;
- connector.currentInstantWatts = 0;
- connector.currentTotalConsumptionWh = 0;
- connector.currentTotalInactivitySecs = 0;
- connector.currentInactivityStatus = InactivityStatus.INFO;
- connector.currentStateOfCharge = 0;
- }
- // Filter User
- if (connector.user) {
- connector.user = UserSecurity.filterMinimalUserResponse(connector.user, loggedUser);
- }
- }
+ filteredChargingStation.capabilities = chargingStation.capabilities;
+ filteredChargingStation.firmwareUpdateStatus = chargingStation.firmwareUpdateStatus;
+ filteredChargingStation.firmwareVersion = chargingStation.firmwareVersion;
+ filteredChargingStation.ocppProtocol = chargingStation.ocppProtocol;
+ filteredChargingStation.ocppVersion = chargingStation.ocppVersion;
+ filteredChargingStation.chargeBoxSerialNumber = chargingStation.chargeBoxSerialNumber;
+ filteredChargingStation.chargePointSerialNumber = chargingStation.chargePointSerialNumber;
+ filteredChargingStation.ocppProtocol = chargingStation.ocppProtocol;
+ filteredChargingStation.ocppVersion = chargingStation.ocppVersion;
+ filteredChargingStation.chargingStationURL = chargingStation.chargingStationURL;
+ filteredChargingStation.currentIPAddress = chargingStation.currentIPAddress;
+ filteredChargingStation.currentServerLocalIPAddressPort = chargingStation.currentServerLocalIPAddressPort;
+ filteredChargingStation.endpoint = chargingStation.endpoint;
+ filteredChargingStation.ocppStandardParameters = chargingStation.ocppStandardParameters;
+ filteredChargingStation.ocppVendorParameters = chargingStation.ocppVendorParameters;
+ filteredChargingStation.voltage = chargingStation.voltage;
}
- } else {
- // Set only necessary info
- filteredChargingStation = {} as ChargingStation;
filteredChargingStation.id = chargingStation.id;
filteredChargingStation.inactive = chargingStation.inactive;
+ filteredChargingStation.lastHeartBeat = chargingStation.lastHeartBeat;
+ filteredChargingStation.maximumPower = chargingStation.maximumPower;
+ filteredChargingStation.chargePointVendor = chargingStation.chargePointVendor;
+ filteredChargingStation.chargePointModel = chargingStation.chargePointModel;
+ filteredChargingStation.siteAreaID = chargingStation.siteAreaID;
+ filteredChargingStation.coordinates = chargingStation.coordinates;
+ if (chargingStation.ocpiData) {
+ filteredChargingStation.ocpiData = chargingStation.ocpiData;
+ }
filteredChargingStation.connectors = chargingStation.connectors.map((connector) => {
if (!connector) {
return connector;
@@ -110,18 +118,9 @@ export default class ChargingStationSecurity {
};
});
}
- filteredChargingStation.lastHeartBeat = chargingStation.lastHeartBeat;
- filteredChargingStation.maximumPower = chargingStation.maximumPower;
- filteredChargingStation.chargePointVendor = chargingStation.chargePointVendor;
- filteredChargingStation.chargePointModel = chargingStation.chargePointModel;
- filteredChargingStation.siteAreaID = chargingStation.siteAreaID;
- filteredChargingStation.coordinates = chargingStation.coordinates;
- if (chargingStation.siteArea) {
- filteredChargingStation.siteArea = chargingStation.siteArea;
- }
- if (chargingStation.ocpiData) {
- filteredChargingStation.ocpiData = chargingStation.ocpiData;
}
+ if (chargingStation.siteArea) {
+ filteredChargingStation.siteArea = SiteAreaSecurity.filterSiteAreaResponse(chargingStation.siteArea, loggedUser);
}
// Sort Connector
filteredChargingStation.connectors.sort(
@@ -132,8 +131,31 @@ export default class ChargingStationSecurity {
return filteredChargingStation;
}
+ public static filterMinimalChargingStationResponse(chargingStation: ChargingStation, loggedUser: UserToken): ChargingStation | ChargingStationInError {
+ let filteredChargingStation: ChargingStation;
+ if (!chargingStation) {
+ return null;
+ }
+ const siteID = chargingStation.siteArea ? chargingStation.siteArea.siteID : null;
+ if (Utils.isComponentActiveFromToken(loggedUser, TenantComponents.ORGANIZATION) &&
+ !Authorizations.canReadSiteArea(loggedUser, siteID)) {
+ return null;
+ }
+ // Check connectors
+ Utils.checkAndUpdateConnectorsStatus(chargingStation);
+ // Check Auth
+ if (Authorizations.canReadChargingStation(loggedUser)) {
+ filteredChargingStation = {} as ChargingStation;
+ filteredChargingStation.id = chargingStation.id;
+ }
+ if (chargingStation.siteArea) {
+ filteredChargingStation.siteArea = SiteAreaSecurity.filterMinimalSiteAreaResponse(chargingStation.siteArea, loggedUser);
+ }
+ return filteredChargingStation;
+ }
+
public static filterChargingStationsResponse(chargingStations: DataResult<ChargingStation>,
- loggedUser: UserToken, organizationIsActive: boolean) {
+ loggedUser: UserToken) {
const filteredChargingStations: ChargingStation[] | ChargingStationInError[] = [];
// Check
if (!chargingStations.result) {
@@ -145,7 +167,7 @@ export default class ChargingStationSecurity {
for (const chargingStation of chargingStations.result) {
// Filter
const filteredChargingStation = ChargingStationSecurity.filterChargingStationResponse(
- chargingStation, loggedUser, organizationIsActive);
+ chargingStation, loggedUser);
if (filteredChargingStation) {
filteredChargingStations.push(filteredChargingStation);
}
@@ -153,37 +175,71 @@ export default class ChargingStationSecurity {
chargingStations.result = filteredChargingStations;
}
- public static filterChargingProfilesResponse(chargingProfiles: DataResult<ChargingProfile>,
- loggedUser: UserToken, organizationIsActive: boolean, filteredRequest: HttpChargingProfilesRequest) {
+ public static filterChargingProfilesResponse(chargingProfiles: DataResult<ChargingProfile>, loggedUser: UserToken): void {
const filteredChargingProfiles: ChargingProfile[] = [];
// Check
if (!chargingProfiles.result) {
return null;
}
- if (!Authorizations.canListChargingStations(loggedUser)) {
+ if (!Authorizations.canListChargingProfiles(loggedUser)) {
return null;
}
for (const chargingProfile of chargingProfiles.result) {
- // Filter
- if (!chargingProfile || !Authorizations.canReadChargingStation(loggedUser)) {
- continue;
+ const filteredChargingProfile = this.filterChargingProfileResponse(chargingProfile, loggedUser, true);
+ if (filteredChargingProfile) {
+ filteredChargingProfiles.push(filteredChargingProfile);
}
- const siteID = chargingProfile.siteArea ? chargingProfile.siteArea.siteID : null;
- if (organizationIsActive && !Authorizations.canReadSiteArea(loggedUser, siteID)) {
- continue;
}
- const filteredChargingProfile = chargingProfile;
- if (filteredChargingProfile) {
- if (!filteredRequest.WithChargingStation) {
- delete filteredChargingProfile.chargingStation;
+ chargingProfiles.result = filteredChargingProfiles;
}
- if (!filteredRequest.WithSiteArea) {
- delete filteredChargingProfile.siteArea;
+
+ static filterChargingProfileResponse(chargingProfile: ChargingProfile, loggedUser: UserToken, forList: boolean): ChargingProfile {
+ const filteredChargingProfile = {} as ChargingProfile;
+ if (!chargingProfile) {
+ return null;
}
- filteredChargingProfiles.push(filteredChargingProfile);
+ // Check auth
+ if (Authorizations.canReadChargingProfile(loggedUser)) {
+ filteredChargingProfile.id = chargingProfile.id;
+ filteredChargingProfile.chargingStationID = chargingProfile.chargingStationID;
+ filteredChargingProfile.chargePointID = chargingProfile.chargePointID;
+ filteredChargingProfile.connectorID = chargingProfile.connectorID;
+ filteredChargingProfile.chargingStation = chargingProfile.chargingStation;
+ if (filteredChargingProfile.chargingStation) {
+ filteredChargingProfile.chargingStation =
+ ChargingStationSecurity.filterMinimalChargingStationResponse(chargingProfile.chargingStation, loggedUser);
+ }
+ filteredChargingProfile.profile = {} as Profile;
+ filteredChargingProfile.profile.chargingProfileId = chargingProfile.profile.chargingProfileId;
+ filteredChargingProfile.profile.transactionId = chargingProfile.profile.transactionId;
+ filteredChargingProfile.profile.stackLevel = chargingProfile.profile.stackLevel;
+ filteredChargingProfile.profile.chargingProfilePurpose = chargingProfile.profile.chargingProfilePurpose;
+ filteredChargingProfile.profile.chargingProfileKind = chargingProfile.profile.chargingProfileKind;
+ filteredChargingProfile.profile.recurrencyKind = chargingProfile.profile.recurrencyKind;
+ filteredChargingProfile.profile.validFrom = chargingProfile.profile.validFrom;
+ filteredChargingProfile.profile.validTo = chargingProfile.profile.validTo;
+ if (!forList) {
+ if (Utils.objectHasProperty(chargingProfile.profile, 'chargingSchedule')) {
+ const chargingSchedule = {} as ChargingSchedule;
+ filteredChargingProfile.profile.chargingSchedule = chargingSchedule;
+ chargingSchedule.duration = chargingProfile.profile.chargingSchedule.duration;
+ chargingSchedule.startSchedule = chargingProfile.profile.chargingSchedule.startSchedule;
+ chargingSchedule.chargingRateUnit = chargingProfile.profile.chargingSchedule.chargingRateUnit;
+ chargingSchedule.minChargeRate = chargingProfile.profile.chargingSchedule.minChargeRate;
+ filteredChargingProfile.profile.chargingSchedule.chargingSchedulePeriod = [];
+ // Check
+ for (const chargingSchedulePeriod of chargingProfile.profile.chargingSchedule.chargingSchedulePeriod) {
+ const chargingSchedulePeriodNew: ChargingSchedulePeriod = {} as ChargingSchedulePeriod;
+ chargingSchedulePeriodNew.startPeriod = sanitize(chargingSchedulePeriod.startPeriod);
+ chargingSchedulePeriodNew.limit = sanitize(chargingSchedulePeriod.limit);
+ chargingSchedulePeriodNew.numberPhases = sanitize(chargingSchedulePeriod.numberPhases);
+ // Add
+ filteredChargingProfile.profile.chargingSchedule.chargingSchedulePeriod.push(chargingSchedulePeriodNew);
}
}
- chargingProfiles.result = filteredChargingProfiles;
+ }
+ }
+ return filteredChargingProfile;
}
public static filterStatusNotificationsResponse(statusNotifications: OCPPStatusNotificationRequestExtended[],
@@ -331,7 +387,7 @@ export default class ChargingStationSecurity {
filteredRequest.chargePointID = sanitize(request.chargePointID);
}
if (Utils.objectHasProperty(request, 'profile')) {
- filteredRequest.profile = ChargingStationSecurity.filterChargingProfile(request.profile);
+ filteredRequest.profile = ChargingStationSecurity.filterChargingProfileRequest(request.profile);
}
return filteredRequest;
}
@@ -396,7 +452,7 @@ export default class ChargingStationSecurity {
filteredRequest.args.transactionId = sanitize(request.args.transactionId);
}
if (Utils.objectHasProperty(request.args, 'csChargingProfiles')) {
- filteredRequest.args.csChargingProfiles = ChargingStationSecurity.filterChargingProfile(request.args.csChargingProfiles);
+ filteredRequest.args.csChargingProfiles = ChargingStationSecurity.filterChargingProfileRequest(request.args.csChargingProfiles);
}
}
return filteredRequest;
@@ -428,7 +484,7 @@ export default class ChargingStationSecurity {
};
}
- private static filterChargingProfile(request: any): Profile {
+ private static filterChargingProfileRequest(request: any): Profile {
const filteredRequest: Profile = {} as Profile;
// Check
if (Utils.objectHasProperty(request, 'chargingProfileId')) {

MODIFY
src/server/rest/service/security/SiteAreaSecurity.ts
src/server/rest/service/security/SiteAreaSecurity.ts
@@ -110,7 +110,7 @@ export default class SiteAreaSecurity {
}
if (siteArea.chargingStations) {
filteredSiteArea.chargingStations = siteArea.chargingStations.map((chargingStation) =>
- ChargingStationSecurity.filterChargingStationResponse(chargingStation, loggedUser, true)
+ ChargingStationSecurity.filterChargingStationResponse(chargingStation, loggedUser)
);
}
// Created By / Last Changed By
@@ -120,6 +120,25 @@ export default class SiteAreaSecurity {
return filteredSiteArea;
}
+ static filterMinimalSiteAreaResponse(siteArea: SiteArea, loggedUser: UserToken): SiteArea {
+ let filteredSiteArea: SiteArea;
+ if (!siteArea) {
+ return null;
+ }
+ // Check auth
+ if (Authorizations.canReadSiteArea(loggedUser, siteArea.siteID)) {
+ // Set only necessary info
+ filteredSiteArea = {} as SiteArea;
+ filteredSiteArea.id = siteArea.id;
+ filteredSiteArea.name = siteArea.name;
+ filteredSiteArea.siteID = siteArea.siteID;
+ filteredSiteArea.maximumPower = siteArea.maximumPower;
+ filteredSiteArea.voltage = siteArea.voltage;
+ filteredSiteArea.numberOfPhases = siteArea.numberOfPhases;
+ }
+ return filteredSiteArea;
+ }
+
static filterSiteAreasResponse(siteAreas: DataResult<SiteArea>, loggedUser) {
const filteredSiteAreas = [];
if (!siteAreas.result) {

MODIFY
src/storage/mongodb/ChargingStationStorage.ts
src/storage/mongodb/ChargingStationStorage.ts
@@ -723,12 +723,19 @@ export default class ChargingStationStorage {
$limit: dbParams.limit
});
if (params.withChargingStation || params.withSiteArea) {
+ // Charging Stations
DatabaseUtils.pushChargingStationLookupInAggregation({
tenantID, aggregation, localField: 'chargingStationID', foreignField: '_id',
- asField: 'chargingStation',
- oneToOneCardinality: true,
- oneToOneCardinalityNotNull: false
+ asField: 'chargingStation', oneToOneCardinality: true, oneToOneCardinalityNotNull: false
});
+ // Site Areas
+ DatabaseUtils.pushSiteAreaLookupInAggregation({
+ tenantID, aggregation, localField: 'chargingStation.siteAreaID', foreignField: '_id',
+ asField: 'chargingStation.siteArea', oneToOneCardinality: true, oneToOneCardinalityNotNull: false
+ });
+ // Convert
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'chargingStation.siteAreaID');
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'chargingStation.siteArea.siteID');
}
// Project
DatabaseUtils.projectFields(aggregation, projectFields);
@@ -736,15 +743,6 @@ export default class ChargingStationStorage {
const chargingProfilesMDB = await global.database.getCollection<ChargingProfile>(tenantID, 'chargingprofiles')
.aggregate(aggregation, { collation: { locale: Constants.DEFAULT_LOCALE, strength: 2 }, allowDiskUse: true })
.toArray();
-
- if (params.withSiteArea) {
- for (const chargingProfile of chargingProfilesMDB) {
- if (chargingProfile.chargingStation.siteAreaID) {
- chargingProfile.siteArea = await SiteAreaStorage.getSiteArea(tenantID, chargingProfile.chargingStation.siteAreaID);
- }
- }
- }
-
// Debug
Logging.traceEnd(MODULE_NAME, 'getChargingProfiles', uniqueTimerID, { params, dbParams });
return {

MODIFY
src/storage/mongodb/DatabaseUtils.ts
src/storage/mongodb/DatabaseUtils.ts
@@ -102,7 +102,7 @@ export default class DatabaseUtils {
public static pushChargingStationLookupInAggregation(lookupParams: DbLookup, additionalPipeline: Record<string, any>[] = []) {
DatabaseUtils.pushCollectionLookupInAggregation('chargingstations', {
- objectIDFields: ['siteAreaID', 'createdBy', 'lastChangedBy'],
+ objectIDFields: ['createdBy', 'lastChangedBy'],
...lookupParams
}, [DatabaseUtils.buildChargingStationInactiveFlagQuery(), ...additionalPipeline]);
}

MODIFY
src/storage/mongodb/NotificationStorage.ts
src/storage/mongodb/NotificationStorage.ts
@@ -85,6 +85,7 @@ export default class NotificationStorage {
tenantID, aggregation: aggregation, localField: 'chargeBoxID', foreignField: '_id',
asField: 'chargeBox', oneToOneCardinality: true, oneToOneCardinalityNotNull: false
});
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'chargeBox.siteAreaID');
// Users
DatabaseUtils.pushUserLookupInAggregation({
tenantID, aggregation: aggregation, asField: 'user', localField: 'userID',

MODIFY
src/storage/mongodb/TransactionStorage.ts
src/storage/mongodb/TransactionStorage.ts
@@ -551,6 +551,7 @@ export default class TransactionStorage {
tenantID, aggregation: aggregation, localField: 'chargeBoxID', foreignField: '_id',
asField: 'chargeBox', oneToOneCardinality: true, oneToOneCardinalityNotNull: false
});
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'chargeBox.siteAreaID');
// Users
DatabaseUtils.pushUserLookupInAggregation({
tenantID, aggregation: aggregation, asField: 'user', localField: 'userID',
@@ -799,6 +800,7 @@ export default class TransactionStorage {
tenantID, aggregation: aggregation, localField: 'chargeBoxID', foreignField: '_id', asField: 'chargeBox',
oneToOneCardinality: true, oneToOneCardinalityNotNull: false, pipelineMatch: { 'issuer': true }
});
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'chargeBox.siteAreaID');
}
// Add respective users
DatabaseUtils.pushUserLookupInAggregation({
@@ -987,14 +989,10 @@ export default class TransactionStorage {
aggregation.push({ $limit: 1 });
// Add Charge Box
DatabaseUtils.pushChargingStationLookupInAggregation({
- tenantID,
- aggregation: aggregation,
- localField: 'chargeBoxID',
- foreignField: '_id',
- asField: 'chargeBox',
- oneToOneCardinality: true,
- oneToOneCardinalityNotNull: false
+ tenantID, aggregation: aggregation, localField: 'chargeBoxID', foreignField: '_id',
+ asField: 'chargeBox', oneToOneCardinality: true, oneToOneCardinalityNotNull: false
});
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'chargeBox.siteAreaID');
// Read DB
const transactionsMDB = await global.database.getCollection<Transaction>(tenantID, 'transactions')
.aggregate(aggregation, { allowDiskUse: true })
@@ -1126,6 +1124,7 @@ export default class TransactionStorage {
tenantID, aggregation, localField: 'chargeBoxID', foreignField: '_id',
asField: 'chargingStation', oneToOneCardinality: true, oneToOneCardinalityNotNull: true
});
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'chargingStation.siteAreaID');
// Format Data
aggregation.push({
$project: {

MODIFY
src/types/ChargingProfile.ts
src/types/ChargingProfile.ts
import ChargingStation from './ChargingStation';
-import SiteArea from './SiteArea';
export interface ChargingProfile {
id?: string;
@@ -7,7 +6,6 @@ export interface ChargingProfile {
chargingStation?: ChargingStation;
chargePointID: number;
connectorID?: number;
- siteArea?: SiteArea;
profile: Profile;
}

Code review 1/2