Skip to content

Commit

Permalink
Managed Client MVP Done
Browse files Browse the repository at this point in the history
  • Loading branch information
romain-cambonie authored and Romain Cambonie committed Jul 22, 2022
1 parent 176bc22 commit 9235e9c
Show file tree
Hide file tree
Showing 25 changed files with 1,227 additions and 319 deletions.
55 changes: 52 additions & 3 deletions back/src/__tests__/unit/HttpPeConnectGateway.unit.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { ConnectionRefusedError } from "shared/src/httpClient/errors/ConnectionRefused.error";
import { createManagedAxiosInstance } from "shared/src/httpClient/ports/axios.port";
import {
createManagedAxiosInstance,
ErrorMapper,
TargetMapper,
} from "../shared/src/httpClient/ports/axios.adapter";

import {
HttpPeConnectGateway,
Expand All @@ -12,7 +16,51 @@ describe("HttpPeConnectGateway", () => {
it("should have a connexion error if the httpClient could not connect", async () => {
const testGateway = new HttpPeConnectGateway(
{} as unknown as HttpPeConnectGatewayConfig,
createManagedAxiosInstance(),
createManagedAxiosInstance(
{} as TargetMapper<"plop">,
{} as ErrorMapper<"plop">,
),
);

await expectPromiseToFailWithError(
testGateway.peAccessTokenThroughAuthorizationCode("fakeCode"),
new ConnectionRefusedError(
`Could not connect to server : ${JSON.stringify(
{
code: "ECONNREFUSED",
address: "127.0.0.1",
port: 80,
config: {
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": "axios/0.26.1",
"Content-Length": 81,
},
method: "post",
data: "grant_type=authorization_code&code=fakeCode&redirect_uri=undefined/api/pe-connect",
},
},
null,
2,
)}`,
),
);
});

it.skip("url in response config shoud match full url | baseUrl should contain target", async () => {
const testGateway = new HttpPeConnectGateway(
{} as unknown as HttpPeConnectGatewayConfig,
createManagedAxiosInstance(
{
OAUTH2_ACCESS_TOKEN_STEP_2: `https://undefined/connexion/oauth2/access_token?realm=%2Findividu`,
},
{
OAUTH2_ACCESS_TOKEN_STEP_2: {
401: () => new Error(`J'aime le paté`),
},
},
),
);

await expectPromiseToFailWithError(
Expand All @@ -31,7 +79,8 @@ describe("HttpPeConnectGateway", () => {
"Content-Length": 81,
},
method: "post",
url: "undefined/connexion/oauth2/access_token?realm=%2Findividu",
baseUrl: `OAUTH2_ACCESS_TOKEN_STEP_2`,
url: "https://undefined/connexion/oauth2/access_token?realm=%2Findividu",
data: "grant_type=authorization_code&code=fakeCode&redirect_uri=undefined/api/pe-connect",
},
},
Expand Down
39 changes: 36 additions & 3 deletions back/src/adapters/primary/config/createGateways.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,16 @@ import { CachingAccessTokenGateway } from "../../secondary/core/CachingAccessTok
import { HybridEmailGateway } from "../../secondary/emailGateway/HybridEmailGateway";
import { InMemoryEmailGateway } from "../../secondary/emailGateway/InMemoryEmailGateway";
import { SendinblueEmailGateway } from "../../secondary/emailGateway/SendinblueEmailGateway";
import { createManagedAxiosInstance } from "shared/src/httpClient/ports/axios.port";
import { HttpPeConnectGateway } from "../../secondary/HttpPeConnectGateway";
import {
createManagedAxiosInstance,
ErrorMapper,
TargetMapper,
} from "../shared/src/httpClient/ports/axios.adapter";
import {
HttpPeConnectGateway,
makeApiPeConnectUrls,
PeConnectUrlTargets,
} from "../../secondary/HttpPeConnectGateway";
import { HttpsSireneGateway } from "../../secondary/HttpsSireneGateway";
import { HttpLaBonneBoiteAPI } from "../../secondary/immersionOffer/HttpLaBonneBoiteAPI";
import { HttpPassEmploiGateway } from "../../secondary/immersionOffer/HttpPassEmploiGateway";
Expand All @@ -26,6 +34,7 @@ import { MinioDocumentGateway } from "../../secondary/MinioDocumentGateway";
import { ExcelReportingGateway } from "../../secondary/reporting/ExcelReportingGateway";
import { InMemoryReportingGateway } from "../../secondary/reporting/InMemoryReportingGateway";
import { AppConfig } from "./appConfig";
import { ManagedRedirectError } from "../helpers/redirectErrors";

const logger = createLogger(__filename);

Expand Down Expand Up @@ -56,6 +65,15 @@ export type Gateways = ReturnType<typeof createGateways> extends Promise<infer T
? T
: never;

const errorMapper: ErrorMapper<PeConnectUrlTargets> = {
PECONNECT_ADVISORS_INFO: {
401: () => new ManagedRedirectError("peConnectAdvisorForbiddenAccess"),
},
OAUTH2_ACCESS_TOKEN_STEP_2: {
400: () => new ManagedRedirectError("peConnectInvalidGrant"),
},
};

// eslint-disable-next-line @typescript-eslint/require-await
export const createGateways = async (config: AppConfig, clock: Clock) => {
logger.info({
Expand All @@ -65,6 +83,18 @@ export const createGateways = async (config: AppConfig, clock: Clock) => {
romeRepository: config.romeRepository,
});

// TODO Move from here
const httpPeConnectGatewayTargetMapper: TargetMapper<PeConnectUrlTargets> =
config.poleEmploiGateway === "HTTPS"
? makeApiPeConnectUrls({
peAuthCandidatUrl:
config.poleEmploiAccessTokenConfig.peAuthCandidatUrl,
immersionBaseUrl:
config.poleEmploiAccessTokenConfig.immersionFacileBaseUrl,
peApiUrl: config.poleEmploiAccessTokenConfig.peApiUrl,
})
: ({} as TargetMapper<PeConnectUrlTargets>);

const cachingAccessTokenGateway = [
config.laBonneBoiteGateway,
config.poleEmploiGateway,
Expand Down Expand Up @@ -110,7 +140,10 @@ export const createGateways = async (config: AppConfig, clock: Clock) => {
config.peConnectGateway === "HTTPS"
? new HttpPeConnectGateway(
config.poleEmploiAccessTokenConfig,
createManagedAxiosInstance(),
createManagedAxiosInstance(
httpPeConnectGatewayTargetMapper,
errorMapper,
),
/*new ExponentialBackoffRetryStrategy(
3_000,
15_0000,
Expand Down
25 changes: 16 additions & 9 deletions back/src/adapters/secondary/HttpPeConnectGateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export class HttpPeConnectGateway implements PeConnectGateway {
private readonly config: HttpPeConnectGatewayConfig,
private readonly httpClient: AxiosInstance,
) {
// TODO Extract and inject
this.apiPeConnectUrls = makeApiPeConnectUrls({
peAuthCandidatUrl: config.peAuthCandidatUrl,
immersionBaseUrl: config.immersionFacileBaseUrl,
Expand Down Expand Up @@ -82,12 +83,16 @@ export class HttpPeConnectGateway implements PeConnectGateway {
redirect_uri: this.apiPeConnectUrls.REGISTERED_REDIRECT_URL,
};

const response: AxiosResponse =
await getOAuthGetAccessTokenThroughAuthorizationCodeResponse(
this.httpClient,
this.apiPeConnectUrls.OAUTH2_ACCESS_TOKEN_STEP_2,
const response: AxiosResponse = await this.httpClient.post(
this.apiPeConnectUrls.OAUTH2_ACCESS_TOKEN_STEP_2,
queryParamsAsString<ExternalPeConnectOAuthGetTokenWithCodeGrantPayload>(
getAccessTokenPayload,
);
),
{
headers: headersUrlEncoded(),
timeout: AXIOS_TIMEOUT_FIVE_SECOND,
},
);

const externalAccessToken: ExternalAccessToken = validateAndParseZodSchema(
externalAccessTokenSchema,
Expand Down Expand Up @@ -137,6 +142,8 @@ export class HttpPeConnectGateway implements PeConnectGateway {
},
);

// Here

const body = this.extractAdvisorsBodyFromResponse(response);

const advisors: ExternalPeConnectAdvisor[] = validateAndParseZodSchema(
Expand Down Expand Up @@ -181,14 +188,14 @@ export class HttpPeConnectGateway implements PeConnectGateway {
}
}

type PeConnectUrlTargets =
export type PeConnectUrlTargets =
| "OAUTH2_AUTH_CODE_STEP_1"
| "OAUTH2_ACCESS_TOKEN_STEP_2"
| "REGISTERED_REDIRECT_URL"
| "PECONNECT_USER_INFO"
| "PECONNECT_ADVISORS_INFO";

const makeApiPeConnectUrls = (params: {
export const makeApiPeConnectUrls = (params: {
peAuthCandidatUrl: AbsoluteUrl;
peApiUrl: AbsoluteUrl;
immersionBaseUrl: AbsoluteUrl;
Expand Down Expand Up @@ -221,11 +228,11 @@ const headersWithAuthPeAccessToken = (

const getOAuthGetAccessTokenThroughAuthorizationCodeResponse = (
axiosInstance: AxiosInstance,
url: AbsoluteUrl,
targetUrl: PeConnectUrlTargets,
getAccessTokenPayload: ExternalPeConnectOAuthGetTokenWithCodeGrantPayload,
): Promise<AxiosResponse> =>
axiosInstance.post(
url,
targetUrl,
queryParamsAsString<ExternalPeConnectOAuthGetTokenWithCodeGrantPayload>(
getAccessTokenPayload,
),
Expand Down
Loading

0 comments on commit 9235e9c

Please sign in to comment.