feat(admin-panel): fix disable account throws error

Because:

* we used the wrong endpoint URL

This commit:

* use profileClient in libs instead of the ad hoc one

Closes #FXA-12700
This commit is contained in:
MagentaManifold
2025-12-09 17:45:43 -05:00
parent e30cddd023
commit 2a03b49779
5 changed files with 37 additions and 73 deletions

View File

@@ -7,7 +7,8 @@ import { AuthClientFactory, AuthClientService } from './auth-client.service';
import { FirestoreFactory, FirestoreService } from './firestore.service';
import { CloudTasksFactory, CloudTasksService } from './cloud-tasks.service';
import { MetricsFactory } from 'fxa-shared/nestjs/metrics.service';
import { ProfileClientService } from './profile-client.service';
import { ProfileClient } from '@fxa/profile/client';
import { ProfileClientFactory } from './profile-client.service';
import {
EmailSenderFactory,
EmailService,
@@ -24,7 +25,7 @@ import { DatabaseService } from '../database/database.service';
CloudTasksFactory,
DatabaseService,
MetricsFactory,
ProfileClientService,
ProfileClientFactory,
EmailLinkBuilderFactory,
FxaEmailRendererFactory,
BouncesFactory,
@@ -36,7 +37,7 @@ import { DatabaseService } from '../database/database.service';
FirestoreService,
CloudTasksService,
DatabaseService,
ProfileClientService,
ProfileClient,
EmailService,
],
})

View File

@@ -1,60 +1,29 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import { Provider } from '@nestjs/common';
import { ProfileClient } from '@fxa/profile/client';
import { Test, TestingModule } from '@nestjs/testing';
import superagent from 'superagent';
import { MockConfig, MockLogService, MockMetricsFactory } from '../mocks';
import { ProfileClientFactory } from './profile-client.service';
import { AuthClientService } from './auth-client.service';
import { ProfileClientService } from './profile-client.service';
import { ConfigService } from '@nestjs/config';
describe('ProfileClient Service', () => {
let service: ProfileClient;
describe('ProfileClientService', () => {
let service: ProfileClientService;
let authClient: any;
const profileUrl = 'https://test.com';
const secretToken = 'secret123';
beforeEach(async () => {
authClient = {};
const MockConfig: Provider = {
provide: ConfigService,
useValue: {
get: jest.fn().mockImplementation((key: string) => {
if (key === 'profileServer') {
return {
url: profileUrl,
secretBearerToken: secretToken,
};
}
return null;
}),
},
};
beforeAll(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
ProfileClientService,
MockConfig,
{ provide: AuthClientService, useValue: authClient },
MockLogService,
MockMetricsFactory,
ProfileClientFactory,
],
}).compile();
service = module.get<ProfileClientService>(ProfileClientService);
service = module.get<ProfileClient>(ProfileClient);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
it('deletes cache', async () => {
const mockDelete = jest.spyOn(superagent, 'delete') as jest.Mock;
const mockSet = jest.fn().mockResolvedValue({ text: '{}' });
mockDelete.mockReturnValueOnce({
set: mockSet,
});
const result = await service.deleteCache('1234abcd');
expect(result).toStrictEqual({});
expect(mockSet).toBeCalledWith('Authorization', 'Bearer ' + secretToken);
expect(mockDelete).toBeCalledWith(profileUrl + '/cache/1234abcd');
});
});

View File

@@ -1,34 +1,28 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import { Inject, Injectable } from '@nestjs/common';
import { Provider } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import AuthClient from 'fxa-auth-client';
import superagent from 'superagent';
import { ProfileClient, ProfileClientConfig } from '@fxa/profile/client';
import { StatsD } from 'hot-shots';
import { MozLoggerService } from '@fxa/shared/mozlog';
import { AppConfig } from '../config';
import { AuthClientService } from './auth-client.service';
@Injectable()
export class ProfileClientService {
private profileServerUrl: string;
private profileServerToken: string;
constructor(
export const ProfileClientFactory: Provider<ProfileClient> = {
provide: ProfileClient,
useFactory: (
configService: ConfigService<AppConfig>,
@Inject(AuthClientService) private authAPI: AuthClient
) {
log: MozLoggerService,
statsd: StatsD
) => {
const profileConfig = configService.get(
'profileServer'
) as AppConfig['profileServer'];
this.profileServerUrl = profileConfig.url;
this.profileServerToken = profileConfig.secretBearerToken;
}
async deleteCache(uid: string) {
const result = await superagent
.delete(this.profileServerUrl + `/cache/${uid}`)
.set('Authorization', 'Bearer ' + this.profileServerToken);
return JSON.parse(result.text);
}
}
const config: ProfileClientConfig = {
...profileConfig,
serviceName: 'admin',
};
return new ProfileClient(log, statsd, config);
},
inject: [ConfigService, MozLoggerService, 'METRICS'],
};

View File

@@ -48,7 +48,7 @@ import { Knex } from 'knex';
import { AuthClientService } from '../../backend/auth-client.service';
import { CloudTasksService } from '../../backend/cloud-tasks.service';
import { FirestoreService } from '../../backend/firestore.service';
import { ProfileClientService } from '../../backend/profile-client.service';
import { ProfileClient } from '@fxa/profile/client';
import { EventLoggingService } from '../../event-logging/event-logging.service';
import { BasketService } from '../../newsletters/basket.service';
import { SubscriptionsService } from '../../subscriptions/subscriptions.service';
@@ -152,7 +152,7 @@ describe('#integration - AccountResolver', () => {
profileClient = { deleteCache: jest.fn() };
const MockProfileClient: Provider = {
provide: ProfileClientService,
provide: ProfileClient,
useValue: profileClient,
};

View File

@@ -44,7 +44,7 @@ import {
CloudTasksService,
} from '../../backend/cloud-tasks.service';
import { FirestoreService } from '../../backend/firestore.service';
import { ProfileClientService } from '../../backend/profile-client.service';
import { ProfileClient } from '@fxa/profile/client';
import { AppConfig } from '../../config';
import { DatabaseService } from '../../database/database.service';
import { uuidTransformer } from '../../database/transformers';
@@ -142,7 +142,7 @@ export class AccountResolver {
@Inject(EmailService) private emailService: EmailService,
@Inject(FirestoreService) private firestore: Firestore,
@Inject(CloudTasksService) private cloudTask: CloudTasks,
@Inject(ProfileClientService) private profileClient: ProfileClientService
@Inject(ProfileClient) private profileClient: ProfileClient
) {}
@Features(AdminPanelFeature.AccountSearch)