Parcourir la source

fix(server): Do not allow re-registration of verified email addresses

Relates to #33
Michael Bromley il y a 7 ans
Parent
commit
b1ffa1e397
2 fichiers modifiés avec 33 ajouts et 9 suppressions
  1. 25 5
      server/e2e/auth.e2e-spec.ts
  2. 8 4
      server/src/service/services/customer.service.ts

+ 25 - 5
server/e2e/auth.e2e-spec.ts

@@ -59,10 +59,6 @@ describe('Authorization & permissions', () => {
         await server.destroy();
     });
 
-    beforeEach(() => {
-        sendEmailFn = jest.fn();
-    });
-
     describe('admin permissions', () => {
         describe('Anonymous user', () => {
             beforeAll(async () => {
@@ -151,6 +147,10 @@ describe('Authorization & permissions', () => {
         const emailAddress = 'test1@test.com';
         let verificationToken: string;
 
+        beforeEach(() => {
+            sendEmailFn = jest.fn();
+        });
+
         it('register a new account', async () => {
             const verificationTokenPromise = getVerificationTokenPromise();
             const input: RegisterCustomerInput = {
@@ -205,11 +205,12 @@ describe('Authorization & permissions', () => {
 
             verificationToken = newVerificationToken;
         });
+
         it('refreshCustomerVerification does nothing with an unrecognized emailAddress', async () => {
             const result = await client.query(REFRESH_TOKEN, {
                 emailAddress: 'never-been-registered@test.com',
             });
-
+            await waitForSendEmailFn();
             expect(result.refreshCustomerVerification).toBe(true);
             expect(sendEmailFn).not.toHaveBeenCalled();
         });
@@ -244,6 +245,18 @@ describe('Authorization & permissions', () => {
             expect(result.verifyCustomerAccount.user.identifier).toBe('test1@test.com');
         });
 
+        it('registration silently fails if attempting to register an email already verified', async () => {
+            const input: RegisterCustomerInput = {
+                firstName: 'Dodgy',
+                lastName: 'Hacker',
+                emailAddress,
+            };
+            const result = await client.query(REGISTER_ACCOUNT, { input });
+            await waitForSendEmailFn();
+            expect(result.registerCustomerAccount).toBe(true);
+            expect(sendEmailFn).not.toHaveBeenCalled();
+        });
+
         it('verification fails if attempted a second time', async () => {
             try {
                 await client.query(VERIFY_EMAIL, {
@@ -331,6 +344,13 @@ describe('Authorization & permissions', () => {
         };
     }
 
+    /**
+     * A "sleep" function which allows the sendEmailFn time to get called.
+     */
+    function waitForSendEmailFn() {
+        return new Promise(resolve => setTimeout(resolve, 10));
+    }
+
     const REGISTER_ACCOUNT = gql`
         mutation Register($input: RegisterCustomerInput!) {
             registerCustomerAccount(input: $input)

+ 8 - 4
server/src/service/services/customer.service.ts

@@ -80,17 +80,21 @@ export class CustomerService {
         return this.connection.getRepository(Customer).save(customer);
     }
 
-    async registerCustomerAccount(ctx: RequestContext, input: RegisterCustomerInput): Promise<Customer> {
+    async registerCustomerAccount(ctx: RequestContext, input: RegisterCustomerInput): Promise<boolean> {
+        let user = await this.userService.getUserByEmailAddress(input.emailAddress);
+        if (user && user.verified) {
+            // If the user has already been verified, do nothing
+            return false;
+        }
         const customer = await this.createOrUpdate({
             emailAddress: input.emailAddress,
             title: input.title || '',
             firstName: input.firstName || '',
             lastName: input.lastName || '',
         });
-        let user = await this.userService.getUserByEmailAddress(input.emailAddress);
         if (!user) {
             user = await this.userService.createCustomerUser(input.emailAddress);
-        } else {
+        } else if (!user.verified) {
             user = await this.userService.setVerificationToken(user);
         }
         customer.user = user;
@@ -98,7 +102,7 @@ export class CustomerService {
         if (!user.verified) {
             this.eventBus.publish(new AccountRegistrationEvent(ctx, user));
         }
-        return customer;
+        return true;
     }
 
     async refreshVerificationToken(ctx: RequestContext, emailAddress: string) {