adapt import user to tags
MODIFY
src/authorization/AuthorizationsDefinition.ts
src/authorization/AuthorizationsDefinition.ts
@@ -25,7 +25,7 @@ const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
},
admin: {
grants: [
- { resource: Entity.USERS, action: [Action.LIST, Action.SYNCHRONIZE_BILLING_USERS, Action.EXPORT, Action.IN_ERROR], attributes: ['*'] },
+ { resource: Entity.USERS, action: [Action.LIST, Action.SYNCHRONIZE_BILLING_USERS, Action.EXPORT, Action.IN_ERROR, Action.IMPORT], attributes: ['*'] },
{ resource: Entity.USER, action: [Action.CREATE, Action.READ, Action.UPDATE, Action.SYNCHRONIZE_BILLING_USER], attributes: ['*'] },
{
resource: Entity.USER, action: Action.DELETE, attributes: ['*'],

MODIFY
src/server/rest/v1/service/TagService.ts
src/server/rest/v1/service/TagService.ts
@@ -562,6 +562,28 @@ export default class TagService {
res.writeHead(HTTPError.INVALID_FILE_FORMAT);
res.end();
}
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
+ }, async () => {
+ const executionDurationSecs = Utils.truncTo((new Date().getTime() - startTime) / 1000, 2);
+ await Logging.logActionsResponse(
+ req.user.tenantID, action,
+ MODULE_NAME, 'handleImportTags', result,
+ `{{inSuccess}} Tag(s) were successfully uploaded in ${executionDurationSecs}s and ready for asynchronous import`,
+ `{{inError}} Tag(s) failed to be uploaded in ${executionDurationSecs}s`,
+ `{{inSuccess}} Tag(s) were successfully uploaded in ${executionDurationSecs}s and ready for asynchronous import and {{inError}} failed to be uploaded`,
+ `No Tag have been uploaded in ${executionDurationSecs}s`, req.user
+ );
+ // Insert batched
+ if (tagsToBeImported.length > 0) {
+ await TagService.insertTags(req.user.tenantID, req.user, action, tagsToBeImported, result);
+ }
+ // Release the lock
+ await LockingManager.release(importTagsLock);
+ // Trigger manually and asynchronously the job
+ void new ImportTagsTask().processTenant(req.tenant);
+ // Respond
+ res.json({ ...result, ...Constants.REST_RESPONSE_SUCCESS });
+ next();
});
// Start processing the file
void file.pipe(converter);
@@ -612,29 +634,6 @@ export default class TagService {
}
}
});
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
- busboy.on('finish', async () => {
- const executionDurationSecs = Utils.truncTo((new Date().getTime() - startTime) / 1000, 2);
- await Logging.logActionsResponse(
- req.user.tenantID, action,
- MODULE_NAME, 'handleImportTags', result,
- `{{inSuccess}} Tag(s) were successfully uploaded in ${executionDurationSecs}s and ready for asynchronous import`,
- `{{inError}} Tag(s) failed to be uploaded in ${executionDurationSecs}s`,
- `{{inSuccess}} Tag(s) were successfully uploaded in ${executionDurationSecs}s and ready for asynchronous import and {{inError}} failed to be uploaded`,
- `No Tag have been uploaded in ${executionDurationSecs}s`, req.user
- );
- // Insert batched
- if (tagsToBeImported.length > 0) {
- await TagService.insertTags(req.user.tenantID, req.user, action, tagsToBeImported, result);
- }
- // Release the lock
- await LockingManager.release(importTagsLock);
- // Trigger manually and asynchronously the job
- void new ImportTagsTask().processTenant(req.tenant);
- // Respond
- res.json({ ...result, ...Constants.REST_RESPONSE_SUCCESS });
- next();
- });
}
private static async insertTags(tenantID: string, user: UserToken, action: ServerAction, tagsToBeImported: ImportedTag[], result: ActionsResponse): Promise<void> {

MODIFY
src/server/rest/v1/service/UserService.ts
src/server/rest/v1/service/UserService.ts
@@ -895,7 +895,7 @@ export default class UserService {
inSuccess: 0,
inError: 0
};
- // Delete all previously imported tags
+ // Delete all previously imported users
await UserStorage.deleteImportedUsers(req.user.tenantID);
// Get the stream
const busboy = new Busboy({ headers: req.headers });
@@ -938,7 +938,7 @@ export default class UserService {
user.importedBy = importedBy;
user.importedOn = importedOn;
// Import
- const importSuccess = await UserService.processUser(action, req, user);
+ const importSuccess = await UserService.processUser(action, req, user, usersToBeImported);
if (!importSuccess) {
result.inError++;
}
@@ -953,13 +953,35 @@ export default class UserService {
module: MODULE_NAME, method: 'handleImportUsers',
action: action,
user: req.user.id,
- message: `Invalid Csv file '${filename}'`,
+ message: `Exception while parsing the CSV '${filename}': ${error.message}`,
detailedMessages: { error: error.message, stack: error.stack }
});
if (!res.headersSent) {
res.writeHead(HTTPError.INVALID_FILE_FORMAT);
res.end();
}
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
+ }, async () => {
+ const executionDurationSecs = Utils.truncTo((new Date().getTime() - startTime) / 1000, 2);
+ await Logging.logActionsResponse(
+ req.user.tenantID, action,
+ MODULE_NAME, 'handleImportUsers', result,
+ `{{inSuccess}} User(s) were successfully uploaded in ${executionDurationSecs}s and ready for asynchronous import`,
+ `{{inError}} User(s) failed to be uploaded in ${executionDurationSecs}s`,
+ `{{inSuccess}} User(s) were successfully uploaded in ${executionDurationSecs}s and ready for asynchronous import and {{inError}} failed to be uploaded`,
+ `No User have been uploaded in ${executionDurationSecs}s`, req.user
+ );
+ // Insert batched
+ if (usersToBeImported.length > 0) {
+ await UserService.insertUsers(req.user.tenantID, req.user, action, usersToBeImported, result);
+ }
+ // Release the lock
+ await LockingManager.release(importUsersLock);
+ // Trigger manually and asynchronously the job
+ void new ImportUsersTask().processTenant(req.tenant);
+ // Respond
+ res.json({ ...result, ...Constants.REST_RESPONSE_SUCCESS });
+ next();
});
void file.pipe(converter);
} else if (mimetype === 'application/json') {
@@ -970,7 +992,7 @@ export default class UserService {
user.importedBy = importedBy;
user.importedOn = importedOn;
// Import
- const importSuccess = await UserService.processUser(action, req, user);
+ const importSuccess = await UserService.processUser(action, req, user, usersToBeImported);
if (!importSuccess) {
result.inError++;
}
@@ -1009,29 +1031,6 @@ export default class UserService {
}
}
});
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
- busboy.on('finish', async () => {
- const executionDurationSecs = Utils.truncTo((new Date().getTime() - startTime) / 1000, 2);
- await Logging.logActionsResponse(
- req.user.tenantID, action,
- MODULE_NAME, 'handleImportUsers', result,
- `{{inSuccess}} User(s) were successfully uploaded in ${executionDurationSecs}s and ready for asynchronous import`,
- `{{inError}} User(s) failed to be uploaded in ${executionDurationSecs}s`,
- `{{inSuccess}} User(s) were successfully uploaded in ${executionDurationSecs}s and ready for asynchronous import and {{inError}} failed to be uploaded`,
- `No User have been uploaded in ${executionDurationSecs}s`, req.user
- );
- // Insert batched
- if (usersToBeImported.length > 0) {
- await UserService.insertUsers(req.user.tenantID, req.user, action, usersToBeImported, result);
- }
- // Release the lock
- await LockingManager.release(importUsersLock);
- // Trigger manually and asynchronously the job
- void new ImportUsersTask().processTenant(req.tenant);
- // Respond
- res.json({ ...result, ...Constants.REST_RESPONSE_SUCCESS });
- next();
- });
}
public static async handleCreateUser(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
@@ -1295,8 +1294,8 @@ export default class UserService {
private static async insertUsers(tenantID: string, user: UserToken, action: ServerAction, usersToBeImported: ImportedUser[], result: ActionsResponse): Promise<void> {
try {
- const nbrInsertedTags = await UserStorage.saveImportedUsers(tenantID, usersToBeImported);
- result.inSuccess += nbrInsertedTags;
+ const nbrInsertedUsers = await UserStorage.saveImportedUsers(tenantID, usersToBeImported);
+ result.inSuccess += nbrInsertedUsers;
} catch (error) {
// Handle dup keys
result.inSuccess += error.result.nInserted;
@@ -1400,7 +1399,7 @@ export default class UserService {
return users;
}
- private static async processUser(action: ServerAction, req: Request, importedUser: ImportedUser): Promise<boolean> {
+ private static async processUser(action: ServerAction, req: Request, importedUser: ImportedUser, usersToBeImported: ImportedUser[]): Promise<boolean> {
try {
const newImportedUser: ImportedUser = {
name: importedUser.name.toUpperCase(),
@@ -1413,8 +1412,8 @@ export default class UserService {
newImportedUser.importedBy = importedUser.importedBy;
newImportedUser.importedOn = importedUser.importedOn;
newImportedUser.status = ImportStatus.READY;
- // Save it for import
- await UserStorage.saveImportedUser(req.user.tenantID, newImportedUser);
+ // Save it later on
+ usersToBeImported.push(newImportedUser);
return true;
} catch (error) {
await Logging.logError({

MODIFY
src/storage/mongodb/MongoDBStorage.ts
src/storage/mongodb/MongoDBStorage.ts
@@ -70,7 +70,7 @@ export default class MongoDBStorage {
{ fields: { 'address.coordinates': '2dsphere' } },
]);
// Users Import
- await this.handleIndexesInCollection(tenantID, 'usersImport', [
+ await this.handleIndexesInCollection(tenantID, 'importedusers', [
{ fields: { email: 1 }, options: { unique: true } }
]);
await this.handleIndexesInCollection(tenantID, 'eulas');
@@ -159,7 +159,7 @@ export default class MongoDBStorage {
{ fields: { coordinates: '2dsphere' } },
{ fields: { deleted: 1, issuer: 1 } },
]);
- Logging.logDebug({
+ await Logging.logDebug({
tenantID: tenantID,
action: ServerAction.MONGO_DB,
message: 'Check of MongoDB database done',

adapt import user to tags