diff --git a/addons/addon-base/packages/services/lib/schema/create-user.json b/addons/addon-base/packages/services/lib/schema/create-user.json index 32f023fde3..085c6a33dd 100644 --- a/addons/addon-base/packages/services/lib/schema/create-user.json +++ b/addons/addon-base/packages/services/lib/schema/create-user.json @@ -26,7 +26,10 @@ }, "email": { "type": "string", - "pattern": "^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$" + "pattern": "^([^.%+!$&*=^|~#%{}]+)[a-zA-Z0-9\\._%+!$&*=^|~#%{}/\\-]+([^.!]+)@([^-.!](([a-zA-Z0-9\\-]+\\.){1,}([a-zA-Z]{2,3})))", + "format": "email", + "minLength": 6, + "maxLength": 512 }, "firstName": { "type": "string", diff --git a/addons/addon-base/packages/services/lib/user/__tests__/user-service.test.js b/addons/addon-base/packages/services/lib/user/__tests__/user-service.test.js index 02089b03be..69fb771d38 100644 --- a/addons/addon-base/packages/services/lib/user/__tests__/user-service.test.js +++ b/addons/addon-base/packages/services/lib/user/__tests__/user-service.test.js @@ -169,6 +169,77 @@ describe('UserService', () => { ); expect(service.audit).toHaveBeenCalledWith({}, expect.objectContaining({ action: 'create-user' })); }); + + const validEmails = [ + 'email@domain.com', + 'firstname.lastname@domain.com', + 'email@subdomain.domain.com', + 'firstname+lastname@domain.com', + '1234567890@domain.com', + 'email@domain-one.com', // Dash in domain name is valid + '_______@domain.com', // Underscore in the address field is valid + 'email@domain.name', + 'email@domain.co.jp', + 'firstname-lastname@domain.com', + ]; + it.each(validEmails)('should pass when creating users with valid email: %p', async email => { + // BUILD + const newUser = { + username: 'nstark', + email, + firstName: 'Ned', + lastName: 'Stark', + }; + service.getUserByPrincipal = jest.fn(); + service.audit = jest.fn(); + + // OPERATE + await service.createUser({}, newUser); + + // CHECK + expect(dbService.table.key).toHaveBeenCalledWith( + expect.objectContaining({ + uid: expect.any(String), + }), + ); + expect(service.audit).toHaveBeenCalledWith({}, expect.objectContaining({ action: 'create-user' })); + }); + + const invalidEmails = [ + 'plainaddress', + '#@%^%#$@#$@#.com', // Garbage + '@domain.com', // Missing username + 'Joe Smith ', // Encoded html within email + 'email.domain.com', // Missing @ + 'email@domain@domain.com', // Two @ sign + '.email@domain.com', // Leading dot in address + 'email.@domain.com', // Trailing dot in address + 'あいうえお@domain.com', // Unicode char as address + 'email@domain.com (Joe Smith)', // Text followed email is not allowed + 'email@domain', // Missing top level domain (.com/.net/.org/etc) + 'email@-domain.com', // Leading dash in front of domain is invalid + 'email@domain..com', // Multiple dot in the domain portion is invalid + ]; + it.each(invalidEmails)('should fail when creating users with invalid email: %p', async email => { + // BUILD + const newUser = { + username: 'nstark', + email, + firstName: 'Ned', + lastName: 'Stark', + }; + service.getUserByPrincipal = jest.fn(); + service.audit = jest.fn(); + + // OPERATE + try { + await service.createUser({}, newUser); + expect.hasAssertions(); + } catch (err) { + // CHECK + expect(err.message).toEqual('Input has validation errors'); + } + }); }); describe('updateUser', () => {