Loopback 4: Failed @repository dependency injection (TypeError: Cannot read property 'findOne' of undefined)
Loopback 4: Failed @repository dependency injection (TypeError: Cannot read property 'findOne' of undefined)
我正在我的 Loopback 4 应用程序上设置 Bearer Token 身份验证,我正在遵循以下一般实施:https://github.com/strongloop/loopback-next/tree/master/packages/authentication。
在我的 src/providers/auth-strategy.provider.ts
中,我需要一个存储库对象的引用才能查询我的数据源。我希望在我工作的 class 的构造函数中使用 @repository
装饰器通过依赖注入来实现这一点。
但是,当我在 @repository
装饰器创建的存储库引用上调用 findOne()
时,会产生以下错误:
TypeError: Cannot read property 'findOne' of undefined
这是我的 auth-strategy.provider.ts
版本:
import {Provider, inject, ValueOrPromise} from '@loopback/context';
import {Strategy} from 'passport';
import {
AuthenticationBindings,
AuthenticationMetadata,
} from '@loopback/authentication';
import {IVerifyOptions} from 'passport-http-bearer';
import {ApiClient} from '../models';
import {ApiClientRepository} from '../repositories';
import {Strategy as BearerStrategy} from 'passport-http-bearer';
import {repository} from '@loopback/repository';
export class BearerStrategyProvider implements Provider<Strategy | undefined> {
constructor(
@inject(AuthenticationBindings.METADATA)
private metadata: AuthenticationMetadata,
@repository(ApiClientRepository)
private apiClientRepository: ApiClientRepository,
) {}
value(): ValueOrPromise<Strategy | undefined> {
// The function was not decorated, so we shouldn't attempt authentication
if (!this.metadata) {
return undefined;
}
const name = this.metadata.strategy;
if (name === 'BearerStrategy') {
return new BearerStrategy(this.verify);
} else {
return Promise.reject(`The strategy ${name} is not available.`);
}
}
async verify(
token: string,
done: (error: any, user?: any, options?: IVerifyOptions | string) => void,
) {
// call cb(null, false) when user not found
// call cb(null, user) when user is authenticated
let apiClient: ApiClient | null;
try {
apiClient = await this.apiClientRepository.findOne({
where: {Token: token},
});
if (apiClient) {
console.log("Found CLIENT!!! Here: " + apiClient.Email);
done(null, {user: apiClient});
} else {
// if token not found in DB:
done('Authentication Error.', false);
}
} catch (e) {
console.log(e);
}
}
}
其实我觉得你的情况和这个问题是一样的:
https://github.com/strongloop/loopback-next/issues/1835
您应该将验证函数的上下文绑定到您的 class,否则 this
不是 BearerStrategyProvider
,而是 BearerStrategy
,那么 this.apiClientRepository
就不是存在于 class。你可以这样绑定它:
return new BearerStrategy(this.verify.bind(this));
我正在我的 Loopback 4 应用程序上设置 Bearer Token 身份验证,我正在遵循以下一般实施:https://github.com/strongloop/loopback-next/tree/master/packages/authentication。
在我的 src/providers/auth-strategy.provider.ts
中,我需要一个存储库对象的引用才能查询我的数据源。我希望在我工作的 class 的构造函数中使用 @repository
装饰器通过依赖注入来实现这一点。
但是,当我在 @repository
装饰器创建的存储库引用上调用 findOne()
时,会产生以下错误:
TypeError: Cannot read property 'findOne' of undefined
这是我的 auth-strategy.provider.ts
版本:
import {Provider, inject, ValueOrPromise} from '@loopback/context';
import {Strategy} from 'passport';
import {
AuthenticationBindings,
AuthenticationMetadata,
} from '@loopback/authentication';
import {IVerifyOptions} from 'passport-http-bearer';
import {ApiClient} from '../models';
import {ApiClientRepository} from '../repositories';
import {Strategy as BearerStrategy} from 'passport-http-bearer';
import {repository} from '@loopback/repository';
export class BearerStrategyProvider implements Provider<Strategy | undefined> {
constructor(
@inject(AuthenticationBindings.METADATA)
private metadata: AuthenticationMetadata,
@repository(ApiClientRepository)
private apiClientRepository: ApiClientRepository,
) {}
value(): ValueOrPromise<Strategy | undefined> {
// The function was not decorated, so we shouldn't attempt authentication
if (!this.metadata) {
return undefined;
}
const name = this.metadata.strategy;
if (name === 'BearerStrategy') {
return new BearerStrategy(this.verify);
} else {
return Promise.reject(`The strategy ${name} is not available.`);
}
}
async verify(
token: string,
done: (error: any, user?: any, options?: IVerifyOptions | string) => void,
) {
// call cb(null, false) when user not found
// call cb(null, user) when user is authenticated
let apiClient: ApiClient | null;
try {
apiClient = await this.apiClientRepository.findOne({
where: {Token: token},
});
if (apiClient) {
console.log("Found CLIENT!!! Here: " + apiClient.Email);
done(null, {user: apiClient});
} else {
// if token not found in DB:
done('Authentication Error.', false);
}
} catch (e) {
console.log(e);
}
}
}
其实我觉得你的情况和这个问题是一样的: https://github.com/strongloop/loopback-next/issues/1835
您应该将验证函数的上下文绑定到您的 class,否则 this
不是 BearerStrategyProvider
,而是 BearerStrategy
,那么 this.apiClientRepository
就不是存在于 class。你可以这样绑定它:
return new BearerStrategy(this.verify.bind(this));