Reputation: 323
I'm building an Angular application using Nebular auth components. I need to add a custom implementation for registering, and also want to include an email validation stage, where the user is entered into the DB as inactive with registration, but is emailed a code in a link which they use to validate their email so they can be marked as active.
I keep getting tied up in dependency injection knots, but I don't see where I'm going wrong. I'd really appreciate some eyes on this. Thanks!
app.module.ts
@NgModule({
imports: [
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
AppRoutingModule,
SharedModule,
ThemeModule.forRoot(),
NbToastrModule.forRoot(),
StoreModule.forRoot(reducers, {
metaReducers,
runtimeChecks: {
strictStateImmutability: true,
strictActionImmutability: true,
},
}),
EffectsModule.forRoot(),
NbAuthModule.forRoot({
strategies: [
CustomAuthStrategy.setup({
name: "email",
baseEndpoint: "/auth/",
login: {
endpoint: "login",
redirect: {
success: HOME_PAGE,
failure: null,
},
},
register: {
endpoint: "register",
redirect: {
success: null,
failure: null,
},
},
verifyemail: {
endpoint: "verify",
},
logout: {
endpoint: "",
},
requestPass: {
endpoint: "requestpass",
},
resetPass: {
endpoint: "resetpass",
},
token: {
class: NbAuthJWTToken,
key: "token",
},
}),
],
forms: {},
}),
],
declarations: [AppComponent],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AddTokenHeaderHttpRequestInterceptor,
multi: true,
},
ApiService,
CustomAuthStrategy,
{ provide: NbAuthService, useClass: CustomAuthService },
NbTokenService,
HttpClient,
],
bootstrap: [AppComponent],
})
export class AppModule {}
custom-auth.service.ts:
@Injectable({
providedIn: "root",
})
export class CustomAuthService extends NbAuthService {
strategies: NbAuthStrategy[];
constructor(
protected tokenService: NbTokenService,
private injector: Injector,
) {
// Initialize strategies after injector is available
super(tokenService, []);
this.strategies = this.injector.get(NbAuthStrategy, []);
}
verifyEmail(
email: string,
code: string,
http: HttpClient,
): Observable<NbAuthResult> {
const endpoint = "/auth/verify";
return http.post(endpoint, { email, code }).pipe(
map((res: any) => {
return new NbAuthResult(
res.success,
res,
res.success ? "/auth/login" : null,
res.success ? [] : ["Verification failed."],
res.success
? ["Email verified successfully. Please log in."]
: [],
);
}),
);
}
}
custom-auth.strategy.ts:
export interface CustomAuthStrategyOptions
extends NbPasswordAuthStrategyOptions {
verifyemail?: {
endpoint: string;
};
}
@Injectable({
providedIn: "root",
})
export class CustomAuthStrategy extends NbPasswordAuthStrategy {
constructor(
protected http: HttpClient,
protected injector: Injector,
route: ActivatedRoute,
options: CustomAuthStrategyOptions,
) {
super(http, route);
}
static setup(
options: CustomAuthStrategyOptions,
): [typeof CustomAuthStrategy, CustomAuthStrategyOptions] {
return [CustomAuthStrategy, options];
}
protected handleResponse(res: any): NbAuthResult {
if (res.success) {
return new NbAuthResult(
true,
res,
this.getOption("register.redirect.success"),
[],
res.message,
);
} else {
return new NbAuthResult(
false,
res,
this.getOption("register.redirect.failure"),
this.getOption("errors.getter")(res),
this.getOption("messages.getter")(res),
);
}
}
register(data?: any): Observable<NbAuthResult> {
return this.http.post(this.getActionEndpoint("register"), data).pipe(
map((res) => this.handleResponse(res)),
catchError((res: HttpErrorResponse) => {
return of(
new NbAuthResult(
false,
res,
this.getOption("register.redirect.failure"),
this.getOption("errors.getter")(res),
),
);
}),
);
}
}
At present, I'm getting an error:
Error: This constructor was not compatible with Dependency Injection. at Module.ɵɵinvalidFactory (core.mjs:10057:11) at Object.CustomAuthStrategy_Factory [as factory] (
The other error I seem to be alternating with is: NullInjectorError: NullInjectorError: No provider for NB_AUTH_STRATEGIES!
Can you help a fried brain out? Thanks!
Upvotes: 0
Views: 53
Reputation: 323
In the end I worked this out.
static setup(
options: NbPasswordAuthStrategyOptions,
): [typeof CustomPasswordAuthStrategy, NbPasswordAuthStrategyOptions] {
return [CustomPasswordAuthStrategy, options];
}
That was enough to prevent the DI errors.
Upvotes: 0