-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core): Export ExternalAuthenticationService
Used to simplify the creation of external authentication strategies
- Loading branch information
1 parent
39c743b
commit c3ed2cd
Showing
6 changed files
with
136 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
110 changes: 110 additions & 0 deletions
110
packages/core/src/service/helpers/external-authentication/external-authentication.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters