Use only password to register, update/create the User, reset the pass...
MODIFY
postman/EVSE.postman_collection.json
postman/EVSE.postman_collection.json
],
"body": {
"mode": "raw",
- "raw": "{\n \"email\": \"demo.basic@sap.com\",\n \"hash\": \"795fc992-d9bd-4695-8fa6-78cee1ef3464\",\n \"captcha\": \"aaa\",\n \"passwords\": {\n \"password\": \"Azerty123?\",\n \"repeatPassword\": \"Azerty123?\"\n },\n \"tenant\": \"{{tenant}}\"\n}"
+ "raw": "{\n \"email\": \"demo.basic@sap.com\",\n \"hash\": \"795fc992-d9bd-4695-8fa6-78cee1ef3464\",\n \"captcha\": \"aaa\",\n \"password\": \"Azerty123?\",\n \"tenant\": \"{{tenant}}\"\n}"
},
"url": {
"raw": "{{base_url}}/v1/auth/password/reset",
"header": [],
"body": {
"mode": "raw",
- "raw": "{\n \"name\": \"CreateName\",\n \"firstName\": \"CreateFirstname\",\n \"email\": \"firstname.lastname@sap.com\",\n \"passwords\": {\n \"password\": \"Azerty123!\",\n \"repeatPassword\": \"Azerty123!\"\n },\n \"acceptEula\": true,\n \"tenant\": \"slf\",\n \"role\": \"B\",\n \"status\": \"A\"\n}\n",
+ "raw": "{\n \"name\": \"CreateName\",\n \"firstName\": \"CreateFirstname\",\n \"email\": \"firstname.lastname@sap.com\",\n \"password\": \"Azerty123!\",\n \"acceptEula\": true,\n \"tenant\": \"slf\",\n \"role\": \"B\",\n \"status\": \"A\"\n}\n",
"options": {
"raw": {
"language": "json"
],
"body": {
"mode": "raw",
- "raw": "{\r\n \"name\": \"FABIANO\",\r\n \"firstName\": \"Sergio\",\r\n \"email\": \"sdf3.sdf.sdfssss@free.fr\",\r\n \"phone\": \"+33 492286307\",\r\n \"mobile\": \"\",\r\n \"iNumber\": \"I030367\",\r\n \"tagIDs\": [\r\n \"66BDC46F\"\r\n ],\r\n \"costCenter\": \"175030602\",\r\n \"status\": \"A\",\r\n \"role\": \"A\",\r\n \"passwords\": {\r\n \"password\": \"\",\r\n \"repeatPassword\": \"\"\r\n }\r\n}\r\n"
+ "raw": "{\r\n \"name\": \"FABIANO\",\r\n \"firstName\": \"Sergio\",\r\n \"email\": \"sdf3.sdf.sdfssss@free.fr\",\r\n \"phone\": \"+33 492286307\",\r\n \"mobile\": \"\",\r\n \"iNumber\": \"I030367\",\r\n \"tagIDs\": [\r\n \"66BDC46F\"\r\n ],\r\n \"costCenter\": \"175030602\",\r\n \"status\": \"A\",\r\n \"role\": \"A\",\r\n \"password\": \"\"\r\n"
},
"url": {
"raw": "{{base_url}}/v1/api/users/{{userID}}",
],
"body": {
"mode": "raw",
- "raw": "{\r\n \"name\": \"DEMO\",\r\n \"firstName\": \"Demo\",\r\n \"email\": \"demo.basic@sap.com\",\r\n \"phone\": \"+33 492286307\",\r\n \"mobile\": \"\",\r\n \"iNumber\": \"I030367\",\r\n \"tagIDs\": [\r\n \"66BDC46F\"\r\n ],\r\n \"costCenter\": \"175030602\",\r\n \"status\": \"A\",\r\n \"role\": \"A\",\r\n \"passwords\": {\r\n \"password\": \"\",\r\n \"repeatPassword\": \"\"\r\n }\r\n}\r\n"
+ "raw": "{\r\n \"name\": \"DEMO\",\r\n \"firstName\": \"Demo\",\r\n \"email\": \"demo.basic@sap.com\",\r\n \"phone\": \"+33 492286307\",\r\n \"mobile\": \"\",\r\n \"iNumber\": \"I030367\",\r\n \"tagIDs\": [\r\n \"66BDC46F\"\r\n ],\r\n \"costCenter\": \"175030602\",\r\n \"status\": \"A\",\r\n \"role\": \"A\",\r\n \"password\": \"\"\r\n}\r\n"
},
"url": {
"raw": "{{base_url}}/v1/api/users/{{userID}}",

MODIFY
src/assets/server/rest/v1/docs/e-mobility-oas.json
src/assets/server/rest/v1/docs/e-mobility-oas.json
"email",
"name",
"firstName",
- "passwords",
+ "password",
"acceptEula",
"tenant",
"captcha"
"type": "string",
"example": "User"
},
- "passwords": {
- "type": "object",
- "properties": {
"password": {
"type": "string",
"example": "DeM*Us$r1"
},
- "repeatPassword": {
- "type": "string",
- "example": "DeM*Us$r1"
- }
- }
- },
"acceptEula": {
"type": "boolean",
"example": true
"type": "string",
"example": "demo.demo@sap.com"
},
- "passwords": {
- "type": "object",
- "properties": {
"password": {
"type": "string"
},
- "repeatPassword": {
- "type": "string"
- }
- }
- },
"captcha": {
"type": "string",
"example": "03AGdBq26Ca8rdqn0-odDV18kJCLnVytzGPXVPyW811IY4pqyQuak-o59MZlYfUIVS-ToLBiL4o7fBfPPvmkAhQLKoMXtqitKxRTG016wmGbFLvZWnOSkJKreB1Kx6n3dB7uYd302UVyVpJJ0BGFcmXWnWZmGnR3ZJC8IE1r7oVohcYVLttnKXtuhJwg5IdHe0HleYzOjxCBw9FnCJhVoSmaPn6FeVjWC9d8vSDwBq-18dA_cm6CQb7BhZm6LXWhMdW1_e_5DcSs1koj_vn3FGB7UQESsPp81WBfr6msCNiddNc1D4MRfF4wXeimJ1wplqoGOmMmI2Y_i-120grLrjkfzBNgDPQPWvfpUjeyW1f_T-5SaObYpUFEEZ4YW6Xt2revAWMmZ6i9_QOWWUcukaZU3jr_MzR1YIMscKrnBP3Zhl45zLXOY-0Bi28z6XxsMqqSHE8lY_C8B-7M-X3PNc_293qtrEnE2rhG9PU-RdFJG4dqBcwU6YfZJwwyXDWG7eyNG8iJoBDgCWrbib2jLKTmuwWCowApAoeA"
"email": "demo.demo@sap.com",
"captcha": "03AGdBq26Ca8rdqn0-odDV18kJCLnVytzGPXVPyW811IY4pqyQuak-o59MZlYfUIVS-ToLBiL4o7fBfPPvmkAhQLKoMXtqitKxRTG016wmGbFLvZWnOSkJKreB1Kx6n3dB7uYd302UVyVpJJ0BGFcmXWnWZmGnR3ZJC8IE1r7oVohcYVLttnKXtuhJwg5IdHe0HleYzOjxCBw9FnCJhVoSmaPn6FeVjWC9d8vSDwBq-18dA_cm6CQb7BhZm6LXWhMdW1_e_5DcSs1koj_vn3FGB7UQESsPp81WBfr6msCNiddNc1D4MRfF4wXeimJ1wplqoGOmMmI2Y_i-120grLrjkfzBNgDPQPWvfpUjeyW1f_T-5SaObYpUFEEZ4YW6Xt2revAWMmZ6i9_QOWWUcukaZU3jr_MzR1YIMscKrnBP3Zhl45zLXOY-0Bi28z6XxsMqqSHE8lY_C8B-7M-X3PNc_293qtrEnE2rhG9PU-RdFJG4dqBcwU6YfZJwwyXDWG7eyNG8iJoBDgCWrbib2jLKTmuwWCowApAoeA",
"hash": "dcff1ec7-cecb-4c2f-99da-47aeb1f83509",
- "passwords": {
"password": "Azerty123?",
- "repeatPassword": "Azerty123?"
- },
"tenant": "slf"
}
}
"address": {
"$ref": "#/components/schemas/Address"
},
- "passwords": {
- "type": "object",
- "properties": {
"password": {
"type": "string",
"example": "DeM*Us$r1"
- }
- }
},
"phone": {
"type": "string",

MODIFY
src/assets/server/rest/v1/schemas/auth/auth-reset-password.json
src/assets/server/rest/v1/schemas/auth/auth-reset-password.json
"type": "string",
"sanitize": "mongo"
},
- "passwords": {
- "type": "object",
- "properties": {
"password": {
"$ref": "user.json#/definitions/password"
- },
- "repeatPassword": {
- "$ref": "user.json#/definitions/password"
- }
- },
- "required": ["password", "repeatPassword"]
}
},
"required": [
{ "required": ["hash"] }
],
"dependencies": {
- "hash": { "required": ["passwords"] }
+ "hash": { "required": ["password"] }
}
}

MODIFY
src/assets/server/rest/v1/schemas/auth/auth-signin.json
src/assets/server/rest/v1/schemas/auth/auth-signin.json
"$ref": "user.json#/definitions/email"
},
"password": {
- "$ref": "user.json#/definitions/password"
+ "type": "string",
+ "sanitize": "mongo"
},
"acceptEula": {
"$ref": "common.json#/definitions/acceptEula"

MODIFY
src/assets/server/rest/v1/schemas/auth/auth-signon.json
src/assets/server/rest/v1/schemas/auth/auth-signon.json
"firstName": {
"$ref": "user.json#/definitions/firstName"
},
- "passwords": {
- "type": "object",
- "properties": {
"password": {
"$ref": "user.json#/definitions/password"
},
- "repeatPassword": {
- "$ref": "user.json#/definitions/password"
- }
- }
- },
"acceptEula": {
"$ref": "common.json#/definitions/acceptEula"
},
"email",
"name",
"firstName",
- "passwords",
+ "password",
"acceptEula",
"captcha"
]

MODIFY
src/assets/server/rest/v1/schemas/user/user-create.json
src/assets/server/rest/v1/schemas/user/user-create.json
"address": {
"$ref": "user.json#/definitions/address"
},
- "passwords": {
- "$ref": "user.json#/definitions/passwords"
+ "password": {
+ "$ref": "user.json#/definitions/password"
},
"phone": {
"$ref": "user.json#/definitions/phone"
"required": [
"name",
"email",
- "passwords"
+ "password"
]
}

MODIFY
src/assets/server/rest/v1/schemas/user/user-update.json
src/assets/server/rest/v1/schemas/user/user-update.json
"address": {
"$ref": "user.json#/definitions/address"
},
- "passwords": {
- "$ref": "user.json#/definitions/passwords"
+ "password": {
+ "$ref": "user.json#/definitions/password"
},
"phone": {
"$ref": "user.json#/definitions/phone"

MODIFY
src/assets/server/rest/v1/schemas/user/user.json
src/assets/server/rest/v1/schemas/user/user.json
"address": {
"$ref": "common.json#/definitions/address"
},
- "passwords": {
- "password": {
- "$ref": "#/definitions/password"
- }
- },
"phone": {
"type": "string",
"sanitize": "mongo"

MODIFY
src/server/rest/v1/service/AuthService.ts
src/server/rest/v1/service/AuthService.ts
@@ -171,7 +171,6 @@ export default class AuthService {
});
}
// Check Mandatory field
- Object.assign(filteredRequest, { password: filteredRequest.passwords.password });
UtilsService.checkIfUserValid(filteredRequest as User, null, req);
// Check email
const user = await UserStorage.getUserByEmail(tenant.id, filteredRequest.email);
@@ -185,7 +184,7 @@ export default class AuthService {
});
}
// Generate a password
- const newPasswordHashed = await Utils.hashPasswordBcrypt(filteredRequest.passwords.password);
+ const newPasswordHashed = await Utils.hashPasswordBcrypt(filteredRequest.password);
// Create the user
const newUser = UserStorage.createNewUser() as User;
newUser.email = filteredRequest.email;
@@ -273,7 +272,6 @@ export default class AuthService {
}
).catch(() => { });
}
- // Ok
res.json(Constants.REST_RESPONSE_SUCCESS);
next();
}
@@ -340,7 +338,6 @@ export default class AuthService {
'evseDashboardResetPassURL': evseDashboardResetPassURL
}
).catch(() => { });
- // Ok
res.json(Constants.REST_RESPONSE_SUCCESS);
next();
}
@@ -350,19 +347,8 @@ export default class AuthService {
const user = await UserStorage.getUserByPasswordResetHash(tenantID, filteredRequest.hash);
UtilsService.assertObjectExists(action, user, `User with password reset hash '${filteredRequest.hash}' does not exist`,
MODULE_NAME, 'handleUserPasswordReset', req.user);
- // Check password
- if (!Utils.isPasswordValid(filteredRequest.passwords.password)) {
- throw new AppError({
- source: Constants.CENTRAL_SERVER,
- errorCode: HTTPError.OBJECT_DOES_NOT_EXIST_ERROR,
- message: `Password with reset hash '${filteredRequest.hash}' is not strong enough`,
- module: MODULE_NAME,
- user: user,
- method: 'handleUserPasswordReset'
- });
- }
// Hash it
- const newHashedPassword = await Utils.hashPasswordBcrypt(filteredRequest.passwords.password);
+ const newHashedPassword = await Utils.hashPasswordBcrypt(filteredRequest.password);
// Save new password
await UserStorage.saveUserPassword(tenantID, user.id,
{
@@ -385,7 +371,6 @@ export default class AuthService {
message: 'User\'s password has been reset successfully',
detailedMessages: { params: req.body }
});
- // Ok
res.json(Constants.REST_RESPONSE_SUCCESS);
next();
}
@@ -394,7 +379,7 @@ export default class AuthService {
const filteredRequest = AuthValidator.getInstance().validateAuthResetPassword(req.body);
// Get Tenant
const tenant = await AuthService.getTenant(filteredRequest.tenant);
- if (!tenant.id) {
+ if (!tenant) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
errorCode: HTTPError.OBJECT_DOES_NOT_EXIST_ERROR,
@@ -570,7 +555,6 @@ export default class AuthService {
'evseDashboardURL': Utils.buildEvseURL(filteredRequest.Tenant),
}
).catch(() => { });
- // Ok
res.json({ status: 'Success', userStatus });
next();
}
@@ -678,7 +662,6 @@ export default class AuthService {
'evseDashboardVerifyEmailURL': evseDashboardVerifyEmailURL
}
).catch(() => { });
- // Ok
res.json(Constants.REST_RESPONSE_SUCCESS);
next();
}

MODIFY
src/server/rest/v1/service/UserService.ts
src/server/rest/v1/service/UserService.ts
@@ -185,8 +185,6 @@ export default class UserService {
// Update timestamp
const lastChangedBy = { id: req.user.id };
const lastChangedOn = new Date();
- // Clean up request
- delete filteredRequest['passwords'];
// Check User validity
UtilsService.checkIfUserValid(filteredRequest, user, req);
// Update user
@@ -632,8 +630,6 @@ export default class UserService {
action: action
});
}
- // Clean request
- delete filteredRequest['passwords'];
// Create
const newUser: User = {
...filteredRequest,

MODIFY
src/server/rest/v1/validator/UserValidator.ts
src/server/rest/v1/validator/UserValidator.ts
@@ -45,7 +45,6 @@ export default class UserValidator extends SchemaValidator {
validateUserCreate(user: any): Partial<User> {
this.validate(this.userCreate, user);
- user.password = user.passwords.password;
return user;
}

MODIFY
src/types/requests/HttpUserRequest.ts
src/types/requests/HttpUserRequest.ts
@@ -68,9 +68,7 @@ export interface HttpResetPasswordRequest {
email: string;
tenant: string;
captcha: string;
- passwords: { password: string; repeatPassword: string }; // Frontend...
- password?: string;
- repeatPassword?: string;
+ password: string;
hash: string;
}
export interface HttpCheckEulaRequest {
@@ -80,7 +78,7 @@ export interface HttpCheckEulaRequest {
export interface HttpRegisterUserRequest extends HttpLoginRequest {
name: string;
firstName: string;
- passwords: { password: string }; // Frontend...
+ password: string;
captcha: string;
status: string;
locale: string;

MODIFY
test/api/AuthenticationTest.ts
test/api/AuthenticationTest.ts
@@ -161,7 +161,7 @@ describe('Authentication Service (utall)', function() {
// testData.createdUsersAdminTenant.push(newUser);
// const userAPI = new CentralServerService(testData.adminTenant, {
// email: newUser.email,
- // password: newUser.passwords.password
+ // password: newUser.password
// });
// let validResponse = await userAPI.userApi.readById(newUser.id);
// // Check
@@ -191,7 +191,7 @@ describe('Authentication Service (utall)', function() {
// testData.createdUsersAdminTenant.push(newUser);
// const userAPI = new CentralServerService(testData.adminTenant, {
// email: newUser.email,
- // password: newUser.passwords.password
+ // password: newUser.password
// });
// let validResponse = await userAPI.userApi.readById(newUser.id);
// // Check
@@ -234,17 +234,17 @@ describe('Authentication Service (utall)', function() {
it('Should not allow registration without password', async () => {
// Call
const newUser = UserFactory.buildRegisterUser();
- delete newUser.passwords;
+ delete newUser.password;
const response = await CentralServerService.defaultInstance.authenticationApi.registerUser(newUser, testData.adminTenant);
// Check
expect(response.status).to.be.eql(StatusCodes.INTERNAL_SERVER_ERROR);
expect(response.data).to.not.have.property('token');
});
- it('Should not allow registration with empty strings passwords', async () => {
+ it('Should not allow registration with empty string password', async () => {
// Call
const newUser = UserFactory.buildRegisterUser();
- newUser.passwords = { password: '', repeatPassword: '' };
+ newUser.password = '';
const response = await CentralServerService.defaultInstance.authenticationApi.registerUser(newUser, testData.adminTenant);
// Check
expect(response.status).to.be.eql(StatusCodes.INTERNAL_SERVER_ERROR);
@@ -254,7 +254,7 @@ describe('Authentication Service (utall)', function() {
it('Should not allow registration with weak password', async () => {
// Call
const newUser = UserFactory.buildRegisterUser();
- newUser.passwords = { password: '1234', repeatPassword: '1234' };
+ newUser.password = '1234';
const response = await CentralServerService.defaultInstance.authenticationApi.registerUser(newUser, testData.adminTenant);
// Check
expect(response.status).to.be.eql(StatusCodes.INTERNAL_SERVER_ERROR);
@@ -269,14 +269,6 @@ describe('Authentication Service (utall)', function() {
expect(response.data).to.not.have.property('token');
});
- it('Should not allow authentication with a password that doesn\'t match requirements', async () => {
- // Call
- const response = await CentralServerService.defaultInstance.authenticationApi.login(testData.adminEmail, '1234', true);
- // Check
- expect(response.status).to.be.eql(StatusCodes.INTERNAL_SERVER_ERROR);
- expect(response.data).to.not.have.property('token');
- });
-
it('Should not allow authentication without password', async () => {
// Call
const response = await CentralServerService.defaultInstance.authenticationApi.login(

MODIFY
test/api/UserTest.ts
test/api/UserTest.ts
@@ -130,8 +130,7 @@ describe('User', function() {
Factory.user.build()
);
testData.newUser.issuer = true;
- // Remove Passwords
- delete testData.newUser['passwords'];
+ delete testData.newUser['password'];
testData.createdUsers.push(testData.newUser);
});
@@ -166,7 +165,7 @@ describe('User', function() {
// Update
await testData.userService.updateEntity(
testData.userService.userApi,
- { ...testData.newUser, passwords: { password: testData.newUser.password } }
+ { ...testData.newUser, password: testData.newUser.password }
);
});

MODIFY
test/factories/UserFactory.ts
test/factories/UserFactory.ts
@@ -6,13 +6,7 @@ const userFactory = Factory.define('user')
.attr('firstName', () => faker.name.firstName())
.attr('name', () => faker.name.lastName().toUpperCase())
.attr('email', () => faker.internet.email().toLowerCase())
- .attr('passwords', () => {
- const password = faker.internet.password() + '@1Aa';
- return {
- password: password,
- repeatPassword: password
- };
- })
+ .attr('password', () => faker.internet.password() + '@1Aa')
.attr('notifications', (): UserNotifications => ({
sendSessionStarted: true,
sendOptimalChargeReached: true,
@@ -47,13 +41,7 @@ const registerUserFactory = Factory.define('user')
.attr('firstName', () => faker.name.firstName())
.attr('name', () => faker.name.lastName())
.attr('email', () => faker.internet.email())
- .attr('passwords', () => {
- const password = faker.internet.password() + '@1Aa';
- return {
- password: password,
- repeatPassword: password
- };
- })
+ .attr('password', () => faker.internet.password() + '@1Aa')
.attr('acceptEula', true)
.attr('locale', 'en_US')
.attr('captcha', '03AMGVjXiyflPJpUOJF-AW2YP9-uQZvbVKsnx2CaESTX7mr59laYB0KKn7QERpWk-cadi1e2D0oYyjClv6UcYJ3IrYI951f2uopiLQv8ykAKEz3TQ3ZWgYJQSvItSZ7cd8wSFl7EF9aVEIHJobWg4OljtmSf2YUyXFnma76ih089LfUe0uSQC8piAT6DJ5WVcNaR827jbJrzCtYSPFX8u_GSFM6jCQU0RdnFgTuFIst2hyZ_FfiKJSpG9pSF2avSie1R-y6PVJktxNHdDaTuN4PK-AucjKrHSO9A');

Use only password to register, update/create the User, reset the pass...