diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 158f19073b..aa868c4309 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -19,6 +19,7 @@ export * from './dto/cluster-config'; export { helpers, api }; export const FACTORY_LINK_ATTR = 'factoryLink'; +export const ERROR_CODE_ATTR = 'error_code'; const common = { helpers, diff --git a/packages/dashboard-backend/src/routes/__tests__/factoryAcceptanceRedirect.spec.ts b/packages/dashboard-backend/src/routes/__tests__/factoryAcceptanceRedirect.spec.ts index 52e3efa35d..de2ddb226f 100644 --- a/packages/dashboard-backend/src/routes/__tests__/factoryAcceptanceRedirect.spec.ts +++ b/packages/dashboard-backend/src/routes/__tests__/factoryAcceptanceRedirect.spec.ts @@ -50,4 +50,24 @@ describe('Factory Acceptance Redirect', () => { expect(res.statusCode).toEqual(302); expect(res.headers.location).toEqual(`/dashboard/#/load-factory?url=${factoryUrl}`); }); + + it('should redirect "/dashboard/f?factoryLink%3Durl%3DfactoryUrl"', async () => { + const factoryUrl = 'factoryUrl'; + const res = await app.inject({ + url: `/dashboard/f?factoryLink%3Durl%3D${factoryUrl}`, + }); + expect(res.statusCode).toEqual(302); + expect(res.headers.location).toEqual(`/dashboard/#/load-factory?url=${factoryUrl}`); + }); + + it('should redirect "/dashboard/f?factoryLink%3Durl%3DfactoryUrl%26error_code%3Daccess_denied"', async () => { + const factoryUrl = 'factoryUrl'; + const res = await app.inject({ + url: `/dashboard/f?factoryLink%3Durl%3D${factoryUrl}%26error_code%3Daccess_denied`, + }); + expect(res.statusCode).toEqual(302); + expect(res.headers.location).toEqual( + `/dashboard/#/load-factory?url=${factoryUrl}&error_code=access_denied`, + ); + }); }); diff --git a/packages/dashboard-backend/src/routes/factoryAcceptanceRedirect.ts b/packages/dashboard-backend/src/routes/factoryAcceptanceRedirect.ts index b9421edf00..bcfc255d7a 100644 --- a/packages/dashboard-backend/src/routes/factoryAcceptanceRedirect.ts +++ b/packages/dashboard-backend/src/routes/factoryAcceptanceRedirect.ts @@ -10,7 +10,7 @@ * Red Hat, Inc. - initial API and implementation */ -import { FACTORY_LINK_ATTR } from '@eclipse-che/common'; +import { ERROR_CODE_ATTR, FACTORY_LINK_ATTR } from '@eclipse-che/common'; import { sanitizeSearchParams } from '@eclipse-che/common/src/helpers/sanitize'; import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'; import querystring from 'querystring'; @@ -20,15 +20,20 @@ export function registerFactoryAcceptanceRedirect(instance: FastifyInstance): vo function redirectFactoryFlow(path: string) { instance.register(async server => { server.get(path, async (request: FastifyRequest, reply: FastifyReply) => { - let queryStr = request.url.replace(path, '').replace(/^\?/, ''); + let factoryLinkStr = request.url.replace(path, '').replace(/^\?/, ''); - const query = querystring.parse(queryStr); + const query = querystring.parse(decodeURIComponent(factoryLinkStr)); if (query[FACTORY_LINK_ATTR] !== undefined) { // restore the factory link from the query string - queryStr = querystring.unescape(query[FACTORY_LINK_ATTR] as string); + factoryLinkStr = querystring.unescape(query[FACTORY_LINK_ATTR] as string); } - const sanitizedQueryParams = sanitizeSearchParams(new URLSearchParams(queryStr)); + const params = new URLSearchParams(factoryLinkStr); + if (query[ERROR_CODE_ATTR] !== undefined) { + params.append(ERROR_CODE_ATTR, querystring.unescape(query[ERROR_CODE_ATTR] as string)); + } + + const sanitizedQueryParams = sanitizeSearchParams(params); return reply.redirect('/dashboard/#/load-factory?' + sanitizedQueryParams.toString()); });