Remove Session Hash maps
MODIFY
src/server/rest/CentralRestServer.ts
src/server/rest/CentralRestServer.ts
@@ -179,10 +179,6 @@ export default class CentralRestServer {
}
public notifyUser(tenantID: string, action: Action, data: NotificationData): void {
- // On User change rebuild userHashID
- if (data && data.id) {
- SessionHashService.rebuildUserHashID(tenantID, data.id).catch(() => { });
- }
// Add in buffer
this.addSingleChangeNotificationInBuffer({
'tenantID': tenantID,
@@ -199,10 +195,6 @@ export default class CentralRestServer {
}
public notifyTag(tenantID: string, action: Action, data: NotificationData): void {
- // On Tag change rebuild userHashID
- if (data && data.id) {
- SessionHashService.rebuildUserHashIDFromTagID(tenantID, data.id).catch(() => { });
- }
// Add in buffer
this.addSingleChangeNotificationInBuffer({
'tenantID': tenantID,
@@ -219,10 +211,6 @@ export default class CentralRestServer {
}
public notifyTenant(tenantID: string, action: Action, data: NotificationData): void {
- // On Tenant change rebuild tenantHashID
- if (data && data.id) {
- SessionHashService.rebuildTenantHashID(data.id).catch(() => { });
- }
// Add in buffer
this.addSingleChangeNotificationInBuffer({
'tenantID': tenantID,

MODIFY
src/server/rest/CentralRestServerService.ts
src/server/rest/CentralRestServerService.ts
@@ -320,7 +320,7 @@ export default class CentralRestServerService {
// Parse the action
const action = req.params.action as ServerAction;
// Check if User has been updated and require new login
- if (SessionHashService.isSessionHashUpdated(req, res, next)) {
+ if ((await SessionHashService.isSessionHashUpdated(req, res, next))) {
return;
}
// Check HTTP Verbs

MODIFY
src/server/rest/v1/service/AuthService.ts
src/server/rest/v1/service/AuthService.ts
@@ -811,10 +811,6 @@ export default class AuthService {
}
public static handleUserLogOut(action: ServerAction, req: Request, res: Response, next: NextFunction): void {
- // Cleanup hash
- if (req.user) {
- SessionHashService.deleteUserHashID(req.user.tenantID, req.user.id);
- }
req.logout();
res.status(StatusCodes.OK).send({});
}

MODIFY
src/server/rest/v1/service/SessionHashService.ts
src/server/rest/v1/service/SessionHashService.ts
@@ -11,28 +11,29 @@ import TenantStorage from '../../../../storage/mongodb/TenantStorage';
import User from '../../../../types/User';
import UserStorage from '../../../../storage/mongodb/UserStorage';
import Utils from '../../../../utils/Utils';
-import global from '../../../../types/GlobalType';
const MODULE_NAME = 'SessionHashService';
export default class SessionHashService {
- public static isSessionHashUpdated(req: Request, res: Response, next: NextFunction): boolean {
+ public static async isSessionHashUpdated(req: Request, res: Response, next: NextFunction): Promise<boolean> {
// Get tenant id, user id and hash ID
const userID = req.user.id;
const tenantID = req.user.tenantID;
const userHashID = req.user.userHashID;
const tenantHashID = req.user.tenantHashID;
- // TODO: To Remove: Temporary log to trace memory leaks
- Logging.logDebug({
- tenantID: tenantID,
- module: MODULE_NAME, method: 'isSessionHashUpdated',
- message: `Session Hash buffer size: ${global.userHashMapIDs.size} user(s), ${global.tenantHashMapIDs.size} tenant(s)`,
- action: ServerAction.SESSION_HASH_SERVICE
- });
+ // No session hash in master tenant
+ if (tenantID === Constants.DEFAULT_TENANT) {
+ return false;
+ }
+ const tenant = await TenantStorage.getTenant(tenantID);
+ const user = await UserStorage.getUser(tenantID, userID);
try {
+ // User or Tenant no longer exists
+ if (!tenant || !user) {
+ return true;
+ }
// Check User's Hash
- if (global.userHashMapIDs.has(`${tenantID}#${userID}`) &&
- global.userHashMapIDs.get(`${tenantID}#${userID}`) !== userHashID) {
+ if (userHashID !== this.buildUserHashID(user)) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
errorCode: StatusCodes.FORBIDDEN,
@@ -43,8 +44,7 @@ export default class SessionHashService {
});
}
// Check Tenant's Hash
- if (global.tenantHashMapIDs.has(`${tenantID}`) &&
- global.tenantHashMapIDs.get(`${tenantID}`) !== tenantHashID) {
+ if (tenantHashID !== this.buildTenantHashID(tenant)) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
errorCode: StatusCodes.FORBIDDEN,
@@ -63,47 +63,16 @@ export default class SessionHashService {
}
public static buildUserHashID(user: User): string {
- // Get all field that need to be hashed
- const tags = user.tags && user.tags.length > 0 ? user.tags.map((tag) => tag.id).sort().join('-') : '';
- const data = `${Utils.getLanguageFromLocale(user.locale)}/${user.email}/${user.role}/${user.status}/${tags}`;
- return Cypher.hash(data);
- }
-
- public static buildTenantHashID(tenant: Tenant): string {
- // Get all field that need to be hashed
- const data = JSON.stringify(Utils.getTenantActiveComponents(tenant));
- return Cypher.hash(data);
- }
-
- public static async rebuildUserHashID(tenantID: string, userID: string): Promise<void> {
- // Build User hash
- const user = await UserStorage.getUser(tenantID, userID, { withTag: true });
+ // Generate User Hash
if (user) {
- global.userHashMapIDs.set(`${tenantID}#${userID}`, SessionHashService.buildUserHashID(user));
- } else {
- global.userHashMapIDs.delete(`${tenantID}#${userID}`);
+ return Cypher.hash(`${Utils.getLanguageFromLocale(user.locale)}/${user.email}/${user.role}/${user.status}`);
}
}
- public static deleteUserHashID(tenantID: string, userID: string): void {
- global.userHashMapIDs.delete(`${tenantID}#${userID}`);
- }
-
- public static async rebuildUserHashIDFromTagID(tenantID: string, tagID: string): Promise<void> {
- // Build User hash
- const tag = await UserStorage.getTag(tenantID, tagID);
- if (tag?.userID) {
- await this.rebuildUserHashID(tenantID, tag.userID);
- }
- }
-
- public static async rebuildTenantHashID(tenantID: string): Promise<void> {
- // Build Tenant hash
- const tenant = await TenantStorage.getTenant(tenantID);
+ public static buildTenantHashID(tenant: Tenant): string {
+ // Generate Tenant Hash
if (tenant) {
- global.tenantHashMapIDs.set(`${tenantID}`, SessionHashService.buildTenantHashID(tenant));
- } else {
- global.tenantHashMapIDs.delete(`${tenantID}`);
+ return Cypher.hash(JSON.stringify(Utils.getTenantActiveComponents(tenant)));
}
}
}

MODIFY
src/server/rest/v1/service/UserService.ts
src/server/rest/v1/service/UserService.ts
@@ -1254,7 +1254,6 @@ export default class UserService {
}
// Filter
const filteredRequest = UserSecurity.filterTagUpdateRequest(req.body, req.user);
- let formerTagOwnerID = '';
// Check
await Utils.checkIfUserTagIsValid(filteredRequest, req);
// Get Tag
@@ -1299,7 +1298,6 @@ export default class UserService {
action: action
});
}
- formerTagOwnerID = tag.userID;
}
if (filteredRequest.default && (tag.default !== filteredRequest.default)) {
await UserStorage.clearTagUserDefault(req.user.tenantID,filteredRequest.userID);
@@ -1313,10 +1311,6 @@ export default class UserService {
tag.lastChangedOn = new Date();
// Save
await UserStorage.saveTag(req.user.tenantID, tag);
- if (formerTagOwnerID) {
- // Recompute the former User's Hash (trigger unlog)
- await SessionHashService.rebuildUserHashID(req.user.tenantID, formerTagOwnerID);
- }
// Synchronize badges with IOP
if (Utils.isComponentActiveFromToken(req.user, TenantComponents.OCPI) && (filteredRequest.userID !== tag.userID)) {
try {

MODIFY
src/start.ts
src/start.ts
@@ -65,9 +65,6 @@ export default class Bootstrap {
Bootstrap.oDataServerConfig = Configuration.getODataServiceConfig();
Bootstrap.isClusterEnabled = Configuration.getClusterConfig().enabled;
Bootstrap.migrationConfig = Configuration.getMigrationConfig();
- // Init global user and tenant IDs hashmap
- global.userHashMapIDs = new Map<string, string>();
- global.tenantHashMapIDs = new Map<string, string>();
// Start the connection to the Database
if (!Bootstrap.databaseDone) {
// Check database implementation

MODIFY
src/types/GlobalType.ts
src/types/GlobalType.ts
@@ -43,8 +43,6 @@ interface TSGlobal extends Global {
appRoot: string;
centralSystemJsonServer: JsonCentralSystemServer;
centralSystemSoapServer: SoapCentralSystemServer;
- userHashMapIDs: Map<string, string>;
- tenantHashMapIDs: Map<string, string>;
}
// Export global variables

Remove Session Hash maps