|
|
@@ -0,0 +1,110 @@
|
|
|
+import { Injectable } from '@nestjs/common';
|
|
|
+import { InjectConnection } from '@nestjs/typeorm';
|
|
|
+import { HistoryEntryType } from '@vendure/common/lib/generated-types';
|
|
|
+import { Connection } from 'typeorm';
|
|
|
+
|
|
|
+import { RequestContext } from '../../../api/common/request-context';
|
|
|
+import { ExternalAuthenticationMethod } from '../../../entity/authentication-method/external-authentication-method.entity';
|
|
|
+import { Customer } from '../../../entity/customer/customer.entity';
|
|
|
+import { User } from '../../../entity/user/user.entity';
|
|
|
+import { HistoryService } from '../../services/history.service';
|
|
|
+import { RoleService } from '../../services/role.service';
|
|
|
+
|
|
|
+/**
|
|
|
+ * @description
|
|
|
+ * This is a helper service which exposes methods related to looking up and creating Users based on an
|
|
|
+ * external {@link AuthenticationStrategy}.
|
|
|
+ *
|
|
|
+ * @docsCategory auth
|
|
|
+ */
|
|
|
+@Injectable()
|
|
|
+export class ExternalAuthenticationService {
|
|
|
+ constructor(
|
|
|
+ @InjectConnection() private connection: Connection,
|
|
|
+ private roleService: RoleService,
|
|
|
+ private historyService: HistoryService,
|
|
|
+ ) {}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @description
|
|
|
+ * Looks up a User based on their identifier from an external authentication
|
|
|
+ * provider.
|
|
|
+ */
|
|
|
+ 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();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @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
|
|
|
+ * 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.
|
|
|
+ */
|
|
|
+ async createCustomerAndUser(
|
|
|
+ ctx: RequestContext,
|
|
|
+ config: {
|
|
|
+ strategy: string;
|
|
|
+ externalIdentifier: string;
|
|
|
+ verified: boolean;
|
|
|
+ emailAddress: string;
|
|
|
+ firstName?: string;
|
|
|
+ lastName?: string;
|
|
|
+ },
|
|
|
+ ): Promise<User> {
|
|
|
+ const customerRole = await this.roleService.getCustomerRole();
|
|
|
+ const newUser = new User({
|
|
|
+ identifier: config.emailAddress,
|
|
|
+ roles: [customerRole],
|
|
|
+ verified: config.verified || false,
|
|
|
+ });
|
|
|
+
|
|
|
+ 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 customer = await this.connection.manager.save(
|
|
|
+ new Customer({
|
|
|
+ emailAddress: config.emailAddress,
|
|
|
+ firstName: config.firstName,
|
|
|
+ lastName: config.lastName,
|
|
|
+ user: savedUser,
|
|
|
+ }),
|
|
|
+ );
|
|
|
+
|
|
|
+ await this.historyService.createHistoryEntryForCustomer({
|
|
|
+ customerId: customer.id,
|
|
|
+ ctx,
|
|
|
+ type: HistoryEntryType.CUSTOMER_REGISTERED,
|
|
|
+ data: {
|
|
|
+ strategy: config.strategy,
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ if (config.verified) {
|
|
|
+ await this.historyService.createHistoryEntryForCustomer({
|
|
|
+ customerId: customer.id,
|
|
|
+ ctx,
|
|
|
+ type: HistoryEntryType.CUSTOMER_VERIFIED,
|
|
|
+ data: {
|
|
|
+ strategy: config.strategy,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ return savedUser;
|
|
|
+ }
|
|
|
+}
|