Skip to content

Commit

Permalink
fix: redirect URL parameters (#1071)
Browse files Browse the repository at this point in the history
Signed-off-by: Oleksii Kurinnyi <[email protected]>
  • Loading branch information
akurinnoy authored Mar 15, 2024
1 parent d2a38a8 commit f0870c1
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('Factory Acceptance Redirect', () => {
teardown(app);
});

it('should redirect "/f?url=factoryUrl"', async () => {
it('should redirect to "/load-factory?url=factoryUrl" (no `factoryLink` param)', async () => {
const factoryUrl = 'factoryUrl';
const res = await app.inject({
url: `/f?url=${factoryUrl}`,
Expand All @@ -34,20 +34,24 @@ describe('Factory Acceptance Redirect', () => {
expect(res.headers.location).toEqual(`/dashboard/#/load-factory?url=${factoryUrl}`);
});

it('should redirect "/f?factoryLink=url%3DfactoryUrl"', async () => {
it('should redirect to "/load-factory?url=factoryUrl"', async () => {
const factoryUrl = 'factoryUrl';
const res = await app.inject({
url: `/f?factoryLink=${encodeURIComponent('url=' + factoryUrl)}`,
url: `/f?factoryLink=${encodeURIComponent(btoa('url=' + factoryUrl))}`,
});
expect(res.statusCode).toEqual(302);
expect(res.headers.location).toEqual(`/dashboard/#/load-factory?url=${factoryUrl}`);
});

it('should redirect "/f?factoryLink=che-editor=che-incubator/.che-code/insiders&override.devfileFilename=my.devfile.yaml&url=factoryUr"', async () => {
it('should redirect to "/load-factory?che-editor=che-incubator%2F.che-code%2Finsiders&override.devfileFilename=my.devfile.yaml&url=factoryUrl"', async () => {
const factoryUrl = 'factoryUrl';
const res = await app.inject({
url: `/f?${encodeURIComponent(
'factoryLink=che-editor=che-incubator/.che-code/insiders&override.devfileFilename=my.devfile.yaml&url=factoryUrl',
`factoryLink=${encodeURIComponent(
btoa(
'che-editor=che-incubator/.che-code/insiders&override.devfileFilename=my.devfile.yaml&url=factoryUrl',
),
)}`,
)}`,
});
expect(res.statusCode).toEqual(302);
Expand All @@ -56,48 +60,47 @@ describe('Factory Acceptance Redirect', () => {
);
});

it('should redirect "/f?url=factoryUrl"', async () => {
it('should redirect to "/load-factory?url=factoryUrl" (with extra encoding)', async () => {
const factoryUrl = 'factoryUrl';
const res = await app.inject({
url: `/f?url=${factoryUrl}`,
url: `/f?factoryLink%3D${encodeURIComponent(btoa('url=' + factoryUrl))}`,
});
expect(res.statusCode).toEqual(302);
expect(res.headers.location).toEqual(`/dashboard/#/load-factory?url=${factoryUrl}`);
});

it('should redirect "/f?factoryLink%3Durl%3DfactoryUrl"', async () => {
it('should redirect to "/load-factory?url=factoryUrl&error_code=access_denied" (with extra encoding)', async () => {
const factoryUrl = 'factoryUrl';
const res = await app.inject({
url: `/f?factoryLink%3Durl%3D${factoryUrl}`,
});
expect(res.statusCode).toEqual(302);
expect(res.headers.location).toEqual(`/dashboard/#/load-factory?url=${factoryUrl}`);
});

it('should redirect "/f?factoryLink%3Durl%3DfactoryUrl%26error_code%3Daccess_denied"', async () => {
const factoryUrl = 'factoryUrl';
const res = await app.inject({
url: `/f?factoryLink%3Durl%3D${factoryUrl}%26error_code%3Daccess_denied`,
url: `/f?factoryLink%3D${encodeURIComponent(
btoa('url=' + factoryUrl + '&error_code=access_denied'),
)}`,
});
expect(res.statusCode).toEqual(302);
expect(res.headers.location).toEqual(
`/dashboard/#/load-factory?url=${factoryUrl}&error_code=access_denied`,
);
});

it('should redirect "/f?factoryLink=url%3Dhttps%253A%252F%252Fgithub.com%252Folexii4%252Fhelloworld.git"', async () => {
it('should redirect to "/load-factory?url=https%3A%2F%2Fgithub.com%2Folexii4%2Fhelloworld.git"', async () => {
const res = await app.inject({
url: `/f?factoryLink=url%3Dhttps%253A%252F%252Fgithub.com%252Folexii4%252Fhelloworld.git`,
url: `/f?factoryLink=${encodeURIComponent(
btoa('url=https%3A%2F%2Fgithub.com%2Folexii4%2Fhelloworld.git'),
)}`,
});
expect(res.statusCode).toEqual(302);
expect(res.headers.location).toEqual(
`/dashboard/#/load-factory?url=https%3A%2F%2Fgithub.com%2Folexii4%2Fhelloworld.git`,
);
});

it('should redirect "/f?factoryLink=override.devfileFilename%3Ddevfile2.yaml%26url%3Dhttps%253A%252F%252Fgithub.com%252Folexii4%252Fhelloworld.git"', async () => {
it('should redirect to "/load-factory?override.devfileFilename=devfile2.yaml&url=https%3A%2F%2Fgithub.com%2Folexii4%2Fhelloworld.git"', async () => {
const res = await app.inject({
url: `/f?factoryLink=override.devfileFilename%3Ddevfile2.yaml%26url%3Dhttps%253A%252F%252Fgithub.com%252Folexii4%252Fhelloworld.git`,
url: `/f?factoryLink=${encodeURIComponent(
btoa(
'override.devfileFilename=devfile2.yaml&url=https%3A%2F%2Fgithub.com%2Folexii4%2Fhelloworld.git',
),
)}`,
});
expect(res.statusCode).toEqual(302);
expect(res.headers.location).toEqual(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ export function registerFactoryAcceptanceRedirect(instance: FastifyInstance): vo
}
const query = querystring.parse(factoryLinkStr);
if (query[FACTORY_LINK_ATTR] !== undefined) {
// restore the factory link from the query string
factoryLinkStr = decodeURIComponent(query[FACTORY_LINK_ATTR] as string);
// restore the factory link from the query string as base64 encoded string
const factoryLinkBase64 = decodeURIComponent(query[FACTORY_LINK_ATTR] as string);
// decode from base64
factoryLinkStr = Buffer.from(factoryLinkBase64, 'base64').toString('utf-8');
}

const params = new URLSearchParams(factoryLinkStr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ describe('Creating steps, fetching a devfile', () => {
await jest.advanceTimersByTimeAsync(MIN_STEP_DURATION_MS);

const expectedRedirectUrl = `${protocol}${host}/f?${FACTORY_LINK_ATTR}=${encodeURIComponent(
'url=' + encodeURIComponent(factoryUrl),
btoa('url=' + encodeURIComponent(factoryUrl)),
)}`;

await waitFor(() =>
Expand All @@ -601,7 +601,7 @@ describe('Creating steps, fetching a devfile', () => {
await jest.advanceTimersByTimeAsync(MIN_STEP_DURATION_MS);

const expectedRedirectUrl = `${protocol}${host}/f?${FACTORY_LINK_ATTR}=${encodeURIComponent(
'url=' + encodeURIComponent(factoryUrl),
btoa('url=' + encodeURIComponent(factoryUrl)),
)}`;

await waitFor(() =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,8 @@ class CreatingStepFetchDevfile extends ProgressStep<Props, State> {
const redirectUrl = new URL('/f', window.location.origin);
redirectUrl.searchParams.set(
FACTORY_LINK_ATTR,
this.props.history.location.search.replace(/^\?/, ''),
// encode to base64
btoa(this.props.history.location.search.replace(/^\?/, '')),
);

OAuthService.openOAuthPage(e.attributes.oauth_authentication_url, redirectUrl.toString());
Expand Down

0 comments on commit f0870c1

Please sign in to comment.