Преглед на файлове

feat(core): Add admin helpers to ExternalAuthenticationService

Michael Bromley преди 5 години
родител
ревизия
3456ffb286

+ 92 - 12
packages/core/src/service/helpers/external-authentication/external-authentication.service.ts

@@ -4,9 +4,13 @@ import { HistoryEntryType } from '@vendure/common/lib/generated-types';
 import { Connection } from 'typeorm';
 
 import { RequestContext } from '../../../api/common/request-context';
+import { Administrator } from '../../../entity/administrator/administrator.entity';
 import { ExternalAuthenticationMethod } from '../../../entity/authentication-method/external-authentication-method.entity';
 import { Customer } from '../../../entity/customer/customer.entity';
+import { Role } from '../../../entity/role/role.entity';
 import { User } from '../../../entity/user/user.entity';
+import { AdministratorService } from '../../services/administrator.service';
+import { CustomerService } from '../../services/customer.service';
 import { HistoryService } from '../../services/history.service';
 import { RoleService } from '../../services/role.service';
 
@@ -23,28 +27,47 @@ export class ExternalAuthenticationService {
         @InjectConnection() private connection: Connection,
         private roleService: RoleService,
         private historyService: HistoryService,
+        private customerService: CustomerService,
+        private administratorService: AdministratorService,
     ) {}
 
     /**
      * @description
      * Looks up a User based on their identifier from an external authentication
-     * provider.
+     * provider, ensuring this User is associated with a Customer account.
      */
-    async findUser(strategy: string, externalIdentifier: string): Promise<User | undefined> {
-        return await this.connection
-            .getRepository(User)
-            .createQueryBuilder('user')
-            .leftJoinAndSelect('user.authenticationMethods', 'authMethod')
-            .where('authMethod.strategy = :strategy', { strategy })
-            .andWhere('authMethod.externalIdentifier = :externalIdentifier', { externalIdentifier })
-            .andWhere('user.deletedAt IS NULL')
-            .getOne();
+    async findCustomerUser(strategy: string, externalIdentifier: string): Promise<User | undefined> {
+        const user = await this.findUser(strategy, externalIdentifier);
+
+        if (user) {
+            // Ensure this User is associated with a Customer
+            const customer = await this.customerService.findOneByUserId(user.id);
+            if (customer) {
+                return user;
+            }
+        }
     }
 
     /**
      * @description
-     * If a user has been successfully authenticated by an external authentication provider, yet cannot
-     * be found using `findUserByExternalAuthenticationMethod`, then we need to create a new User and
+     * Looks up a User based on their identifier from an external authentication
+     * provider, ensuring this User is associated with an Administrator account.
+     */
+    async findAdministratorUser(strategy: string, externalIdentifier: string): Promise<User | undefined> {
+        const user = await this.findUser(strategy, externalIdentifier);
+        if (user) {
+            // Ensure this User is associated with an Administrator
+            const administrator = await this.administratorService.findOneByUserId(user.id);
+            if (administrator) {
+                return user;
+            }
+        }
+    }
+
+    /**
+     * @description
+     * If a customer has been successfully authenticated by an external authentication provider, yet cannot
+     * be found using `findCustomerUser`, then we need to create a new User and
      * Customer record in Vendure for that user. This method encapsulates that logic as well as additional
      * housekeeping such as adding a record to the Customer's history.
      */
@@ -107,4 +130,61 @@ export class ExternalAuthenticationService {
 
         return savedUser;
     }
+
+    /**
+     * @description
+     * If an administrator has been successfully authenticated by an external authentication provider, yet cannot
+     * be found using `findAdministratorUser`, then we need to create a new User and
+     * Administrator record in Vendure for that user.
+     */
+    async createAdministratorAndUser(
+        ctx: RequestContext,
+        config: {
+            strategy: string;
+            externalIdentifier: string;
+            identifier: string;
+            emailAddress?: string;
+            firstName?: string;
+            lastName?: string;
+            roles: Role[];
+        },
+    ) {
+        const newUser = new User({
+            identifier: config.identifier,
+            roles: config.roles,
+            verified: true,
+        });
+
+        const authMethod = await this.connection.manager.save(
+            new ExternalAuthenticationMethod({
+                externalIdentifier: config.externalIdentifier,
+                strategy: config.strategy,
+            }),
+        );
+
+        newUser.authenticationMethods = [authMethod];
+        const savedUser = await this.connection.manager.save(newUser);
+
+        const administrator = await this.connection.manager.save(
+            new Administrator({
+                emailAddress: config.emailAddress,
+                firstName: config.firstName,
+                lastName: config.lastName,
+                user: savedUser,
+            }),
+        );
+
+        return newUser;
+    }
+
+    private findUser(strategy: string, externalIdentifier: string): Promise<User | undefined> {
+        return this.connection
+            .getRepository(User)
+            .createQueryBuilder('user')
+            .leftJoinAndSelect('user.authenticationMethods', 'authMethod')
+            .where('authMethod.strategy = :strategy', { strategy })
+            .andWhere('authMethod.externalIdentifier = :externalIdentifier', { externalIdentifier })
+            .andWhere('user.deletedAt IS NULL')
+            .getOne();
+    }
 }

+ 1 - 1
packages/dev-server/test-plugins/google-auth/google-authentication-strategy.ts

@@ -46,7 +46,7 @@ export class GoogleAuthenticationStrategy implements AuthenticationStrategy<Goog
         if (!payload || !payload.email) {
             return false;
         }
-        const user = await this.externalAuthenticationService.findUser(this.name, payload.sub);
+        const user = await this.externalAuthenticationService.findCustomerUser(this.name, payload.sub);
         if (user) {
             return user;
         }