Как получить доступ к SharedService на уровне модуля в Angular 5+

Я относительно новичок в Angular5/TypeScript, поэтому я прошу прощения за (возможно) тривиальный вопрос.

Я пытаюсь реализовать службу аутентификации, которую я намерен использовать, чтобы позволить моему веб-интерфейсу Angular5 использовать некоторый REST API, предоставляемый бэкэндом WordPress.

Пока сервис реализован и работает. Чего мне не хватает, так это способа ввода данных для входа в REST-запросы.

Если быть более точным, я знаю, как это сделать, но сейчас я не знаю, как получить доступ к информации для входа, которую я ранее хранил в моей общей службе.

Но позвольте мне быть еще более конкретным и позвольте мне поделиться своим кодом:

// auth.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';

import { JwtHelperService } from '@auth0/angular-jwt';

interface IUser
{
    token: string,
    token_expires: number,
    user_display_name: string,
}

@Injectable()
export class AuthService
{
    private currentUser: IUser = null;
    private nonce: string = '';

    constructor(
        private http: HttpClient,
        private jwt: JwtHelperService,
    )
    {
        // set User Info if saved in local/session storage
        .
        .
        .
    }

    logIn(username: string, password: string, persist: boolean): Observable<boolean>
    {
        return this.http.post(
            API_BASE_DOMAIN + API_BASE_PATH + '/jwt-auth/v1/token',
            { username: username, password: password },
            {
                observe: 'response', // Full response instead of the body only
                withCredentials: true, // Send cookies
            }
        ).map(response  => {
            this.nonce = response.headers.get('X-WP-Nonce');
            const body: any = response.body

            // login successful if there's a jwt token in the response
            if (body.token)
            {
                // set current user data
                this.currentUser = <IUser>body;

                // store username and jwt token in local storage to keep user logged in between page refreshes
                let storage = (persist) ? localStorage : sessionStorage;
                storage.setItem('currentUser', JSON.stringify(this.currentUser));

                // return true to indicate successful login
                return true;
            }
            else
            {
                // return false to indicate failed login
                return false;
            }
        });
    }

    getNonce(): string
    {
        console.log((this.nonce) ? this.nonce : '');
        return (this.nonce) ? this.nonce : '';
    }

    getToken(): string
    {
        console.log((this.currentUser) ? this.currentUser.token : '');
        return (this.currentUser) ? this.currentUser.token : '';
    }
}



// app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { JwtModule } from '@auth0/angular-jwt';
import { RouterModule, Routes } from '@angular/router';

import { AppComponent } from './app.component';

import { AuthService } from './main/auth/services/auth.service';
import { AuthGuardService } from './main/auth/services/auth-guard.service';

import { API_BASE_DOMAIN } from './main/auth/services/auth.service';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { NonceHttpInterceptor } from './main/auth/auth.interceptor';

const appRoutes: Routes = [
   .
   .
   .
];


@NgModule({
    declarations: [
        AppComponent
    ],
    imports     : [
        BrowserModule,
        HttpClientModule,
        RouterModule.forRoot(appRoutes),

        // Jwt Token Injection
        JwtModule.forRoot({
            config: {
                tokenGetter: (***AuthService?????***).getToken,
                whitelistedDomains: [ API_BASE_DOMAIN ]
            }
        })
    ],
    providers   : [
        AuthService,
        AuthGuardService,
        {
          provide: HTTP_INTERCEPTORS,
          useClass: NonceHttpInterceptor,
          multi: true
        }
    ],
    bootstrap   : [
        AppComponent
    ]
})

export class AppModule
{
}

Как вы можете видеть в моем коде в //JWT Token Injection, мне нужно указать средство получения токена, которое реализовано в моем auth.service.

В файле компонента я могу получить доступ к его публичным методам, внедрив службу в качестве параметра для конструктора, например так:

//login.component.ts
import { AuthService } from '../services/auth.service';

@Component({
      .
      .
      .
})

export class MyLoginComponent implements OnInit
{
    constructor(
        private authService: AuthService,
    )
    {
      .
      .
      .
    }

    onFormSubmit()
    {
        this.authService.logIn(uname, pwd, persist)
            .subscribe(
               .
               .
               .
            );
    }
}

Но я, похоже, не могу найти способ доступа к методу сервиса на уровне модуля!

Я знаю, что я мог бы использовать статический доступ для своего tokenGetter и перемещать все на уровне класса, а не на уровне экземпляра (например, так: AuthService.getToken) но я думаю, что есть лучший, более элегантный способ доступа к getToken() метод.

Заранее благодарю за любую подсказку / помощь.

1 ответ

Решение

Angular2-jwt поддерживает использование функции фабрики пользовательских опций, для определенных случаев, например, когда

Функция tokenGetter опирается на сервис

Определите заводскую функцию следующим образом

export function jwtOptionsFactory(authService: AuthService) {
  return {
    tokenGetter: () => {return authService.getToken();},
    whitelistedDomains: [ API_BASE_DOMAIN ]
  }
}

Затем объявите эту функцию как фабрику для JWT_OPTIONS знак

imports: [
JwtModule.forRoot({
  jwtOptionsProvider: {
    provide: JWT_OPTIONS,
    useFactory: jwtOptionsFactory,
    deps: [AuthService]
  }
})
],

ПРИМЕЧАНИЕ. Если определен jwtOptionsFactory, то конфигурация игнорируется. Обе альтернативы конфигурации не могут быть определены одновременно.

Другие вопросы по тегам