ng2-smart-table icon indicating copy to clipboard operation
ng2-smart-table copied to clipboard

How to pass tokens ?

Open nameisvick opened this issue 8 years ago • 13 comments

source: ServerDataSource;

constructor(private http: Http) { this.source = new ServerDataSource(http, { endPoint: 'http://172.18.1.223/api/InspectionService/GetInspectionStatus' }); } can any 1 tell me how to pass tokens and setRequest header in the above service since i need to pass the API only if it is authorized

nameisvick avatar Nov 15 '17 09:11 nameisvick

I just started out using this package, but from what I understand you would probably have to create your own CustomDataSource, based off the ServerDataSource https://github.com/akveo/ng2-smart-table/tree/master/src/ng2-smart-table/lib/data-source/server

Copy paste those 2 files in your own project and add whatever functionnality you need

dizco avatar Nov 23 '17 20:11 dizco

Do you get any solutions? @nameisvick

uzzT avatar Dec 28 '17 07:12 uzzT

If you need to set a session/authentication token that it is applied app-wide, you can use Angular's HttpInterceptor class. You just need to create a class that extends HttpInterceptor, make it injectable and implement the function intercept(). In this function, you can do something like this:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return this.authService.getToken()
      .switchMap((token: NbAuthJWTToken) => {
        if (token) {
          const JWT = `Bearer ${token.getValue()}`;
          req = req.clone({
            setHeaders: {
              Authorization: JWT,
            },
          });
        }
        return next.handle(req);
      });
}

In my example, I get a JWT token from my authService and I make the same request adding that token on the headers. You can find more information on how to do that on the Angular documentation: https://angular.io/guide/http#writing-an-interceptor

There's the possibility, too, that the token you need to pass is specific only for this data request. In that case, I agree that you need to implement you own custom ServerDataSource that takes care of this request.

clasqui avatar Dec 28 '17 10:12 clasqui

@hulehule20 i have tried the method , it can reset or add token on the headers from my other httpRequest expected the httpRequest from the method when i use the class serverdatasource it always prompts 403 forbidden ,
here is my code: ` token.intercepter.ts import { Injectable, Inject, Component } from '@angular/core'; import { Http, RequestOptions, ConnectionBackend, HttpModule } from '@angular/http'; import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'; import { NB_AUTH_TOKEN_WRAPPER_TOKEN, NbAuthJWTToken, NbTokenService } from '@nebular/auth'; import { Observable } from 'rxjs/Observable'; export class TokenInterceptor implements HttpInterceptor { constructor( @Inject(NB_AUTH_TOKEN_WRAPPER_TOKEN) private token: NbAuthJWTToken, ) {

}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    request = request.clone({
        setHeaders: {
            Authorization: `Bearer ${this.token.getValue()}`
        }
    });
    console.log(request);
    return next.handle(request);
}

} app.module.ts @NgModule({ declarations: [AppComponent], imports: [ BrowserModule, BrowserAnimationsModule, HttpModule, AppRoutingModule,

    NgbModule.forRoot(),
    ThemeModule.forRoot(),
    CoreModule.forRoot(),
],
bootstrap: [AppComponent],
providers: [
    { provide: APP_BASE_HREF, useValue: '/' },
    { provide: NB_AUTH_TOKEN_WRAPPER_TOKEN, useClass: NbAuthJWTToken },
    { provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true},
],

}) `

uzzT avatar Dec 29 '17 06:12 uzzT

Beacuse serverdatasource use http form '@angular/http', while when you add the interceptor you need to use httpclient from '@angular/common/http', i just cannot find how to handle with it @hulehule20 , sorry for my poor expression;

uzzT avatar Dec 29 '17 06:12 uzzT

@hulehule20 https://medium.com/@ryanchenkie_40935/angular-authentication-using-the-http-client-and-http-interceptors-2f9d1540eb8 in this blog , the author methoded If we try to make requests with the traditional Httpclass, the interceptor won’t be hit. while the serverdatasource in smart-table is using httpClass , how to resolve it?

uzzT avatar Jan 02 '18 02:01 uzzT

Problem 🔴

As you just said @uzzT, the new HttpInterceptor only works with the new HttpClient class from Angular 4.3 or beyond🔝. Therefore, as we can see on the server.data-source.ts file

import { Http } from '@angular/http';

the token injection is not going to work with the requests made by this data source because it is using the old Http class to make its requests.

Solution 💡

I think the better solution here should be upgrading to HttpClient in your custom data-source class while we wait a project-wide update for ng2-smart-table by Akveo. To accomplish this I suggest you have a look at this article here and also check out Angular's documentation on HttpClient. The basic change you need to make to your code is including the new library like this:

import { HttpClient } from '@angular/common/http';

and then update the methods that create and perform the request so they use the new class. I think that the most crititcal methods are the ones between lines 73 and 84 in the server.data-source.ts file.

Further Help ⚠️

If you need further help transitioning to HttpClient just send me an email 📩 and I'll try to help you out on implementing it in your class. I think that this is no longer an ng2-smart-table issue and that this issue should be closed now, and that if you need it we can continue the discussion by email.

clasqui avatar Jan 02 '18 14:01 clasqui

@hulehule20 thanks for your patience,i have already changed the source code of server.data-source.ts file

uzzT avatar Jan 03 '18 01:01 uzzT

You don't need to modify the source code, this snippet make the magic:

const headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
headers.append('Authorization', `Bearer ${token}`);
const options = new RequestOptions({
    headers: headers
});
const connection = new XHRBackend(new BrowserXhr(), new ResponseOptions(), new CookieXSRFStrategy());
http: Http = new Http(connection, options);

this.sourceConf = new ServerSourceConf({
    endPoint: 'http://example.com/endpoint',
    totalKey: 'total',
    dataKey: 'data'
});
this.source = new ServerDataSource(http, this.sourceConf);

Hope this help.

yunier0525 avatar Mar 13 '18 20:03 yunier0525

My solution is :

export class HeadersServerDataSource extends ServerDataSource {
  httpHeaders: HttpHeaders
  constructor(protected http: HttpClient, headers: HttpHeaders, conf: ServerSourceConf | {} = {}) {
    super(http, conf);
    this.httpHeaders = headers
  }

  protected requestElements(): Observable<any> {
    let httpParams = this.createRequesParams();
    return this.http.get(this.conf.endPoint, { params: httpParams, headers: this.httpHeaders, observe: 'response' });
  }
}

theromis avatar Jul 17 '20 13:07 theromis

PR created https://github.com/akveo/ng2-smart-table/pull/1188/files

theromis avatar Jul 18 '20 03:07 theromis

@theromis you are genius thx all work perfect

tesak68711730 avatar Jul 09 '21 10:07 tesak68711730

I just started out using this package, but from what I understand you would probably have to create your own CustomDataSource, based off the ServerDataSource https://github.com/akveo/ng2-smart-table/tree/master/src/ng2-smart-table/lib/data-source/server

Copy paste those 2 files in your own project and add whatever functionnality you need

This link is broken. Does anybody have steps to create custom class from ServerDataSource? I managed to write something like this, but I guess there could be more elegant way:

export class MyDataSource extends ServerDataSource {
    constructor(http: HttpClient, conf?: ServerSourceConf | {}) {        
        super(http, conf);
        this.init();
      }     
      public init(): Promise<any> {
          let endPoint = `${environment.apiEndpoint}/${this.conf.endPoint}`;
          this.conf.endPoint = endPoint;
          this.conf.sortFieldKey = 'orderBy';
          this.conf.sortDirKey = 'sortDirection';
          this.conf.pagerPageKey = 'pageNumber';
          this.conf.pagerLimitKey = 'pageSize';
          this.conf.filterFieldKey = null;
          this.conf.totalKey = 'count';
          this.conf.dataKey = 'value';
          return super.getElements();
      }
}

call:

this.source = new MyDataSource(this.http, {
	endPoint: 'myMethod'
});

imbrod avatar Jan 21 '22 16:01 imbrod