diff --git a/src/app/auth/permission.service.spec.ts b/src/app/auth/permission.service.spec.ts index 57333ee..bf4d0a5 100644 --- a/src/app/auth/permission.service.spec.ts +++ b/src/app/auth/permission.service.spec.ts @@ -1,36 +1,183 @@ import { TestBed } from '@angular/core/testing'; -import { PermissionService, Permission } from './permission.service'; +import { PermissionService, Permission, UserRoleData } from './permission.service'; +import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing'; +import { AUTH_API_URL } from '../shared/auth-api'; +import { JwtHelperService } from '@auth0/angular-jwt'; +import { of } from 'rxjs'; describe('Service: Permission Service', () => { + const jwtHelper: JwtHelperService = new JwtHelperService(); // tslint:disable-next-line:max-line-length - const fakeToken = 'eyJhbGciOiJSUzI1NiIsImtpZCI6ImFVR3Y4bVFBODVqZzRWMURVOFVrMVcwdUtzeG4xODdLUU9OQUdsNkFNdGMiLCJ0eXAiOiJKV1QifQ.eyJhY3IiOiIwIiwiYWxsb3dlZC1vcmlnaW5zIjpbImh0dHA6Ly9hdXRoLm9wZW5zaGlmdC5pbyIsImh0dHA6Ly9vcGVuc2hpZnQuaW8iXSwiYXBwcm92ZWQiOnRydWUsImF1ZCI6Imh0dHA6Ly9vcGVuc2hpZnQuaW8iLCJhdXRoX3RpbWUiOjE1MzU0MTQxNjAsImF6cCI6Imh0dHA6Ly9vcGVuc2hpZnQuaW8iLCJlbWFpbCI6IlRlc3RVc2VyLTUwZWRmZjE4LTZjODYtNDkxMC1iMDY5LTM3ZDY4ZjFjMDJjMUB0ZXN0LmNvbSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiZXhwIjoxNTM4MDA2MTYwLCJmYW1pbHlfbmFtZSI6IiIsImdpdmVuX25hbWUiOiJUZXN0VXNlci01MGVkZmYxOC02Yzg2LTQ5MTAtYjA2OS0zN2Q2OGYxYzAyYzEiLCJpYXQiOjE1MzU0MTQxNjAsImlzcyI6Imh0dHA6Ly9hdXRoLm9wZW5zaGlmdC5pbyIsImp0aSI6IjEwOWQwOWVkLTkxY2MtNDM5My04ZmExLWJjMzE4N2FhNDBiYSIsIm5hbWUiOiJUZXN0VXNlci01MGVkZmYxOC02Yzg2LTQ5MTAtYjA2OS0zN2Q2OGYxYzAyYzEiLCJuYmYiOjAsInBlcm1pc3Npb25zIjpbeyJyZXNvdXJjZV9zZXRfbmFtZSI6bnVsbCwicmVzb3VyY2Vfc2V0X2lkIjoiYzBlZTJiOTQtYWVlMy00YzQxLTllMTUtNmZhMzMwY2U4ZTBiIiwic2NvcGVzIjpbImxpbWEiXSwiZXhwIjoxNTM1NTAwNTcyfV0sInByZWZlcnJlZF91c2VybmFtZSI6IlRlc3RVc2VySWRlbnRpdHktNTBlZGZmMTgtNmM4Ni00OTEwLWIwNjktMzdkNjhmMWMwMmMxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19LCJicm9rZXIiOnsicm9sZXMiOlsicmVhZC10b2tlbiJdfX0sInNlc3Npb25fc3RhdGUiOiIiLCJzdWIiOiI3YWNhNThkZi1iNmUxLTRhNTgtOGQzYS02MDBkZjM4MmRkNDAiLCJ0eXAiOiJCZWFyZXIifQ.xbY2neM56yeHRwhXnaKLp67o6ine38MkJb4Yhe-guQ2nN0-aLrXkqxYF7Jgqb-8w1TfDfdUuKQGWUK1Ye-Xh10biZq-Cl7amPIRQwZ8bLsoII9KFXTjkUQbCxOjNxMl89PuliIP_rO3OXydATnL2KAoU36qKbkBiUTKpQNUOXkcb8wtID_SXE1lssHHNeHNVU358kJjMJUqYE0K59C8csddupR1vpEYJknoLW7nKxxWtAJYGYTOjCey8BkVom6bOgOXz0AiEq2aYdjcaRdwz4IeiLGeFIyvT_sIDyPgYFSR2YCN4_N3CSQPfQYdrQhDGKM7fKLBKnYqAwfUe2OeibQ'; + const fakeRptToken = 'eyJhbGciOiJSUzI1NiIsImtpZCI6ImFVR3Y4bVFBODVqZzRWMURVOFVrMVcwdUtzeG4xODdLUU9OQUdsNkFNdGMiLCJ0eXAiOiJKV1QifQ.eyJhY3IiOiIwIiwiYWxsb3dlZC1vcmlnaW5zIjpbImh0dHA6Ly9hdXRoLm9wZW5zaGlmdC5pbyIsImh0dHA6Ly9vcGVuc2hpZnQuaW8iXSwiYXBwcm92ZWQiOnRydWUsImF1ZCI6Imh0dHA6Ly9vcGVuc2hpZnQuaW8iLCJhdXRoX3RpbWUiOjE1MzU0MTQxNjAsImF6cCI6Imh0dHA6Ly9vcGVuc2hpZnQuaW8iLCJlbWFpbCI6IlRlc3RVc2VyLTUwZWRmZjE4LTZjODYtNDkxMC1iMDY5LTM3ZDY4ZjFjMDJjMUB0ZXN0LmNvbSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiZXhwIjoxNTM4MDA2MTYwLCJmYW1pbHlfbmFtZSI6IiIsImdpdmVuX25hbWUiOiJUZXN0VXNlci01MGVkZmYxOC02Yzg2LTQ5MTAtYjA2OS0zN2Q2OGYxYzAyYzEiLCJpYXQiOjE1MzU0MTQxNjAsImlzcyI6Imh0dHA6Ly9hdXRoLm9wZW5zaGlmdC5pbyIsImp0aSI6IjEwOWQwOWVkLTkxY2MtNDM5My04ZmExLWJjMzE4N2FhNDBiYSIsIm5hbWUiOiJUZXN0VXNlci01MGVkZmYxOC02Yzg2LTQ5MTAtYjA2OS0zN2Q2OGYxYzAyYzEiLCJuYmYiOjAsInBlcm1pc3Npb25zIjpbeyJyZXNvdXJjZV9zZXRfbmFtZSI6bnVsbCwicmVzb3VyY2Vfc2V0X2lkIjoiYzBlZTJiOTQtYWVlMy00YzQxLTllMTUtNmZhMzMwY2U4ZTBiIiwic2NvcGVzIjpbImxpbWEiXSwiZXhwIjoxNTM1NTAwNTcyfV0sInByZWZlcnJlZF91c2VybmFtZSI6IlRlc3RVc2VySWRlbnRpdHktNTBlZGZmMTgtNmM4Ni00OTEwLWIwNjktMzdkNjhmMWMwMmMxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19LCJicm9rZXIiOnsicm9sZXMiOlsicmVhZC10b2tlbiJdfX0sInNlc3Npb25fc3RhdGUiOiIiLCJzdWIiOiI3YWNhNThkZi1iNmUxLTRhNTgtOGQzYS02MDBkZjM4MmRkNDAiLCJ0eXAiOiJCZWFyZXIifQ.xbY2neM56yeHRwhXnaKLp67o6ine38MkJb4Yhe-guQ2nN0-aLrXkqxYF7Jgqb-8w1TfDfdUuKQGWUK1Ye-Xh10biZq-Cl7amPIRQwZ8bLsoII9KFXTjkUQbCxOjNxMl89PuliIP_rO3OXydATnL2KAoU36qKbkBiUTKpQNUOXkcb8wtID_SXE1lssHHNeHNVU358kJjMJUqYE0K59C8csddupR1vpEYJknoLW7nKxxWtAJYGYTOjCey8BkVom6bOgOXz0AiEq2aYdjcaRdwz4IeiLGeFIyvT_sIDyPgYFSR2YCN4_N3CSQPfQYdrQhDGKM7fKLBKnYqAwfUe2OeibQ'; + // tslint:disable-next-line:max-line-length + const fakeAuthToken = 'eyJhbGciOiJSUzI1NiIsImtpZCI6InpELTU3b0JGSU1VWnNBV3FVbklzVnVfeDcxVklqZDFpckdrR1VPaVRzTDgiLCJ0eXAiOiJKV1QifQ.eyJhY3IiOiIwIiwiYWxsb3dlZC1vcmlnaW5zIjpbImh0dHBzOi8vYXV0aC5wcm9kLXByZXZpZXcub3BlbnNoaWZ0LmlvIiwiaHR0cHM6Ly9wcm9kLXByZXZpZXcub3BlbnNoaWZ0LmlvIl0sImFwcHJvdmVkIjp0cnVlLCJhdWQiOiJodHRwczovL3Byb2QtcHJldmlldy5vcGVuc2hpZnQuaW8iLCJhdXRoX3RpbWUiOjE1NDI3MDc3NTEsImF6cCI6Imh0dHBzOi8vcHJvZC1wcmV2aWV3Lm9wZW5zaGlmdC5pbyIsImVtYWlsIjoicm9yYWkrcHJldmlld0ByZWRoYXQuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImV4cCI6MTU0NTQ5NzcwMiwiZmFtaWx5X25hbWUiOiJSYWkiLCJnaXZlbl9uYW1lIjoiUm9oaXQiLCJpYXQiOjE1NDI3MDc3NTEsImlzcyI6Imh0dHBzOi8vYXV0aC5wcm9kLXByZXZpZXcub3BlbnNoaWZ0LmlvIiwianRpIjoiMGEzMTAwNWUtYzdjMS00Yzg5LWFmNzEtMjA2NjAxYWRiNmE0IiwibmFtZSI6IlJvaGl0IFJhaSIsIm5iZiI6MCwicGVybWlzc2lvbnMiOm51bGwsInByZWZlcnJlZF91c2VybmFtZSI6InJvcmFpLXByZXZpZXciLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX0sImJyb2tlciI6eyJyb2xlcyI6WyJyZWFkLXRva2VuIl19fSwic2Vzc2lvbl9zdGF0ZSI6IjFmYzRlNzcwLTkxNWUtNDg4ZC04YjczLTY2M2U2MTAxZjA0MSIsInN1YiI6IjcwMjk1ZWZhLWI4MzItNDRjNi1hYjM5LTJmMDMyNDY1Y2M5NiIsInR5cCI6IkJlYXJlciJ9.d83O0APtqullLeMcXw7nEUXVnpPJDNigsmRUS71Ff9Bhb6SEbA-Ugbn4DPgS1zipW92h_x-r8-CX5AZgbCDVeBkr6uJ5lqLk8wLjt3qVVTRjEDJ1J0ecOxSV1zGt5ZBmDXfQ6B-j-41AAZ2p6IEl9J-l-rB32OZfC6oXxDnPIkfGyQyG3kyyEIrfYqW7Dic17zo7vnCLD08K1hFd67UALa2YoYvUM8yyFn8-EUEkL2deQGbTggdzK68kzBOCluu9m_GW8Ly2ePa9H3RebD3VHKwnpji0-a-1HDnFk87Cz8j6SEWChD1F1AMp2-iozxsADCO9edLcAc4DEVSNSLkylQ'; const fakeResourceId = 'c0ee2b94-aee3-4c41-9e15-6fa330ce8e0b'; + const authUrl = 'http://auth.example.com/'; let service: PermissionService; + let httpTestingController: HttpTestingController; + + const fakeUser1: UserRoleData = { + assignee_id: 'user-1', + assignee_type: 'something', + inherited: false, + inherited_from: 'something', + role_name: 'role-1' + } as UserRoleData; + + const fakeUser2: UserRoleData = { + assignee_id: 'user-2', + assignee_type: 'something', + inherited: false, + inherited_from: 'something', + role_name: 'role-1' + } as UserRoleData; + + const fakeUsers: UserRoleData[] = [fakeUser1, fakeUser2]; + + const fakePermission: Permission = { + 'resource_set_name': null, + 'resource_set_id': 'c0ee2b94-aee3-4c41-9e15-6fa330ce8e0b', + 'scopes': [ + 'lima' + ], + 'exp': 1535500572 + } as Permission; + beforeEach(() => { TestBed.configureTestingModule({ + imports: [ HttpClientTestingModule ], providers: [ - PermissionService + PermissionService, + { provide: AUTH_API_URL, useValue: 'http://auth.example.com/'} ] }); service = TestBed.get(PermissionService); - localStorage.setItem('auth_token', fakeToken); + httpTestingController = TestBed.get(HttpTestingController); + localStorage.setItem('auth_token', fakeRptToken); }); - it('should return permission for a resource', () => { - const permission: Permission = service.getPermission(fakeResourceId); - expect(permission.resource_set_id).toBe(fakeResourceId); + afterEach(() => { + // After every test, assert that there are no more pending requests. + httpTestingController.verify(); }); - it('should check for scope for a resource', () => { - expect(service.hasScope(fakeResourceId, 'lima')).toBe(true); - expect(service.hasScope(fakeResourceId, 'bean')).toBe(false); + it('should return permission for a resource', (done: DoneFn) => { + service.getPermission(fakeResourceId).subscribe((permission: Permission) => { + expect(permission.resource_set_id).toBe(fakeResourceId); + done(); + }); }); - it('should return all scopes for a resource', () => { - const scopes = service.getAllScopes(fakeResourceId); - expect(scopes.length).toBe(1); - expect(scopes.includes('lima')).toBe(true); + it('should check for scope for a resource', (done: DoneFn) => { + service.hasScope(fakeResourceId, 'lima').subscribe((res: boolean) => { + expect(res).toBe(true); + done(); + }); + service.hasScope(fakeResourceId, 'bean').subscribe((res: boolean) => { + expect(res).toBe(false); + done(); + }); }); + + it('should return all scopes for a resource', (done: DoneFn) => { + service.getAllScopes(fakeResourceId).subscribe((scopes: string[]) => { + expect(scopes.length).toBe(1); + expect(scopes.includes('lima')).toBe(true); + done(); + }); + }); + + it('should audit RPT if the auth_token saved in localStorage is not valid RPT', (done: DoneFn) => { + localStorage.setItem('auth_token', fakeAuthToken); + service.getPermission(fakeResourceId).subscribe((permission: Permission) => { + expect(permission.resource_set_id).toBe(fakeResourceId); + done(); + }); + + const req = httpTestingController.expectOne(`${authUrl}token/audit?resource_id=${fakeResourceId}`); + expect(req.request.method).toBe('POST'); + req.flush({ 'rpt_token': fakeRptToken }); + }); + + it('should audit RPT if the RPT does not have permission for required resource', (done: DoneFn) => { + service.getPermission('some-resource-id').subscribe((permission: Permission) => { + expect(permission).toBeUndefined(); + done(); + }); + + const req = httpTestingController.expectOne(`${authUrl}token/audit?resource_id=some-resource-id`); + expect(req.request.method).toBe('POST'); + req.flush(''); + }); + + it('should check if findPermissionAfterAudit is called if localStorage has invalid RPT', (done: DoneFn) => { + localStorage.setItem('auth_token', fakeAuthToken); + spyOn(service, 'findPermissionAfterAudit').and.returnValue(of(fakePermission)); + service.getPermission(fakeResourceId).subscribe((permission: Permission) => { + expect(permission.resource_set_id).toBe(fakeResourceId); + done(); + }); + expect(service.findPermissionAfterAudit).toHaveBeenCalledWith(fakeResourceId); + expect(service.findPermissionAfterAudit).toHaveBeenCalledTimes(1); + }); + + it('should check if findPermissionAfterAudit is called if permission is not found', (done: DoneFn) => { + spyOn(service, 'findPermissionAfterAudit').and.returnValue(of(undefined)); + service.getPermission('some-resource-id').subscribe((permission: Permission) => { + expect(permission).toBeUndefined(); + done(); + }); + expect(service.findPermissionAfterAudit).toHaveBeenCalledWith('some-resource-id'); + expect(service.findPermissionAfterAudit).toHaveBeenCalledTimes(1); + }); + + it('should assign a role to users', (done: DoneFn) => { + service.assignRole(fakeResourceId, 'admin', ['user-1', 'user-2']).subscribe( + () => done() + ); + + const req = httpTestingController.expectOne(`${authUrl}resources/${fakeResourceId}/roles`); + expect(req.request.method).toBe('PUT'); + req.flush(''); + }); + + it('should get all users with a specific role', (done: DoneFn) => { + service.getUsersByRole(fakeResourceId, 'admin') + .subscribe((users: UserRoleData[]) => { + expect(users).toBe(fakeUsers); + done(); + }); + + const req = httpTestingController.expectOne(`${authUrl}resources/${fakeResourceId}/roles/admin`); + expect(req.request.method).toBe('GET'); + req.flush({ data: fakeUsers }); + }); + + it('should return permission from new decoded RPT after audit', (done: DoneFn) => { + service.findPermissionAfterAudit(fakeResourceId).subscribe((permission: Permission | undefined) => { + expect(localStorage.getItem('auth_token')).toBe(fakeRptToken); + expect(permission).toEqual(fakePermission); + done(); + }); + + const req = httpTestingController.expectOne(`${authUrl}token/audit?resource_id=${fakeResourceId}`); + expect(req.request.method).toBe('POST'); + req.flush({ 'rpt_token': fakeRptToken }); + }); + + it('should return undefined when no new RPT info is there after audit', (done: DoneFn) => { + localStorage.setItem('auth_token', fakeAuthToken); + service.findPermissionAfterAudit(fakeResourceId).subscribe((permission: Permission | undefined) => { + expect(localStorage.getItem('auth_token')).toBe(fakeAuthToken); + expect(permission).toEqual(undefined); + done(); + }); + + const req = httpTestingController.expectOne(`${authUrl}token/audit?resource_id=${fakeResourceId}`); + expect(req.request.method).toBe('POST'); + req.flush(''); + }); + }); diff --git a/src/app/auth/permission.service.ts b/src/app/auth/permission.service.ts index 86eac98..a478e48 100644 --- a/src/app/auth/permission.service.ts +++ b/src/app/auth/permission.service.ts @@ -1,5 +1,9 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Inject } from '@angular/core'; import { JwtHelperService } from '@auth0/angular-jwt'; +import { AUTH_API_URL } from '../shared/auth-api'; +import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; +import { Observable, iif, of } from 'rxjs'; +import { map } from 'rxjs/operators'; export type Permission = { exp: number, @@ -8,17 +12,34 @@ export type Permission = { scopes: Array }; +export type UserRoleData = { + assignee_id: string, + assignee_type: string, + inherited: boolean, + inherited_from: string, + role_name: string +}; + @Injectable() export class PermissionService { private jwtHelper: JwtHelperService = new JwtHelperService(); + private headers = new HttpHeaders({ 'Content-Type': 'application/json' }); + + constructor( + private http: HttpClient, + @Inject(AUTH_API_URL) private authApi: string + ) {} /** * Returns all the scopes a user has for a specific resource. * @param resourceId ID of a specific resource such as a Space */ - getAllScopes(resourceId: string): Array { - const permissions = this.getPermission(resourceId); - return permissions ? permissions.scopes : []; + getAllScopes(resourceId: string): Observable { + return this.getPermission(resourceId).pipe( + map((permission: Permission | undefined) => { + return permission && permission.scopes; + }) + ); } /** @@ -26,36 +47,103 @@ export class PermissionService { * @param resourceId ID of a specific resource such as a Space * @param scope the scope you want to check for. Ex - `can edit` */ - hasScope(resourceId: string, scope: string): boolean { - const permissions = this.getPermission(resourceId); - return permissions ? permissions.scopes.includes(scope) : false; + hasScope(resourceId: string, scope: string): Observable { + return this.getPermission(resourceId).pipe( + map((permission: Permission | undefined) => { + return permission && permission.scopes ? permission.scopes.includes(scope) : false; + }) + ); } /** * Returns the permission for a specific resource. + * If there is no permission info in current RPT then we need to audit new RPT token. * @param resourceId ID of a specific resource such as a Space */ - getPermission(resourceId: string): Permission | null { - const decodedToken = this.getDecodedToken(); - if (this.isValidRPT(decodedToken)) { - return decodedToken.permissions.find((permission: Permission) => permission.resource_set_id === resourceId); - } - return null; + getPermission(resourceId: string): Observable { + const permission = this.findPermission(this.getDecodedToken(), resourceId); + return iif( + () => !!permission, + of(permission), + this.findPermissionAfterAudit(resourceId) + ); } /** - * Decodes the JWT token using JwtHelperService from `angular-jwt`. + * Assign a specific role to a one or more users in a resource such as space. + * @param resourceId ID of a specific resource such as a Space + * @param roleName Role to be assigned for the resource + * @param userIDs IDs for users that need to be assigned the specified role. */ - private getDecodedToken(): any { - const token = localStorage.getItem('auth_token'); - return token ? this.jwtHelper.decodeToken(token) : ''; + assignRole(resourceId: string, roleName: string, userIDs: Array): Observable { + const url = `${this.authApi}resources/${resourceId}/roles`; + const payload = { + data: [ + { ids: userIDs, role: roleName } + ] + }; + return this.http + .put(url, payload, { headers: this.headers, responseType: 'text' }); } /** - * Checks if the decoded token is valid RPT by checking the permissions claim. - * @param token Decoded JWT token. + * Get all the users who have a speicific role. + * @param resourceId ID of a specific resource such as a Space + * @param roleName Role to get all the users for the resource */ - private isValidRPT(token: any) { - return token && token.permissions; + getUsersByRole(resourceId: string, roleName: string): Observable { + const url = `${this.authApi}resources/${resourceId}/roles/${roleName}`; + return this.http + .get<{data: UserRoleData[]}>(url, { headers: this.headers }) + .pipe( + map(res => res.data) + ); + } + + /** + * Call the Audit RPT API to get a new RPT token if the token if not an RPT + * Or if the token doesn't contain permission info for a particular resource + * @param resourceId ID of a specific resource such as a Space + */ + findPermissionAfterAudit(resourceId: string): Observable { + const url = `${this.authApi}token/audit`; + const params = new HttpParams().set('resource_id', resourceId); + return this.http + .post<{'rpt_token': string} | undefined>(url, '', { headers: this.headers, params }) + .pipe( + map((res): Permission | undefined => { + if (res) { + this.saveRPT(res.rpt_token); + return this.findPermission(this.getDecodedToken(), resourceId); + } + }) + ); + } + + /** + * Find permission info for a particular resource in decoded RPT token. + * @param token Decoded RPT token + * @param resourceId ID of a specific resource such as a Space + */ + private findPermission(token: any, resourceId: string): Permission | undefined { + return token && token.permissions && token.permissions + .find((perm: Permission): boolean => perm.resource_set_id === resourceId); + } + + /** + * Saves new token with RPT info as auth_token in localStorage. + * @param rpt RPT token returned after calling audit API + */ + private saveRPT(rpt: string): void { + localStorage.setItem('auth_token', rpt); + } + + /** + * Decodes the JWT token using JwtHelperService from `angular-jwt`. + * If the token if not valid RPT the call auditRPT to get new token. + */ + private getDecodedToken(): any { + const token = localStorage.getItem('auth_token'); + return token ? this.jwtHelper.decodeToken(token) : undefined; } }