@@ -178,6 +178,120 @@ The code snippet for whoAmI function:
178178The complete file is in
179179[user .controller .ts ](https : // github.com/strongloop/loopback-next/tree/master/extensions/authentication-jwt/src/__tests__/fixtures/controllers/user.controller.ts)
180180
181+ ## Customize Model
182+
183+ 1. Create your own user model and repository by ` lb4 model ` and
184+ ` lb4 repository ` .
185+
186+ 2. The user service requires the user model , to provide your own one , you need
187+ to copy the
188+ [` user.service.ts ` ](https : // github.com/strongloop/loopback-next/blob/master/extensions/authentication-jwt/src/services/user.service.ts)
189+ file into your application , e.g. copy to file
190+ ` myapp/src/services/custom.user.service.ts ` , and replace the default ` User ` ,
191+ ` UserRepository ` with ` MyUser ` , ` MyUserRepository ` :
192+
193+ <details >
194+ <summary ><strong >Check The Code </strong ></summary >
195+ <p >
196+
197+ ` ` ` ts
198+ import {UserService} from '@loopback/authentication';
199+ import {repository} from '@loopback/repository';
200+ import {HttpErrors} from '@loopback/rest';
201+ import {securityId, UserProfile} from '@loopback/security';
202+ import {compare} from 'bcryptjs';
203+ // User --> MyUser
204+ import {MyUser} from '../models';
205+ // UserRepository --> MyUserRepository
206+ import {MyUserRepository} from '../repositories';
207+
208+ export type Credentials = {
209+ email: string;
210+ password: string;
211+ };
212+
213+ // User --> MyUser
214+ export class CustomUserService implements UserService<MyUser, Credentials> {
215+ constructor(
216+ // UserRepository --> MyUserRepository
217+ @repository(MyUserRepository) public userRepository: MyUserRepository,
218+ ) {}
219+
220+ // User --> MyUser
221+ async verifyCredentials(credentials: Credentials): Promise<MyUser> {
222+ const invalidCredentialsError = 'Invalid email or password.';
223+
224+ const foundUser = await this.userRepository.findOne({
225+ where: {email: credentials.email},
226+ });
227+ if (!foundUser) {
228+ throw new HttpErrors.Unauthorized(invalidCredentialsError);
229+ }
230+
231+ const credentialsFound = await this.userRepository.findCredentials(
232+ foundUser.id,
233+ );
234+ if (!credentialsFound) {
235+ throw new HttpErrors.Unauthorized(invalidCredentialsError);
236+ }
237+
238+ const passwordMatched = await compare(
239+ credentials.password,
240+ credentialsFound.password,
241+ );
242+
243+ if (!passwordMatched) {
244+ throw new HttpErrors.Unauthorized(invalidCredentialsError);
245+ }
246+
247+ return foundUser;
248+ }
249+
250+ // User --> MyUser
251+ convertToUserProfile(user: MyUser): UserProfile {
252+ return {
253+ [securityId]: user.id.toString(),
254+ name: user.username,
255+ id: user.id,
256+ email: user.email,
257+ };
258+ }
259+ }
260+ ` ` `
261+
262+ </p >
263+ </details >
264+
265+ 3. Bind ` MyUserRepository ` (and ` MyUserCredentialsRepository ` if you create your
266+ own as well ) to the corresponding key in your ` application.ts ` :
267+
268+ ` ` ` ts
269+ import {CustomUserService} from './services/custom-user-service';
270+ import {MyUserRepository, MyUserCredentialsRepository} from './repositories';
271+ import {UserServiceBindings} from '@loopback/extension-authentication-jwt';
272+
273+ export class TestApplication extends BootMixin(
274+ ServiceMixin(RepositoryMixin(RestApplication)),
275+ ) {
276+ constructor(options: ApplicationConfig = {}) {
277+ super(options);
278+ // ...other setup
279+ this.component(JWTAuthenticationComponent);
280+ // Bind datasource
281+ this.dataSource(DbDataSource, UserServiceBindings.DATASOURCE_NAME);
282+ // Bind user service
283+ this.bind(UserServiceBindings.USER_SERVICE).toClass(CustomUserService),
284+ // Bind user and credentials repository
285+ this.bind(UserServiceBindings.USER_REPOSITORY).toClass(
286+ UserRepository,
287+ ),
288+ this.bind(UserServiceBindings.USER_CREDENTIALS_REPOSITORY).toClass(
289+ UserCredentialsRepository,
290+ ),
291+ }
292+ }
293+ ` ` `
294+
181295## Future Work
182296
183297The security specification is currently manually added in the application file .
0 commit comments