Skip to content

Commit b33c39d

Browse files
committed
Use access token as auth header instead of idToken
1 parent e510b0d commit b33c39d

15 files changed

Lines changed: 326 additions & 247 deletions

src/app/app.component.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ describe('AppComponent', () => {
4141
azureLoggedUser$ = new Subject<AppUser>();
4242
natsLiveMessage$ = new Subject<NatsMessage | null>();
4343
natsMessageCount$ = new Subject<number>();
44-
mockAzureService = jasmine.createSpyObj('AzureService', ['initialize', 'login', 'logout', 'refreshToken'], { loggedUser$: azureLoggedUser$.asObservable() });
44+
mockAzureService = jasmine.createSpyObj('AzureService', ['initialize', 'login', 'logout', 'getAccessToken'], { loggedUser$: azureLoggedUser$.asObservable() });
4545
mockNatsService = jasmine.createSpyObj('NatsService', ['initialize', 'initializeUser', 'readMessages', 'isValidMessage'], { liveMessage$: natsLiveMessage$.asObservable(), unreadMessagesCount$: natsMessageCount$.asObservable() });
4646
mockToastService = jasmine.createSpyObj('AppShellToastService', ['showToast'], { toasts$: of([]) });
4747
mockCatalogService = jasmine.createSpyObj(
@@ -77,7 +77,7 @@ describe('AppComponent', () => {
7777
mockCatalogService.getSelectedCatalogSlug.and.returnValue(null);
7878
mockCatalogService.getSelectedCatalogDescriptor.and.returnValue({ slug: 'test-catalog', id: '1' });
7979
mockAppConfigService.getConfig.and.returnValue({ natsUrl: 'nats://localhost:4222' });
80-
mockAzureService.refreshToken.and.returnValue(Promise.resolve({ accessToken: 'new-token' } as any));
80+
mockAzureService.getAccessToken.and.returnValue(Promise.resolve('new-token'));
8181
mockProjectService.getUserProjects.and.returnValue(of([]));
8282
mockDialogRef.afterClosed.and.returnValue(dialogSubject.asObservable());
8383
mockMatDialog.open.and.returnValue(mockDialogRef);

src/app/app.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,8 @@ export class AppComponent implements OnInit, OnDestroy {
139139
// Apply optimistic UI, start with it and later apply validations after fetching projects to avoid empty parts
140140
this.projectPicker = {...this.projectPicker, label: 'Project: ', selected: currentProjectForUi.projectKey};
141141
}
142-
this.azureService.refreshToken().then((azureData) => {
143-
this.projectService.getUserProjects(azureData.accessToken).subscribe((projects: string[]) => {
142+
this.azureService.getAccessToken().then((accessToken: string) => {
143+
this.projectService.getUserProjects(accessToken).subscribe((projects: string[]) => {
144144
user.projects = projects;
145145
this.initializeNats(user);
146146
if (projects.length > 0) {

src/app/app.config.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { AppConfigService } from './services/app-config.service';
22
import { msalProviders } from './azure.config';
3-
import { ApplicationConfig, provideZoneChangeDetection, provideAppInitializer, inject } from '@angular/core';
3+
import { ApplicationConfig, provideZoneChangeDetection, provideAppInitializer, inject, Injector } from '@angular/core';
4+
import { MsalService } from '@azure/msal-angular';
5+
import { firstValueFrom } from 'rxjs';
46
import { provideRouter } from '@angular/router';
57
import { routes } from './app.routes';
68
import { provideMarkdown } from 'ngx-markdown';
@@ -30,9 +32,15 @@ export const appConfig: ApplicationConfig = {
3032
provideAppInitializer(() => {
3133
const appConfigService = inject(AppConfigService);
3234
const iconService = inject(IconRegistryService);
33-
return appConfigService.loadConfig().then(() =>
34-
iconService.registerIconsFromManifest()
35-
);
35+
const injector = inject(Injector);
36+
return appConfigService.loadConfig()
37+
.then(() => iconService.registerIconsFromManifest())
38+
.then(() => {
39+
const msalService = injector.get(MsalService);
40+
return firstValueFrom(msalService.initialize()).then(() =>
41+
firstValueFrom(msalService.handleRedirectObservable())
42+
);
43+
});
3644
}),
3745
{
3846
provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,

src/app/azure.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export function MSALGuardConfigFactory(config: AppConfigService): MsalGuardConfi
6161
return {
6262
interactionType: InteractionType.Redirect,
6363
authRequest: {
64-
scopes: [...config.getConfig()?.apiConfig?.scopes || []],
64+
scopes: [...config.getConfig()?.apiConfig?.scopes || [], 'User.Read'],
6565
},
6666
loginFailedRoute: '/login-failed',
6767
};

src/app/screens/product-action-screen/product-action-screen.component.spec.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,7 @@ describe('ProductActionScreenComponent', () => {
256256
{ name: 'param_4', type: 'string', value: '' },
257257
{ name: 'param_5', type: 'string', value: 'value_location_1' },
258258
{ name: 'param_6', type: 'singlelist', value: '' },
259-
{ name: 'catalog_item_id', type: 'string', value: 'fakeId' },
260-
{ name: 'access_token', type: 'string', value: 'fakeAccessToken' }
259+
{ name: 'catalog_item_id', type: 'string', value: 'fakeId' }
261260
]
262261
})
263262
req.flush({});
@@ -292,8 +291,7 @@ describe('ProductActionScreenComponent', () => {
292291
expect(req.request.body).toEqual({
293292
id: 'fakeAction',
294293
parameters: [
295-
{ name: 'catalog_item_id', type: 'string', value: 'fakeId' },
296-
{ name: 'access_token', type: 'string', value: 'fakeAccessToken' }
294+
{ name: 'catalog_item_id', type: 'string', value: 'fakeId' }
297295
],
298296
})
299297
req.flush({});
@@ -325,8 +323,7 @@ describe('ProductActionScreenComponent', () => {
325323
expect(req.request.body).toEqual({
326324
id: 'fakeAction',
327325
parameters: [
328-
{ name: 'catalog_item_id', type: 'string', value: 'fakeId' },
329-
{ name: 'access_token', type: 'string', value: 'fakeAccessToken' }
326+
{ name: 'catalog_item_id', type: 'string', value: 'fakeId' }
330327
],
331328
})
332329
req.flush({});
@@ -366,8 +363,7 @@ describe('ProductActionScreenComponent', () => {
366363
parameters: [
367364
{ name: 'param_1', type: 'string', value: 'value1' },
368365
{ name: 'param_2', type: 'string', value: 'value2' },
369-
{ name: 'catalog_item_id', type: 'string', value: 'fakeId' },
370-
{ name: 'access_token', type: 'string', value: 'fakeAccessToken' }
366+
{ name: 'catalog_item_id', type: 'string', value: 'fakeId' }
371367
],
372368
});
373369

@@ -413,8 +409,7 @@ describe('ProductActionScreenComponent', () => {
413409
id: 'fakeAction',
414410
parameters: [
415411
{ name: 'param_1', type: 'string', value: 'value1' },
416-
{ name: 'catalog_item_id', type: 'string', value: 'fakeId' },
417-
{ name: 'access_token', type: 'string', value: 'fakeAccessToken' },
412+
{ name: 'catalog_item_id', type: 'string', value: 'fakeId' }
418413
],
419414
});
420415

src/app/screens/product-action-screen/product-action-screen.component.ts

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { ProductActionParameterValidation } from '../../models/product-action-pa
1717
import { MatOptionModule } from '@angular/material/core';
1818
import { MatSelectModule } from '@angular/material/select';
1919
import { ProjectService } from '../../services/project.service';
20-
import { Subject, switchMap, takeUntil } from 'rxjs';
20+
import { Subject, takeUntil } from 'rxjs';
2121
import { AppProject } from '../../models/project';
2222
import { AzureService } from '../../services/azure.service';
2323
import { AppUser } from '../../models/app-user';
@@ -358,32 +358,23 @@ export class ProductActionScreenComponent implements OnInit, OnDestroy {
358358
if (this.formGroup.valid && this.action.url && this.selectedProject) {
359359
this.isExecutingAction = true;
360360
const actionUrl = this.action.url;
361-
this.azureService.getRefreshedAccessToken().pipe(
362-
switchMap((refreshedAccessToken: string) => {
363-
const actionBody = {
364-
id: this.action.id,
365-
parameters: this.actionParams.map(param => ({
366-
name: param.name,
367-
type: param.type,
368-
value: this.formGroup.getRawValue()[param.name] || this.getParamDefaultValue(param) || ''
369-
})),
370-
};
371-
actionBody.parameters.push(
372-
{
373-
name: 'catalog_item_id',
374-
type: 'string',
375-
value: this.product.id
376-
},
377-
{
378-
name: 'access_token', // ToDo: when using access token in headers, this parameter is not needed and the provisioner should retrieve it and add the param.
379-
type: 'string',
380-
value: refreshedAccessToken
381-
}
382-
);
383-
this.formGroup.disable();
384-
return this.http.post(actionUrl, actionBody);
385-
})
386-
).subscribe({
361+
const actionBody = {
362+
id: this.action.id,
363+
parameters: this.actionParams.map(param => ({
364+
name: param.name,
365+
type: param.type,
366+
value: this.formGroup.getRawValue()[param.name] || this.getParamDefaultValue(param) || ''
367+
})),
368+
};
369+
actionBody.parameters.push(
370+
{
371+
name: 'catalog_item_id',
372+
type: 'string',
373+
value: this.product.id
374+
}
375+
);
376+
this.formGroup.disable();
377+
this.http.post(actionUrl, actionBody).subscribe({
387378
next: () => {
388379
if(this.action.triggerMessage && this.action.triggerMessage !== '') {
389380
this.toastService.showToast({

src/app/screens/project-components-screen/project-components-screen.component.spec.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,7 @@ describe('ProjectComponentsScreenComponent', () => {
243243
{ name: 'caller', type: 'string', value: 'test-user' as String },
244244
{ name: 'is_deployed', type: 'boolean', value: true as Boolean },
245245
{ name: 'change_number', type: 'string', value: 'CHG1234567' as String },
246-
{ name: 'reason', type: 'string', value: 'Test reason' as String },
247-
{ name: 'access_token', type: 'string', value: 'test-access-token' as String }
246+
{ name: 'reason', type: 'string', value: 'Test reason' as String }
248247
]
249248
expect(provisionerServiceSpy.requestComponentDeletion).toHaveBeenCalledWith(
250249
'PROJECT_1',
@@ -293,8 +292,7 @@ describe('ProjectComponentsScreenComponent', () => {
293292
{ name: 'caller', type: 'string', value: 'test-user' as String },
294293
{ name: 'is_deployed', type: 'boolean', value: true as Boolean },
295294
{ name: 'change_number', type: 'string', value: 'CHG1234567' as String },
296-
{ name: 'reason', type: 'string', value: 'Test reason' as String },
297-
{ name: 'access_token', type: 'string', value: 'test-access-token' as String }
295+
{ name: 'reason', type: 'string', value: 'Test reason' as String }
298296
]
299297
expect(provisionerServiceSpy.requestComponentDeletion).toHaveBeenCalledWith(
300298
'PROJECT_1',
@@ -343,8 +341,7 @@ describe('ProjectComponentsScreenComponent', () => {
343341
{ name: 'caller', type: 'string', value: 'unknown' as String },
344342
{ name: 'is_deployed', type: 'boolean', value: true as Boolean },
345343
{ name: 'change_number', type: 'string', value: 'CHG1234567' as String },
346-
{ name: 'reason', type: 'string', value: 'Test reason' as String },
347-
{ name: 'access_token', type: 'string', value: 'test-access-token' as String }
344+
{ name: 'reason', type: 'string', value: 'Test reason' as String }
348345
]
349346
expect(provisionerServiceSpy.requestComponentDeletion).toHaveBeenCalledWith(
350347
'PROJECT_1',

src/app/screens/project-components-screen/project-components-screen.component.ts

Lines changed: 41 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -147,56 +147,47 @@ export class ProjectComponentsScreenComponent implements OnInit, OnDestroy {
147147
originalStatus = this.projectComponents[componentIndex].status;
148148
this.projectComponents[componentIndex].status = 'DELETING';
149149
}
150-
this.azureService.getRefreshedAccessToken().subscribe({
151-
next: (accessToken) => {
152-
/* eslint-disable @typescript-eslint/no-wrapper-object-types */
153-
const incidentParams: CreateIncidentParameter[] = [
154-
{
155-
name: 'cluster_location',
156-
type: 'string',
157-
value: result.location as String // NOSONAR
158-
},
159-
{
160-
name: 'caller',
161-
type: 'string',
162-
value: this.loggedUser?.username as String || 'unknown' // NOSONAR
163-
},
164-
{
165-
name: 'is_deployed',
166-
type: 'boolean',
167-
value: result.deploymentStatus as Boolean // NOSONAR
168-
169-
},
170-
{
171-
name: 'change_number',
172-
type: 'string',
173-
value: result.changeNumber as String // NOSONAR
174-
},
175-
{
176-
name: 'reason',
177-
type: 'string',
178-
value: result.reason as String // NOSONAR
179-
},
180-
{
181-
name: 'access_token',
182-
type: 'string',
183-
value: accessToken as String // NOSONAR
184-
},
185-
];
186-
/* eslint-enable @typescript-eslint/no-wrapper-object-types */
187-
this.provisionerService.requestComponentDeletion(
188-
result.projectKey,
189-
result.componentName,
190-
incidentParams
191-
).subscribe({
192-
next: () => this.onDeletionRequestSuccess(),
193-
error: (error) => {
194-
this.onDeletionRequestError(error)
195-
if (originalStatus && componentIndex !== -1) {
196-
this.projectComponents[componentIndex].status = originalStatus;
197-
}
198-
}
199-
});
150+
/* eslint-disable @typescript-eslint/no-wrapper-object-types */
151+
const incidentParams: CreateIncidentParameter[] = [
152+
{
153+
name: 'cluster_location',
154+
type: 'string',
155+
value: result.location as String // NOSONAR
156+
},
157+
{
158+
name: 'caller',
159+
type: 'string',
160+
value: this.loggedUser?.username as String || 'unknown' // NOSONAR
161+
},
162+
{
163+
name: 'is_deployed',
164+
type: 'boolean',
165+
value: result.deploymentStatus as Boolean // NOSONAR
166+
167+
},
168+
{
169+
name: 'change_number',
170+
type: 'string',
171+
value: result.changeNumber as String // NOSONAR
172+
},
173+
{
174+
name: 'reason',
175+
type: 'string',
176+
value: result.reason as String // NOSONAR
177+
}
178+
];
179+
/* eslint-enable @typescript-eslint/no-wrapper-object-types */
180+
this.provisionerService.requestComponentDeletion(
181+
result.projectKey,
182+
result.componentName,
183+
incidentParams
184+
).subscribe({
185+
next: () => this.onDeletionRequestSuccess(),
186+
error: (error) => {
187+
this.onDeletionRequestError(error)
188+
if (originalStatus && componentIndex !== -1) {
189+
this.projectComponents[componentIndex].status = originalStatus;
190+
}
200191
}
201192
});
202193
}

0 commit comments

Comments
 (0)