问题
I have followed this link for creating custom service for authentication in loopback 4. I successfully created the service but while binding this service in application.ts I am getting the following error.
Argument of type 'typeof CustomUserService' is not assignable to parameter of type 'Constructor>'.
Construct signature return types 'CustomUserService' and 'UserService' are incompatible. The types returned by 'verifyCredentials(...)' are incompatible between these types. Type 'Promise' is not assignable to type 'Promise'. Property 'userCredentials' is missing in type 'import("d:/ionic-pr/loopback-projects/custom/src/models/user.model").User' but required in type 'import("d:/ionic-pr/loopback-projects/custom/node_modules/@loopback/authentication-jwt/dist/models/user.model").User'
GIT REPOSITORY - https://github.com/pratikjaiswal15/loopbck4uth
I have two models user and userCred with has one realtionship. The relation name is userCred
.
here is the code
thank you in advance
application.ts
import {UserCredRepository, UserRepository} from './repositories';
import {CustomUserService} from './services/custom-user.service';
import {UserServiceBindings} from '@loopback/authentication-jwt';
// Bind user service inside constructor
this.bind(UserServiceBindings.USER_SERVICE).toClass(CustomUserService),// error on this line
// Bind user and credentials repository
this.bind(UserServiceBindings.USER_REPOSITORY).toClass(
UserRepository,
),
this.bind(UserServiceBindings.USER_CREDENTIALS_REPOSITORY).toClass(
UserCredRepository,
)
custom-service.ts
import {UserService} from '@loopback/authentication';
import {repository} from '@loopback/repository';
import {HttpErrors} from '@loopback/rest';
import {securityId, UserProfile} from '@loopback/security';
import {compare} from 'bcryptjs';
// User --> MyUser
import {User} from '../models/user.model';
// UserRepository --> MyUserRepository
import {Credentials, UserRepository} from '../repositories/user.repository';
export class CustomUserService implements UserService<User, Credentials> {
constructor(
// UserRepository --> MyUserRepository
@repository(UserRepository) public userRepository: UserRepository,
) {}
// User --> MyUser
async verifyCredentials(credentials: Credentials): Promise<User> {
const invalidCredentialsError = 'Invalid email or password.';
const foundUser = await this.userRepository.findOne({
where: {email: credentials.email},
});
if (!foundUser) {
throw new HttpErrors.Unauthorized(invalidCredentialsError);
}
const credentialsFound = await this.userRepository.findCredentials(
foundUser.id,
);
if (!credentialsFound) {
throw new HttpErrors.Unauthorized(invalidCredentialsError);
}
const passwordMatched = await compare(
credentials.password,
credentialsFound.password,
);
if (!passwordMatched) {
throw new HttpErrors.Unauthorized(invalidCredentialsError);
}
return foundUser;
}
// User --> MyUser
convertToUserProfile(user: User): UserProfile {
let address = ''
if (user.address) {
address = user.address
}
return {
[securityId]: user.id!.toString(),
name: user.name,
id: user.id,
email: user.email,
address: address
};
}
}
user.repositor.ts
import {Getter, inject} from '@loopback/core';
import {DefaultCrudRepository, HasOneRepositoryFactory, repository} from '@loopback/repository';
import {MygodDataSource} from '../datasources';
import {User, UserCred, UserRelations} from '../models';
import {UserCredRepository} from './user-cred.repository';
export type Credentials = {
email: string;
password: string;
};
export class UserRepository extends DefaultCrudRepository<
User,
typeof User.prototype.id,
UserRelations
> {
public readonly userCred: HasOneRepositoryFactory<UserCred, typeof User.prototype.id>;
constructor(
@inject('datasources.mygod') dataSource: MygodDataSource, @repository.getter('UserCredRepository') protected userCredRepositoryGetter: Getter<UserCredRepository>,
) {
super(User, dataSource);
this.userCred = this.createHasOneRepositoryFactoryFor('userCred', userCredRepositoryGetter);
this.registerInclusionResolver('userCred', this.userCred.inclusionResolver);
}
async findCredentials(
userId: typeof User.prototype.id,
): Promise<UserCred | undefined> {
try {
return await this.userCred(userId).get();
} catch (err) {
if (err.code === 'ENTITY_NOT_FOUND') {
return undefined;
}
throw err;
}
}
}
回答1:
have a brief explaination of the issue at your git post Follow you answer at https://github.com/strongloop/loopback-next/issues/5541
来源:https://stackoverflow.com/questions/61969175/loopback-4-authentication-error-while-binding-custom-service